Thursday, 31 October 2013

Performance improvement in JSF2

Recently, I come across performance issues with JSF2. The challenge was to improve the time response for rendering the page. I am here with configuration of jsf2 parameters, which helped us to reduce the time response to render the page contents,

Set the state method as server.

        <context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>

Limit the number of views in session to small number.

    <context-param>
            <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>
            <param-value>15</param-value>
    </context-param>

Don't serialize the state, set the compress state as false
    <context-param>
        <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
        <param-value>false</param-value>
    </context-param>


    <context-param>
        <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.PRETTY_HTML</param-name>
        <param-value>false</param-value>
    </context-param>


cache the el-expressions
    <context-param>
        <param-name>org.apache.myfaces.CACHE_EL_EXPRESSIONS</param-name>
        <param-value>always</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.CHECK_ID_PRODUCTION_MODE</param-name>
        <param-value>false</param-value>
    </context-param>



below parameters are added to not refresh facelets for static pages
    <context-param>
        <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
        <param-value>-1</param-value>
    </context-param>
    <context-param>
        <param-name>facelets.REFRESH_PERIOD</param-name>
        <param-value>-1</param-value>
    </context-param>
    <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>false</param-value>
    </context-param>



Sunday, 7 July 2013

Dynamically displaying the modification of .xhtml files in JSF/MyFaces apps

To see any changes in the static files of jsf/myfaces application at run time, we need to add following context-params in the web.xml file.


<!-- below parameters are added to refresh facelets for static pages -->
    <context-param>
        <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
        <param-value>1</param-value>
    </context-param>
    <context-param>
        <param-name>facelets.REFRESH_PERIOD</param-name>
        <param-value>1</param-value>
    </context-param>
    <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
    </context-param>


Thursday, 4 July 2013

Tiles framework for Jsps

I am here with the introduction of tiles framework for Java Servlet Page (JSP)s. I am not giving the information on integration of tiles with sturts/spring here. It is simple tiles usage with jsps.

Following the steps. Considering web app is build by maven tool, tiles version is 2.1.2.

1. Maven dependencies required to include in the project object model file pom.xml


       <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-extras</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-core</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-servlet</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-jsp</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-api</artifactId>
            <version>2.1.2</version>
        </dependency>


2. Modifications in web descriptor file web.xml


    <!-- listener needs to be added for tiles -->

    <listener>
        <listener-class>org.apache.tiles.web.startup.TilesListener</listener-class>
    </listener>


    <!-- servlet needs to be added for tiles -->


    <servlet>
        <servlet-name>tiles</servlet-name>
        <servlet-class>org.apache.tiles.web.startup.TilesServlet</servlet-class>
        <init-param>
            <param-name>
                org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
            </param-name>
            <param-value>
                /WEB-INF/tiles-defs.xml
            </param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>


3. Add a tiles descriptor file tiles-defs.xml file


<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
        "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>

    <definition name="unauthorized_default" template="/appName/templates/layout.jsp">
        <put-attribute name="header" value="/appName/templates/nonAuthenticatedHeader.jsp" />
        <put-attribute name="menu" value="/appName/templates/menu.jsp" />
        <put-attribute name="body" value="/appName/templates/body.jsp" />
        <put-attribute name="footer" value="/appName/templates/footer.jsp" />
    </definition>

    <definition name="authorized_default" template="/appName/templates/layout.jsp">
        <put-attribute name="header" value="/appName/templates/header.jsp" />
        <put-attribute name="menu" value="/appName/templates/menu.jsp" />
        <put-attribute name="body" value="/appName/templates/body.jsp" />
        <put-attribute name="footer" value="/appName/templates/footer.jsp" />
    </definition>

    <definition name="authorized_home" template="/appName/templates/layout_leftmenu.jsp">
        <put-attribute name="header" value="/appName/templates/header.jsp" />
        <put-attribute name="menu" value="/appName/templates/menu.jsp" />
        <put-attribute name="leftMenu" value="/appName/templates/leftMenu.jsp" />
        <put-attribute name="body" value="/appName/templates/body.jsp" />
        <put-attribute name="footer" value="/appName/templates/footer.jsp" />
    </definition>

</tiles-definitions>




4. Template files required to add:

(a) layout.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>



      <table width="100%">
      <tr>
        <td>
          <tiles:insertAttribute name="header" />
        </td>
      </tr>
      <tr>
        <td>
          <tiles:insertAttribute name="menu" />
        </td>
      </tr>
      <tr>
        <td>
          <tiles:insertAttribute name="body" />
        </td>
      </tr>
      <tr>
        <td>
          <tiles:insertAttribute name="footer" />
        </td>
      </tr>
    </table>

