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);
            }
        }
    }

}




Thursday, 27 December 2012

Integration of JSF2 with Spring3

Recently, I come across a situation where we need to inject spring beans into JSF managed beans. I am putting down the integration piece (mostly configuration code snippet) here which has worked for us. Configuration details for individual spring and individual jsf2 are out of scope. Only configuration details of Integration with JSF2 and Spring are mentioned below. If you have any queries, please buzz me.

Step: 1
Add below code snippet in web.xml file of web application project.


<listener>
   <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> 
</listener>

This listener class is provided by Spring, and it is mainly for use with third party servlets like JSF.

Step: 2
Add below code snippet in faces-config.xml file of web application project. This code snippet should be inside the <application> tag .


<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>

This resolves name references to Spring defined beans.


Step: 3
Add below code snippet in the spring-application-context.xml file of web application.

<context:component-scan base-package="com.company.application.web.beans" /> 

By doing this, we could able to inject the spring reference beans into jsf managed beans during the run time.

Wednesday, 5 September 2012

Using CARGO plugin in Maven building tool

Hello! Now, we will see how can we configure an application container with maven.

CARGO is the Codehaus plugin, integration with maven helps to deploy the artifacts to the container, start the application container and stop the application container and many more options. Below is the code snippet for configuration of JBoss 4.0.2 application server with the Maven.

Step: 1 - Add the below code snippet with in the <plugins></plugins> tag.
     <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven2-plugin</artifactId>
                <version>1.0</version>
               
                <configuration>
                    <!-- container configuration -->
                    <container>
                        <containerId>jboss4x</containerId>
                        <home>${app.server.home}</home>
                    </container>
                    <configuration>
                        <type>existing</type>
                        <home>${app.server.deploy.dir}</home>
                    </configuration>
                   
                    <!-- <deployer>
                        <type>installed</type>
                    </deployer>
                     -->
                    <deployables>
                        <deployable>
                          <groupId>com.company</groupId>
                          <artifactId>application</artifactId>
                          <type>war</type>
                        </deployable>
                    </deployables>
                   
                </configuration>
               
                <!-- executions of tasks by the cargo plugin -->
                <executions>
                    <execution>
                        <id>start-container</id>
                        <phase>start</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                    </execution>
                   
                    <execution>
                        <id>stop-container</id>
                        <phase>stop</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>
                </executions>
       </plugin>


In the above stated code snippet, apart from the Codehaus Cargo plugin information, container configuration, deploy-able items, deployer info and executions are mentioned.

Step: 2 - Add following code snippet as a part of <properties></properties> tag.
        <app.server.home><path-to-jboss>/jboss-4.0.2</app.server.home>
        <app.server.deploy.dir>${app.server.home}/server/default</app.server.deploy.dir>


Step: 3 - Command to deploy the artifacts to the application container.
mvn cargo:deploy

Step: 4 - Command to start the application container using maven.
mvn cargo:start

Step: 5 - Command to stop the application container using maven.
mvn cargo:stop

For more information on Cargo plugin, please visit here

How to push build artifacts to remote repository using Maven

Hello! After a bit long time, I am writing a post in this "Gyan of Java" blog. Today, we will look into few concepts of Apache Maven building tool. Have you ever come across a situation where you need to push build artifacts to a remote repository? Have you ever come across a situation where you need to push third party artifacts to a remote repository? Let's look into these now.


To answer first query, need to add a <distributionManagement> tag entries in the pom.xml of the application.

Step: 1

<!-- remote repository server info where artifacts would be pushed -->
<distributionManagement>
<repository>
<id>remoteRepo</id>
<name>Internal Nexus Repository</name>
<url>http://<remote host name>:<port name>/<remote repository path>/</url>
</repository>
</distributionManagement>


Also, need to below add entries in the settings.xml file located in M2_HOME directory.

Step: 2
   <servers>
<server>
<id>remoteRepo</id>
<username><username></username>
<password><password></password>
</server>
  </servers>


After doing these changes, build your app with following command:
mvn clean deploy

Regarding the later question, pushing third party artifacts whose pom.xml is not available, below is the code snippet.

Step: 3
mvn deploy:deploy-file -DgroupId=com.company.app -DartifactId=appName -Dversion=1.0 -Dfile=<path-to-file>/appName.jar -Dpackaging=jar -DrepositoryId=remoteRepo -Durl=http://<remote host>:<port no>/<remote repository path> -DgeneratePom=true

but before executing Step :3 command, please make sure to add entries in settings.xml file as mentioned in Step: 2