(b) layout_leftmenu.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>



      <table width="100%">
      <tr>
        <td colspan="2">
          <tiles:insertAttribute name="header" />
        </td>
      </tr>
      <tr>
        <td colspan="2">
          <tiles:insertAttribute name="menu" />
        </td>
      </tr>
      <tr>
        <td width="25%">
          <tiles:insertAttribute name="leftMenu" />
        </td>
        <td>
          <tiles:insertAttribute name="body" />
        </td>
      </tr>
      <tr>
        <td align="center">
          <tiles:insertAttribute name="footer" />
        </td>
      </tr>
    </table>




5. Calling the tiles definitions on any jsp


<html>
<body>
    <div align="center" width="100%">
        <tiles:insertDefinition name="unauthorized_default">
            <tiles:putAttribute name="menu" value="/callCenter/templates/blank.jsp" />
            <tiles:putAttribute name="body" value="/callCenter/loginPage.jsp" />
        </tiles:insertDefinition>
    </div>
</body>
</html>





Wednesday, 3 July 2013

URL change while redirecting the page in JSF application

In JSF applications, url will not be changing while redirecting the page using navigation rules. However, sometimes, it might be a damn need to change the url while redirecting from one page to another page. This request can be fulfilled by following way.

In general navigation rule is defined as:

<navigation-rule>
       <from-view-id>/callCenter/crmLogin.jsp</from-view-id>
       <navigation-case>
<from-outcome>gotoMainPanel</from-outcome>
<to-view-id>/callCenter/crmMainPanel.jsp</to-view-id>
       </navigation-case>
</navigation-rule>

However, you need to add <redirect /> tag to do the url change as mentioned below.


<navigation-rule>
       <from-view-id>/callCenter/crmLogin.jsp</from-view-id>
       <navigation-case>
<from-outcome>gotoMainPanel</from-outcome>
<to-view-id>/callCenter/crmMainPanel.jsp</to-view-id>
                <redirect />
</navigation-case>
</navigation-rule>

PS: Navigation rules are mentioned in the faces-config.xml file ( inside WEB-INF directory)

Monday, 17 June 2013

Clustering of tomcat servers

I am here with brief notes on how to form a clustering on tomcat servers.

1. Set up two tomcat servers (tomcat-pri & tomcat-sec)
2. In the setup of tomcat-pri, go the conf directory, and add following content in the server.xml file in the <Host> tag.

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="6">

          <Manager className="org.apache.catalina.ha.session.BackupManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"
                   mapSendOptions="6"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="5000"
                      selectorTimeout="100"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/host/Work/servers/tomcat-pri/webapps"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="true"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

NOTE: If you observe carefully, the server.xml will have <Cluster> tag is commented out with in the <Engine> tag. However, we need to keep the <Cluster> tag with in the <Host> tag.


3. In the setup of tomcat-pri, go the conf directory, and edit the server.xml file.
Change the port information so that, you wouldn't see port already used messages in the logs.
(i) Server Port
(ii) Connector Port (two places)


4. Also add following content in the server.xml file of tomcat-sec setup.

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="6">

          <Manager className="org.apache.catalina.ha.session.BackupManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"
                   mapSendOptions="6"/>
          <!--
          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>
          -->
          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="5020"
                      selectorTimeout="100"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/host/Work/servers/apache-tomcat-7.0.41-sec/webapps"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="true"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

5. Now, deploy the web-application artifact in the directory "/tmp/war-listen"

6. Start the tomcat-pri server

7. Start the tomcat-sec server (once tomcat-pri server is started)

8. You would observer following in logs.

Jun 17, 2013 1:53:11 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Jun 17, 2013 1:53:11 PM org.apachecatalina.startup.Catalina load
INFO: Initialization processed in 524 ms
Jun 17, 2013 1:53:11 PM org.apache..coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Jun 17, 2013 1:53:11 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Jun 17, 2013 1:53:11 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.41
Jun 17, 2013 1:53:11 PM org.apache.catalina.ha.tcp.SimpleTcpCluster startInternal
INFO: Cluster is about to start
Jun 17, 2013 1:53:11 PM org.apache.catalina.tribes.transport.ReceiverBase bind
INFO: Receiver Server Socket bound to:/127.0.1.1:5000
Jun 17, 2013 1:53:11 PM org.apache.catalina.tribes.membership.McastServiceImpl setupSocket
INFO: Setting cluster mcast soTimeout to 500
Jun 17, 2013 1:53:11 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:4
Jun 17, 2013 1:53:12 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Done sleeping, membership established, start level:4
Jun 17, 2013 1:53:12 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:8
Jun 17, 2013 1:53:13 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Done sleeping, membership established, start level:8
Jun 17, 2013 1:53:13 PM org.apache.catalina.ha.deploy.FarmWarDeployer start
INFO: Cluster deployment is watching [/tmp/war-listen/] for changes.
Jun 17, 2013 1:53:13 PM org.apache.catalina.ha.deploy.FarmWarDeployer start
INFO: Cluster FarmWarDeployer started.

Thursday, 13 June 2013

Configuration of Jetty-Maven plugin to a web app

In present era development process, everybody is primarily concerned about faster development process, because of which development environment has become vital in the project implementation plan.

Jetty is the one of the light weight application server, which can be run on stand-alone or using maven plugin. I am here giving the configuration details of later one.

(One assumption here is, reader has the knowledge of Maven)

1. Add jetty-maven plugin in the plugins section of pom.xml


           <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>8.1.9.v20130131</version>
                <configuration>
                    <connectors>
                        <connector  implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
                            <port>8080</port>
                        </connector>
                    </connectors>
                    <stopPort>18080</stopPort>
    <scanIntervalSeconds>0</scanIntervalSeconds>
    <webXml>target/classes/web.xml</webXml>
    <webApp>
           <contextPath>/</contextPath>
    </webApp>
                </configuration>
                <dependencies>
                    // any dependencies required can be added here
                    // if you project has dependency on jsf, add jsf dependencies here too.
                </dependencies>
            </plugin>


2. Go to the terminal and change directory to base directory of project and run the server using below command.

mvn jetty:run

PS: Maven Options might need to be mentioned

(i) Perm Genspace attributes:
MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=256m"

(ii) Starting jetty server in debug mode with Perm Genspace attributes:
MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=256m -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=y"

Thursday, 16 May 2013

Dynamically changing the enum type ids

Have you ever felt, modelling a "STATUS" column as a enum type in any of your ticketing system?? Obviously, most of the people opt for it. I am here with one of example here...

eg:

public enum Status {
      
     OPEN("Open" , 1),
     IN_PROGRESS("In_Progress", 2),
     RESOLVED("Resolved", 3),
     CLOSE("Close", 4);

     private String name;
     private Integer id;

     private Status(String name, Integer id) {
           this.name = name;
           this.id = id;
     }

     public String getName() {
             return this.name;
     }

     public Integer getId() {
            return this.id;
     }
}

In the above mentioned enum class, whenever we change the id of the statuses due to environmental specific reasons, developers need to modify this enum class to keep the mapping between state names and the state ids.

How can we capture only state names in the enums, and ids need to be captured during the start of application dynamically??



public enum Status {

    OPEN ("Open"),

 IN_PROGRESS("In_Progress"),
     RESOLVED("Resolved"),

    CLOSE("Close");


    private String name;
    private Integer id;

    private CaseStatus(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String toString() {
        return this.name;
    }
}

Now, how do we map the ids with the states? Now, we will have a configuration class, which helps this. Of course, I have used the spring abilities here, you may use which is relevant for your scenarios.



import Status;
import models.Status;
import repositories.StatusRepository;
import org.springframework.stereotype.Service;
import play.Logger;
import sun.reflect.ReflectionFactory;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Service
public class StatusConfiguration {

    private static ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();

    @Resource
    private StatusRepository statusRepository;


    @PostConstruct
    private void initialize() {
        Map<String, Integer> statuses = this.fetchStatuses();

        if (null != statuses && !statuses.isEmpty()) {
            this.updateStatusEnum(statuses);
        }
    }

    public Map<String, Integer> fetchStatuses() {
        Map<String, Integer> statuses = null;
        try {
            List<Status> statusList = this.statusRepository.findAll();
            if (null != statusList && !statusList.isEmpty()) {
                statuses = new HashMap<String, Integer>(statusList.size());
                for (Status status : statusList) {
                    statuses.put(status.getName(), status.getId());
                }
            }
        } catch (Exception ex) {
            Logger.error("Error while fetching statuses information!", ex);
        }
        return statuses;
    }

    private void updateStatusEnum(Map<String, Integer> statuses) {
        Iterator<Map.Entry<String, Integer>> iterator = statuses.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> status = iterator.next();
            this.updateStatusEnumIds(statuses);
        }
    }

    private void updateStatusEnumIds(Map<String, Integer> statuses) {
        for (Status status : Status.values()) {
            Integer statusId = statuses.get(status.toString());
            if (null != statusId) {
                status.setId(statusId);
            }
        }
    }

}