WebServer

Using mod_cluster with JBoss AS 7.1 cluster

We have seen how to create clusters in standalone, domain with multicast and unicast protocols also which have been listed below. However in this article we would be seeing how to use mod_cluster with our created clusters in both standalone and domain mode.

Following are the list of article we have created till now for creating a cluster in JBoss AS 7.1.1 Final till now

  1. How to create cluster in JBoss AS 7.1 in standalone mode?
  2. How to create cluster in JBoss AS 7.1 in domain mode?
  3. Creating TCP cluster in JBoss AS 7.1 in standalone mode?

Again we would be using JBoss AS 7.1.1.Final for this article as well so that we are all on the same page, as few things have been change from JBoss AS 7.0 to JBoss AS 7.1.

Changes taken place:

  1. AJP connector is enabled by default in standalone-ha.xml , standalone-full-ha.xml and domain.xml for ha and full-ha profile.
  2. Instead of JVMRoute, now we have to use instance-id

Using mod_cluster with JBoss AS 7.1 cluster

For this we would have to modify from both side Apache as well as JBoss AS7 side, hence lets see the configuration one at a time

Apache side configuration

Lets see what all configuration has to be made from Apache side

  1. You can configure mod_cluster from the below article, just follow the “Apache side configuration” part only
  2. How to configure mod_cluster with JBoss ?

  3. In the above article you can just add the IP_ADDRESS of the box on which Apache is running which is in the Step-3 something as shown below
  4. ############### mod_cluster Setting - STARTED ###############
    LoadModule slotmem_module modules/mod_slotmem.so
    LoadModule manager_module modules/mod_manager.so
    LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
    LoadModule advertise_module modules/mod_advertise.so
    
    Listen 1.1.1.1:80
    
    <VirtualHost 1.1.1.1:80>
    	<Directory />
    		Order deny,allow
    		Allow from all
    	</Directory>
    	<Location /mod_cluster-manager>
    		SetHandler mod_cluster-manager
    		Order deny,allow
    		Allow from all
    	</Location>
              KeepAliveTimeout 60
              ManagerBalancerName mycluster
              ServerAdvertise On
    </VirtualHost>
    ############### mod_cluster Setting - ENDED ###############
    

JBoss side configuration

Now we would see what all changes we have to be done from JBoss end in standalone and domain files

Standalone

  1. First you would have to follow all the steps given in the link – How to create cluster in JBoss AS 7.1 in standalone mode? and then make the below changes in all the standalone servers.
  2. Give a unique name in the server element, as shown below .
  3. standalone-node1

    <server name="standalone-node1" xmlns="urn:jboss:domain:1.2">
    

    standalone-node2

    <server name="standalone-node2" xmlns="urn:jboss:domain:1.2">
    
  4. As told earlier you would have to add the instance-id attribute in web subsystem as shown below in both the standalone nodes.
  5.         <subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" instance-id="${jboss.node.name}" native="false">
                <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
                <connector name="ajp" protocol="AJP/1.3" scheme="http" socket-binding="ajp"/>
                .
                .
                .
            </subsystem>
    
  6. Last you just have to add the proxy-list in the attribute in mod-cluster-config of modcluster subsystem, which would be having IP Address and Port on which your Apache server is running so that JBoss server can communicate with it, as shown below in both the standalone nodes.
  7.         <subsystem xmlns="urn:jboss:domain:modcluster:1.0">
                <mod-cluster-config advertise-socket="modcluster" proxy-list="1.1.1.1:80">
                .
                .
                .
                </mod-cluster-config>
            </subsystem>
    

If everything is configured properly you can hit the URL = http://1.1.1.1/mod_cluster-manager which would show similar below screen. Below image is showing when cluster is been made in on the same box using standalone mode

mod_cluster for Standalone on the same box

Domain

  1. First you would have to follow all the steps given in the link – How to create cluster in JBoss AS 7.1 in domain mode? and then make the below changes in your domain file.
  2. We would have to add the instance-id attribute in web subsystem as shown below in domain.xml for the respective profile ha and full-ha which is been used.
  3.             <subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" instance-id="${jboss.node.name}" native="false">
                    <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
                    <connector name="ajp" protocol="AJP/1.3" scheme="http" socket-binding="ajp"/>
                     .
                     .
                     .
                </subsystem>
    
  4. Last you just have to add the proxy-list in the attribute in mod-cluster-config of modcluster subsystem, which would be having IP Address and Port on which your Apache server is running so that JBoss server can communicate with it, as shown below in domain.xml for the respective profile ha and full-ha which is been used.
  5.         <subsystem xmlns="urn:jboss:domain:modcluster:1.0">
                <mod-cluster-config advertise-socket="modcluster" proxy-list="1.1.1.1:80">
                .
                .
                .
                </mod-cluster-config>
            </subsystem>
    

If everything is configured properly you can hit the URL = http://1.1.1.1/mod_cluster-manager which would show similar below screen. Below image is showing when cluster is been made in on the same box as well as in remote box using domain mode.

Same Box

mod_cluster for Domain mode on the same box

Remote Box

mod_cluster for Domain mode on Remote box

Testing

In all our previous article we had asked you to use one of our application called ClusterWebAp, this is the time when we would be testing if our cluster is working properly with mod_cluster configuration.

  1. Once everything thing is been configured and have been started up properly you can hit the application using Apache URL as shown below and you would see something like in the snap-shot
  2. 
    http://1.1.1.1/ClusterWebApp
    

    ClusterWebApp

  3. Suppose the first request goes to standalone-node2 , you can see there is a session-id which is been generated. Now you just have to shutdown your standalone-node2 and then click on the link Click Here to move to nextPage sessionCheck.jsp on the same page.
  4. Once you click on the link, you will notice that the request has been served by the standalone-node1 this time as node2 had been brought down, but the session-id remains the same which was created earlier having the same timestamp as shown below
  5. Session Replication

With this test it is clear that our cluster is working fine as the session replication is happening properly on JBoss using mod_cluster.

Issues you might face

If you have not given the instance-id in the domain.xml file for ha or full-ha and have a step up a cluster which is having a mod_cluster in front of them you might get the following error in the logs.

[Server:ha-server-1] 20:29:36,429 ERROR [org.jboss.modcluster.mcmp.impl.DefaultMCMPHandler] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Error [MEM: MEM: Old node still exist: {4}] sending command CONFIG to proxy 10.10.10.10:80, configuration will be reset
[Server:ha-server-2] 20:29:37,426 ERROR [org.jboss.modcluster.mcmp.impl.DefaultMCMPHandler] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Error [MEM: MEM: Can't read node: {4}] sending command STATUS to proxy 10.10.10.10:80, configuration will be reset
[Server:ha-server-2] 20:29:47,432 ERROR [org.jboss.modcluster.mcmp.impl.DefaultMCMPHandler] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Error [MEM: MEM: Old node still exist: {4}] sending command CONFIG to proxy 10.10.10.10:80, configuration will be reset
[Server:ha-server-1] 20:29:56,441 ERROR [org.jboss.modcluster.mcmp.impl.DefaultMCMPHandler] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Error [MEM: MEM: Can't read node: {4}] sending command STATUS to proxy 10.10.10.10:80, configuration will be reset

For this you just have to follow the step-2 of Domain configuration, which would fix this issue.


Custom error pages in Apache for JBoss AS7

In this article we would show a simple demonstration of using our own custom error pages which would be severed from Apache side with the static contents like image/HTML/etc files, however here we would using images and HTML pages as a repository. Custom error pages are been required by everyone in there production environments, becasue one would not like there clients to see the default error pages when some issue comes from the server side or by mistake your clients tries to access a non-existing page in your application, hence with this article you can show your own custom error pages using Apache for JBoss AS 7

We would be using the standalone mode for this article and in JBoss AS 7.1.0.CR1b version we have a different xml file called standalone-full.xml which would be used with Apache mod_jk.

Now there are few things which has to be noted here to achieve this configuration

  1. Add system-properties to give the jvmRoute
  2. Enable AJP protocol and add AJP port

Custom error pages in Apache for JBoss AS7

For this we would have to modify from both side Apache as well as JBoss AS7 side, hence lets see the configuration one at a time

Apache side configuration

Lets see what all configuration has to be made from Apache side

  1. You can configure mod_jk from the below article
  2. Configuring mod_jk to connect to JBoss
    In the following section of the above link: “Apache WebServer Configuration Part”

  3. In the above article you just have to replace the Step-8 by the following content
  4. ##### JBOSS #############
    LoadModule jk_module modules/mod_jk.so
    
    # Include mod_jk's specific configuration file
    Include conf/mod_jk.conf
    
    Listen 10.10.10.10:80
    
    # (1) Setting up the Alias for the "error" directory
    Alias /error/ "/etc/httpd/www/error/"
    
    # (2) Mapping the error codes with custom error pages
    ErrorDocument 404 /error/404_ErrorPage.html
    ErrorDocument 503 /error/MaintenancePage.html
    
    <VirtualHost 10.10.10.10:80>
    
      # (3) All the application context would go to "nodeA"
      JkMount /* nodeA
    
      # (4) Setting error code 404 for "MyApp" application
      JkMount /MyApp/* nodeA;use_server_errors=404
    
      # Static files in the examples webapp are served by Apache
      Alias /images /etc/httpd/www/html/MyApp/images
    
      # All requests go to nodeA
      JkMount /* nodeA
    
      # Serve html, jpg, png etc using httpd
      JkUnMount /*.html  nodeA
      JkUnMount /*.png  nodeA
      JkUnMount /*.jpg  nodeA
      JkUnMount /*.gif  nodeA
    
    </VirtualHost>
    ###########################
    

    Where: 10.10.10.10:80 is the “IP_ADDRESS:PORT” of your Apache box

  5. And in the Step-10 of above article replace it by the following content
  6. ##### JBOSS #############
    # Define list of workers that will be used for mapping requests
    worker.list=nodeA,status
    
    # Status worker for managing load balancer
    worker.status.type=status
    
    # Define nodeA modify the host as your host IP or DNS name.
    worker.nodeA.port=8009
    worker.nodeA.host=20.20.20.20
    worker.nodeA.type=ajp13
    worker.nodeA.ping_mode=A
    ###########################
    

    Where: 20.20.20.20 is the “binding address” of your JBoss AS7 on which it is running and “8009″ is the AJP port

So with the above configuration you can see that

  1. In the path “/etc/httpd/www/error/” would have all custom error pages with an alias “error”
  2. Mapping the custom error pages with the respective error codes
  3. All the application would be severed by “nodeA”
  4. If someone tires to access some page which is not present in the application would get our 404 custom error page.

Following are the custom error pages which we have created. Hope you like them.

MaintenancePage.html

<html>
  <head>
     <title>Middleware Magic - 503 Custom Error Page</title>
  </head>
  <body>
	<center><font color=maroon>
		<h1>Custom Maintenance Page</h1>
		<h2>Oops...You caught us down !!!.<br><br>
		<img src="/images/down.jpg"/><br><br>
		Please try after sometime...</h2><br>
		<img src="/images/MiddlewareMagic.png" width="150" height="150" />
		<h1>Middleware Magic</h1>
	        </font>
	</center>
   </body>
</html>

404_ErrorPage.html

<html>
  <head>
     <title>Middleware Magic - 404 Custom Error Page</title>
  </head>
  <body>
	<center><font color=maroon>
		<h1>404 Error - Page Not Found</h1>
		<h2>Look's like your yesterday's HANGOVER has not gone...<br><br>
		<img src="/images/hangover.jpg" width="200" height="200"/><br><br>
		Try accessing the correct page !!!</h2><br>
		<img src="/images/MiddlewareMagic.png" width="150" height="150"/>
		<h1>Middleware Magic</h1>
		</font>
	</center>
  </body>
</html>

JBoss AS7 side configuration

Lets see what all configuration has to be made from JBoss AS7 side

  1. As described earlier we would have to add the system-properties to give the jvmRoute which can be done by adding the “system-propertie” tag just after the extensions gets over, as shown below
  2. <extensions>
    .
    .
    </extensions>
    
    <!-- Below system properties tag has been added -->
    <system-properties>
    	<property name="jvmRoute" value="nodeA"/>
    </system-properties>
    
  3. By default in JBoss AS7 AJP protocol and port are not their, hence we would have to enable and add them as shown below
  4. Enabling AJP protocol

    <subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host">
    	<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
     <!-- We have to enable the AJP protocol by adding below line -->
    	<connector name="ajp" protocol="AJP/1.3" socket-binding="ajp" enabled="true"/>
    

    Adding AJP port

    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
    	<socket-binding name="http" port="8080"/>
    <!-- We have to add the AJP port by adding below line -->
    	<socket-binding name="ajp" port="8009"/>
    

The configuration has been done from both the ends, now comes the application which would be used to test the above configuration which have done.

Steps to create a test application

  1. Create a folder called MyApp
  2. In “MyApp” folder create index.jsp file and WEB-INF folder which has web.xml inside it and copy the below code in “web.xml”
  3. <web-app>
       <welcome-file-list>
           <welcome-file>index.jsp</welcome-file>
       </welcome-file-list>
    </web-app>
    
  4. In “index.jsp” file copy the below code in it
  5. <html>
    	<head>
    		<title>Middleware Magic - MyApp Static Page Test</title>
    	</head>
    	<body>
    		<center><h3><font color=maroon>This page coming from JBoss AS7....</font></h3>
    		<h1><font color=maroon>but image is coming from Apache!!! </font></h1>
    		<img src="/images/MiddlewareMagic.png"/>
    		<h1><font color=maroon>Middleware Magic </font></h1></center>
    	</body>
    </html>
    

    NOTE: You would have to give the image name with the extension which is present in the path “/etc/httpd/www/html/MyApp/images” from Apache side.

  6. Once you have done with all this you now just have to create an WAR file out of this, for that you need to be in the MyApp folder and run the below command (make sure you have setted the java/bin in your PATH). Note: you would have to give the (.) dot at last as well
  7. MyApp] jar -cvf MyApp.war .
    

Testing

Now just start your Apache and JBoss AS7 by keeping the “MyApp.war” in “/standalone/deployments” folder and hit the Apache URL with the context root of the application.


http://10.10.10.10:80/MyApp

You will notice that the JSP file is been picked up from JBoss AS7 but the image is been picked up from Apache which is getting displaced on the page, this means that the static content is been served from Apache.

Good our application is working fine, now lets try if your custom error pages work. Hence try hitting the below URL to check the custom 404 error page


http://10.10.10.10:80/MyApp/a.jsp

That’s working, let try the custom maintenance page, for that we would have to shut-down the JBoss AS7 server which would give us 503 error which means that the backend server is down, which we do sometime if we need to do a maintenance on the JBoss sever side. Thus bring down your running JBoss AS 7 server and hit the below link


http://10.10.10.10:80/MyApp


Apache as static content repository for JBoss AS7

In this article we would show a simple demonstration of using Apache as a repository for caching static contents like image/HTML/etc files, however here we would use image as a repository.This helps us in improving the performance of the backend servers as all the static contents would be served by Apache itself and all the dynamic contents can be served backend server JBoss AS7.

We would be using the standalone mode for this article and in JBoss AS 7.1.0.CR1b version we have a different xml file called standalone-full.xml which would be used with Apache mod_jk.

Now there are few things which has to be noted here to achieve this configuration

  1. Add system-properties to give the jvmRoute
  2. Enable AJP protocol and add AJP port

Configuring Apache as a static content repository

For this we would have to modify from both side Apache as well as JBoss AS7 side, hence lets see the configuration one at a time

Apache side configuration

Lets see what all configuration has to be made from Apache side

  1. You can configure mod_jk from the below article
  2. Configuring mod_jk to connect to JBoss
    In the following section of the above link: “Apache WebServer Configuration Part”

  3. In the above article you just have to replace the Step-8 by the following content
  4. ##### JBOSS #############
    LoadModule jk_module modules/mod_jk.so
    
    # Include mod_jk's specific configuration file
    Include conf/mod_jk.conf
    
    Listen	10.10.10.10:80
    NameVirtualHost	10.10.10.10:80
    
    <VirtualHost 10.10.10.10:80>
    
      # Static files in the examples webapp are served by Apache
      Alias /images /etc/httpd/www/html/MyApp/images
    
      # All requests go to nodeA
      JkMount /* nodeA
    
      # Serve html, jpg, png etc using httpd
      JkUnMount /*.png  nodeA
      JkUnMount /*.html  nodeA
      JkUnMount /*.jpg  nodeA
      JkUnMount /*.gif  nodeA
    
    </VirtualHost>
    ###########################
    

    Where: 10.10.10.10:80 is the “IP_ADDRESS:PORT” of your Apache box

  5. And in the Step-10 of above article replace it by the following content
  6. ##### JBOSS #############
    # Define list of workers that will be used for mapping requests
    worker.list=nodeA,status
    
    # Status worker for managing load balancer
    worker.status.type=status
    
    # Define nodeA modify the host as your host IP or DNS name.
    worker.nodeA.port=8009
    worker.nodeA.host=20.20.20.20
    worker.nodeA.type=ajp13
    worker.nodeA.ping_mode=A
    ###########################
    

    Where: 20.20.20.20 is the “binding address” of your JBoss AS7 on which it is running and “8009″ is the AJP port

So here you can see that in the path “/etc/httpd/www/html/MyApp/images” would have all the images for an application called “MyApp” and the paths alias is been giving as “/images” which would used in application.

JBoss AS7 side configuration

Lets see what all configuration has to be made from JBoss AS7 side

  1. As described earlier we would have to add the system-properties to give the jvmRoute which can be done by adding the “system-propertie” tag just after the extensions gets over, as shown below
  2. <extensions>
    .
    .
    </extensions>
    
    <!-- Below system properties tag has been added -->
    <system-properties>
    	<property name="jvmRoute" value="nodeA"/>
    </system-properties>
    
  3. By default in JBoss AS7 AJP protocol and port are not their, hence we would have to enable and add them as shown below
  4. Enabling AJP protocol

    <subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host">
    	<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
     <!-- We have to enable the AJP protocol by adding below line -->
    	<connector name="ajp" protocol="AJP/1.3" socket-binding="ajp" enabled="true"/>
    

    Adding AJP port

    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
    	<socket-binding name="http" port="8080"/>
    <!-- We have to add the AJP port by adding below line -->
    	<socket-binding name="ajp" port="8009"/>
    

The configuration has been done from both the ends, now comes the application which would be used to test the above configuration which have done.

Steps to create a test application

  1. Create a folder called MyApp
  2. In “MyApp” folder create index.jsp file and WEB-INF folder which has web.xml inside it and copy the below code in “web.xml”
  3. <web-app>
       <welcome-file-list>
           <welcome-file>index.jsp</welcome-file>
       </welcome-file-list>
    </web-app>
    
  4. In “index.jsp” file copy the below code in it
  5. <html>
    	<head>
    		<title>Middleware Magic - MyApp Static Page Test</title>
    	</head>
    	<body>
    		<center><h3><font color=maroon>This page coming from JBoss AS7....</font></h3>
    		<h1><font color=maroon>but image is coming from Apache!!! </font></h1>
    		<img src="/images/MiddlewareMagic.png"/>
    		<h1><font color=maroon>Middleware Magic </font></h1></center>
    	</body>
    </html>
    

    NOTE: You would have to give the image name with the extension which is present in the path “/etc/httpd/www/html/MyApp/images” from Apache side.

  6. Once you have done with all this you now just have to create an WAR file out of this, for that you need to be in the MyApp folder and run the below command (make sure you have setted the java/bin in your PATH). Note: you would have to give the (.) dot at last as well
  7. MyApp] jar -cvf MyApp.war .
    

Testing

Now just start your Apache and JBoss AS7 by keeping the “MyApp.war” in “/standalone/deployments” folder and hit the Apache URL with the context root of the application.


http://10.10.10.10:80/MyApp

You will notice that the JSP file is been picked up from JBoss AS7 but the image is been picked up from Apache which is getting displaced on the page, this means that the static content is been served from Apache.


How to Develop WebService and use @HandlerChain Annotation in JBoss AS7

Hi,

As JBoss AS7 is very new And most powerful application server with many changes in it. Here we are going to see a very simple demo of how we can develop, build, deploy and test a simple WebService application in JBoss AS7

In this example we will mainly focus on following points

Point-1). What is the use of “standalone-preview.xml” file which is present inside the directory “/home/userone/jboss-as-7.0.1.Final/standalone/configuration”

Point-2). How to use the Ant Task “org.jboss.ws.tools.ant.WSProvideTask” to build our WebService and how to use the “org.jboss.ws.tools.ant.WSConsumeTask” ant task to generate the Client side artifacts.

Point-3). Also we will discuss a little about “*.dodeploy” file as well which is required for exploded directory deployment in AS7.

Point-4). Mainly we will see the classpath and path settings required while running the ANT script to build and test our webservice.

Point-5). How to use the @HandlerChain annotation and where exactly we are supposed to place the “handler-chain.xml” file.

So here we begin the Simple WebService development.

Step1). Create a directory somewhere in your filesystem like “/home/userone/TestWebServiceAS7″ where we will place our webservice related stuffs to build. Then create another directory “src” inside “/home/userone/TestWebServiceAS7″ where we will be placing our source codes and XML files which will be used by the WebService.

Step2). Create webservice class “HandlerWS.java” as following inside the “/home/userone/TestWebServiceAS7/src” directory.

package ws;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.HandlerChain;
import javax.annotation.Resource;
import javax.xml.ws.WebServiceContext;
import java.util.Collection;
@WebService(name = "HandlerDemoService", targetNamespace="http://test.org")
@HandlerChain(file="handler-chain.xml")
// Make sure that the "handler-chain.xml" file is placed just beside the compiled webservice class
// Example: "DemoHandlerService.war/WEB-INF/classes/ws" directory.

public class HandlerWS
{
  @Resource
  WebServiceContext ctx;
  @WebMethod()
  public String getProperty(String propertyName)
  {
    System.out.println("nnt Method Invoked....String getProperty(String propertyName)");
    return "RETURNED: "+(Collection) ctx.getMessageContext().values();
  }
}

Step3). As we want to use a simple “javax.xml.ws.handler.soap.SOAPHandler” inside our webservice so we will create “HandlerOne.java” handler class inside “/home/userone/TestWebServiceAS7/src” directory as following:

package ws;
import java.util.Set;
import java.util.Collections;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPMessage;
public class HandlerOne implements SOAPHandler<SOAPMessageContext>
{
  public Set<QName> getHeaders()
  {
    return Collections.emptySet();
  }
  public boolean handleMessage(SOAPMessageContext messageContext)
  {
      System.out.println("nntHandler1-----handleMessage(SOAPMessageContext messageContext) called...");
      System.out.println("** Response: "+messageContext.getMessage().toString());
      return true;
  }
  public boolean handleFault(SOAPMessageContext messageContext)
  {
    return true;
  }
  public void close(MessageContext messageContext)
  {
  }
}

Step4). Now we will create the “handler-chain.xml” to specify what all handlers our webservice is going to use, Place this file as wll inside the “/home/userone/TestWebServiceAS7/src” directory as following:

<?xml version="1.0" encoding="UTF-8"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
  <handler-chain>
    <handler>
      <handler-class>ws.HandlerOne</handler-class>
    </handler>
  </handler-chain>
</handler-chains>

Step5). Now create a “web.xml” file deployment descriptor for our webapplication which is going to contain the above webservice description in it. Place the “web.xml” file inside “/home/userone/TestWebServiceAS7/src” directory as following:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>HandlerDemoService</servlet-name>
    <servlet-class>ws.HandlerWS</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>HandlerDemoService</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

Step6). Now create an empty file with name “DemoHandlerService.war.dodeploy” inside “/home/userone/TestWebServiceAS7/src” directory. The EMPTY ‘${war.name}.dodeploy’ tells JBoss AS7 to deploy the application, This file is needed if we want to deploy an exploded application in JBossAS7.

Step7). Now write a “TestClient.java” class as following inside “/home/userone/TestWebServiceAS7/src”, this will be our WebService client application to test the WebService as following:

package client;
import  java.net.URL;
public class TestClient
  {
     public static void main(String ar[]) throws Exception
      {
        String WSDL_URL=ar[0];
        HandlerWSService service=new HandlerWSService(new URL(WSDL_URL));
        HandlerDemoService port= service.getHandlerDemoServicePort();
        System.out.println("nt port.getProperty("something") = "+port.getProperty("something"));
      }
  }

Step7). Now the most important part, here we are going to develop “build.xml” ANT file, which will build, deploy and create clientside artifacts as wel as run the TestClient program for us, so write the following “build.xml” file inside “/home/userone/TestWebServiceAS7″ directory.

<project name="JBoss_Service" default="build">
<property name="jboss.home" value="/home/userone/jboss-as-7.0.1.Final" />
<property name="jboss.module.dir" value="${jboss.home}/modules" />
<property name="basedir" value="." />
<property name="war.name" value="DemoHandlerService.war" />
<property name="src.dir" value="src" />
<property name="client.src.dir" value="${basedir}/clientSrc" />
<property name="output.dir" value="build" />
<property name="client.dir" value="${basedir}/clientStuff" />
<property name="client.jar.name" value="HandlerDemoClient.jar" />

   <path id="jboss.classpath">
     <fileset dir="${jboss.module.dir}">
        <include name="**/*.jar"/>
     </fileset>
   </path>

   <path id="client.classpath">
     <fileset dir="${jboss.module.dir}">
        <include name="**/*.jar"/>
     </fileset>
     <fileset dir="${client.dir}">
        <include name="*.jar"/>
     </fileset>
   </path>

   <taskdef name="wsprovide" classname="org.jboss.ws.tools.ant.WSProvideTask">
       <classpath refid="jboss.classpath"/>
   </taskdef>

   <taskdef name="wsconsume" classname="org.jboss.ws.tools.ant.WSConsumeTask">
       <classpath refid="jboss.classpath"/>
   </taskdef>

        <target name="init">
           <delete dir="${output.dir}" />
           <mkdir dir="${output.dir}" />
           <mkdir dir="${output.dir}/${war.name}"/>
           <mkdir dir="${output.dir}/${war.name}/META-INF"/>
           <mkdir dir="${output.dir}/${war.name}/WEB-INF"/>
           <mkdir dir="${output.dir}/${war.name}/WEB-INF/classes"/>
           <delete dir="${client.dir}" />
           <mkdir dir="${client.dir}"/>
        </target>

    <target name="build" depends="init">
       <javac srcdir="${src.dir}" destdir="${output.dir}/${war.name}/WEB-INF/classes"  includes="*.java" excludes="TestClient.java" classpathref="jboss.classpath"/>
       <copy todir="${output.dir}/${war.name}/WEB-INF/classes/ws">
	  <fileset dir="${basedir}/src">
	      <include name="handler-chain.xml"/>
	  </fileset>
	</copy>
       <copy todir="${output.dir}/${war.name}/WEB-INF">
	  <fileset dir="${basedir}/src">
	      <include name="web.xml"/>
	  </fileset>
	</copy>
       <wsprovide
        	fork="false"
        	keep="true"
        	destdir="${output.dir}"
        	resourcedestdir="${output.dir}/${war.name}/WEB-INF/wsdl"
        	sourcedestdir="${output.dir}"
        	genwsdl="true"
        	verbose="true"
        	sei="ws.HandlerWS">
            	<classpath>
                	  <pathelement path="${output.dir}/${war.name}/WEB-INF/classes"/>
            	</classpath>
      </wsprovide>
    </target>

        <target name="deploy">
            <echo message="*******************  Deploying   *********************" />
            <echo message="********** ${war.name} to ${jboss.home}/standalone/deployments **********" />
            <copy todir="${jboss.home}/standalone/deployments/">
                <fileset dir="${output.dir}/">
                  <include name="${war.name}/**"/>
                </fileset>
            </copy>
            <echo message="The EMPTY '${war.name}.dodeploy' tells JBoss AS7 to deploy the application"/>
            <echo message="This file is needed if we want to deploy an exploded application in JBossAS7"/>
            <copy todir="${jboss.home}/standalone/deployments/">
	        <fileset dir="${basedir}/src">
	          <include name="${war.name}.dodeploy"/>
	        </fileset>
	    </copy>
            <echo message="*******************  Deployed Successfully   *********************" />
        </target>

        <target name="post-deploy" depends="deploy">
            <echo message="*******************  NOTE  *********************" />
            <echo message="***** You should be able to access your WSDL using Browser now *****" />
            <echo message="                 http://localhost:8080/DemoHandlerService?wsdl          " />
        </target>

        <target name="client" depends="post-deploy">
             <wsconsume
                      fork="true"
                      keep="true"
                      destdir="${client.dir}"
                      sourcedestdir="${client.dir}"
                      package="client"
                      wsdlLocation="service.wsdl"
                      wsdl="http://localhost:8080/DemoHandlerService?wsdl">
            </wsconsume>
            <jar jarfile="${client.dir}/${client.jar.name}" basedir="${client.dir}" compress="true" />
       </target>

        <target name="run" depends="client">
            <javac srcdir="${src.dir}" destdir="${client.dir}"  includes="TestClient.java" classpathref="client.classpath"/>
            <java classname="client.TestClient"  >
	        <classpath>
	            <pathelement location="${client.dir}"/>
	            <path refid="client.classpath"/>
	        </classpath>
                <arg value="http://localhost:8080/DemoHandlerService?wsdl"/>
            </java>
        </target>
</project>

NOTE: The only change in the above file you need to do is to change the “jboss.home” directory path in the second line of the above script
to point to your own JBoss AS7 directory.

Step8). Now before running your ANT script to build and deploy the above webservice you should have the ANT as well as JAVA set in the $PATH variable of the Shell / command prompt as following:

For Unix Based OS:
export PATH=/home/userone/jdk1.6.0_21/bin:/home/userone/org.apache.ant_1.6.5/bin:$PATH

For Windows Based OS:
set PATH=C:/jdk1.6.0_21/bin;C:/org.apache.ant_1.6.5/bin;%PATH%

Step9). Now once the PATH is set In the command/Shell prompt you can move inside the directory “/home/userone/TestWebServiceAS7″ and then run the ant to build the webservice. by running the command “ant build”

ant build

Buildfile: build.xml
init:
    [mkdir] Created dir: /home/userone/TestWebServiceAS7/build
    [mkdir] Created dir: /home/userone/TestWebServiceAS7/build/DemoHandlerService.war
    [mkdir] Created dir: /home/userone/TestWebServiceAS7/build/DemoHandlerService.war/META-INF
    [mkdir] Created dir: /home/userone/TestWebServiceAS7/build/DemoHandlerService.war/WEB-INF
    [mkdir] Created dir: /home/userone/TestWebServiceAS7/build/DemoHandlerService.war/WEB-INF/classes
    [mkdir] Created dir: /home/userone/TestWebServiceAS7/clientStuff

build:
    [javac] Compiling 1 source file to /home/userone/TestWebServiceAS7/build/DemoHandlerService.war/WEB-INF/classes
     [copy] Copying 1 file to /home/userone/TestWebServiceAS7/build/DemoHandlerService.war/WEB-INF/classes/ws
     [copy] Copying 1 file to /home/userone/TestWebServiceAS7/build/DemoHandlerService.war/WEB-INF
[wsprovide] Generating from endpoint: ws.HandlerWS
[wsprovide] log4j:WARN No appenders could be found for logger (org.apache.cxf.common.logging.LogUtils).
[wsprovide] log4j:WARN Please initialize the log4j system properly.
[wsprovide] log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
[wsprovide] java2ws -s /home/userone/TestWebServiceAS7/build -classdir /home/userone/TestWebServiceAS7/build -d /home/userone/TestWebServiceAS7/build/DemoHandlerService.war/WEB-INF/wsdl -verbose -wsdl -cp :::::::: -wrapperbean -createxsdimports ws.HandlerWS
[wsprovide] java2ws - Apache CXF 2.4.1

Step10). Now to deploy and run the TestClient you can run the following command “ant run”

deploy:
     [echo] *******************  Deploying   *********************
     [echo] ********** DemoHandlerService.war to /home/userone/jboss-as-7.0.1.Final/standalone/deployments **********
     [copy] Copying 5 files to /home/userone/jboss-as-7.0.1.Final/standalone/deployments
     [echo] The EMPTY 'DemoHandlerService.war.dodeploy' tells JBoss AS7 to deploy the application
     [echo] This file is needed if we want to deploy an exploded application in JBossAS7
     [copy] Copying 1 file to /home/userone/jboss-as-7.0.1.Final/standalone/deployments
     [echo] *******************  Deployed Successfully   *********************

post-deploy:
     [echo] *******************  NOTE  *********************
     [echo] ***** You should be able to access your WSDL using Browser now *****
     [echo]                  http://localhost:8080/DemoHandlerService?wsdl

client:
[wsconsume] Consuming wsdl: http://localhost:8080/DemoHandlerService?wsdl
[wsconsume] log4j:WARN No appenders could be found for logger (org.apache.cxf.common.logging.LogUtils).
[wsconsume] log4j:WARN Please initialize the log4j system properly.
[wsconsume] log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
      [jar] Building jar: /home/userone/TestWebServiceAS7/clientStuff/HandlerDemoClient.jar

run:
    [javac] Compiling 1 source file to /home/userone/TestWebServiceAS7/clientStuff
     [java] Nov 3, 2011 1:49:45 AM client.HandlerWSService <clinit>
     [java] INFO: Can not initialize the default wsdl from service.wsdl
     [java] log4j:WARN No appenders could be found for logger (org.apache.cxf.common.logging.LogUtils).
     [java] log4j:WARN Please initialize the log4j system properly.
     [java] log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

     [java] 	 port.getProperty("something") = RETURNED: [{http://test.org}HandlerDemoServicePort, [MessageInfo INPUT: {http://test.org}getProperty], {Accept=[*/*], cache-control=[no-cache], connection=[keep-alive], Content-Length=[194], content-type=[text/xml; charset=UTF-8], host=[localhost:8080], pragma=[no-cache], SOAPAction=[""], user-agent=[Apache CXF 2.4.1]}, null, stem, http://localhost:8080/DemoHandlerService, {http://test.org}HandlerDemoService, /DemoHandlerService, org.apache.catalina.connector.RequestFacade@2991d3fe, null, org.apache.catalina.core.StandardWrapperFacade@4c81ff8e, */*, [], /DemoHandlerService, /DemoHandlerService/, {http://test.org}HandlerWSService, [], [org.apache.cxf.transport.https.CertConstraintsInterceptor@481beb90], UTF-8, null, org.jboss.wsf.stack.cxf.HttpServletResponseExt@6ab0eadf, org.apache.cxf.transport.http.AbstractHTTPDestination$2@50c0d32, true, null, true, POST, true, {http://test.org}getProperty, org.apache.cxf.transport.servlet.ServletDestination@23cbb431, false, http://localhost:8080/DemoHandlerService?wsdl, {}, org.apache.cxf.service.model.BindingMessageInfo@12a30f53, org.apache.catalina.core.ApplicationContextFacade@f431bb4, text/xml; charset=UTF-8]

Some Issues which you may face

Issue-1).

Classpath might not be set properly so you may see the following kind of exception:

build.xml:27: taskdef class org.jboss.ws.tools.ant.WSProvideTask cannot be found
OR
build.xml:27: taskdef class org.jboss.ws.tools.ant.WSConsumeTask cannot be found

So make sure that the JAR “jboss-as-7.0.1.Final/modules/org/jboss/ws/tools/common/main/jbossws-common-tools-1.0.0.Beta1.jar” is added in the classpath or better if you include the CLasspath setting in your ant file like following to include all the required JARs present inside the “modules” directory of JBoss:

   <property name="jboss.module.dir" value="/home/userone/jboss-as-7.0.1.Final/modules" />
   <path id="jboss.classpath">
     <fileset dir="${jboss.module.dir}">
        <include name="**/*.jar"/>
     </fileset>
   </path>

Issue-2).

While deploying your above webservice on JBoss AS7 you may see following kind of Exception trace:

 11:33:20,677 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-7) Starting deployment of "DemoHandlerService.war"
11:33:20,697 INFO  [org.jboss.as.jpa] (MSC service thread 1-1) added javax.persistence.api dependency to DemoHandlerService.war
11:33:20,703 WARN  [org.jboss.as.ee.component.ResourceInjectionAnnotationParsingProcessor] (MSC service thread 1-3) Can't handle @Resource for ENC name: ws.HandlerWS/ctx on class ws.HandlerWS since it's missing a "lookup" (or "mappedName") value and isn't of any known type
11:33:20,743 INFO  [org.jboss.web] (MSC service thread 1-8) registering web context: /DemoHandlerService
11:33:20,776 INFO  [org.jboss.as.server.controller] (DeploymentScanner-threads - 2) Deployed "DemoHandlerService.war"
11:33:45,070 INFO  [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/DemoHandlerService]] (http-localhost-127.0.0.1-8080-1) Marking servlet HandlerDemoService as unavailable
11:33:45,070 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/DemoHandlerService].[HandlerDemoService]] (http-localhost-127.0.0.1-8080-1) Allocate exception for servlet HandlerDemoService: java.lang.ClassCastException: ws.HandlerWS cannot be cast to javax.servlet.Servlet
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1156) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:952) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:188) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:139) [jboss-as-web-7.0.1.Final.jar:7.0.1.Final]
	at org.jboss.as.web.NamingValve.invoke(NamingValve.java:57) [jboss-as-web-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:154) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:667) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:952) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
	at java.lang.Thread.run(Thread.java:619) [:1.6.0_21]

11:33:45,841 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-4) Stopped deployment DemoHandlerService.war in 27ms
11:33:45,843 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-4) Starting deployment of "DemoHandlerService.war"
11:33:45,852 INFO  [org.jboss.as.jpa] (MSC service thread 1-5) added javax.persistence.api dependency to DemoHandlerService.war
11:33:45,857 WARN  [org.jboss.as.ee.component.ResourceInjectionAnnotationParsingProcessor] (MSC service thread 1-5) Can't handle @Resource for ENC name: ws.HandlerWS/ctx on class ws.HandlerWS since it's missing a "lookup" (or "mappedName") value and isn't of any known type
11:33:45,915 INFO  [org.jboss.web] (MSC service thread 1-4) registering web context: /DemoHandlerService
11:33:45,960 INFO  [org.jboss.as.server.controller] (DeploymentScanner-threads - 2) Replaced deployment "DemoHandlerService.war" with deployment "DemoHandlerService.war"

The above exception is an indication that the required WebService stack might not be loaded in yur JBoss Profile. So we will need to make sure that to start the JBoss AS7 we use the “standalone-preview.xml” rather than using “standalone.xml”, Because the “standalone-preview.xml” file has the configuration to load the WebService Stack of JBoss.
So make sure that you start your JBoss like following from directory “jboss-as-7.0.1.Final/bin”:

./standalone.sh --server-config=standalone-preview.xml

Issue-3).

If you have not placed the “handler-chain.xml” file at the right place then you may see following kind of Exception while deploying your WebService which uses @HandlerChain annotation:

11:40:44,656 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-5) MSC00001: Failed to start service jboss.deployment.unit."DemoHandlerService.war".INSTALL: org.jboss.msc.service.StartException in service jboss.deployment.unit."DemoHandlerService.war".INSTALL: Failed to process phase INSTALL of deployment "DemoHandlerService.war"
	at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:121)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1765)
	at org.jboss.msc.service.ServiceControllerImpl$ClearTCCLTask.run(ServiceControllerImpl.java:2291)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_21]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_21]
	at java.lang.Thread.run(Thread.java:619) [:1.6.0_21]
Caused by: javax.xml.ws.WebServiceException: javax.xml.ws.WebServiceException: Could not find the handler configuration file handler-chain.xml specified by @HandlerChain annotation
	at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:350)
	at org.jboss.wsf.stack.cxf.deployment.EndpointImpl.doPublish(EndpointImpl.java:88)
	at org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:239)
	at org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:509)
	at org.jboss.wsf.stack.cxf.configuration.NonSpringBusHolder.configure(NonSpringBusHolder.java:116)
	at org.jboss.wsf.stack.cxf.deployment.aspect.BusDeploymentAspect.startDeploymentBus(BusDeploymentAspect.java:109)
	at org.jboss.wsf.stack.cxf.deployment.aspect.BusDeploymentAspect.start(BusDeploymentAspect.java:132)
	at org.jboss.as.webservices.deployers.AspectDeploymentProcessor.internalDeploy(AspectDeploymentProcessor.java:79)
	at org.jboss.as.webservices.deployers.TCCLDeploymentProcessor.deploy(TCCLDeploymentProcessor.java:42)
	at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:115)
	... 5 more
Caused by: javax.xml.ws.WebServiceException: Could not find the handler configuration file handler-chain.xml specified by @HandlerChain annotation
	at org.apache.cxf.jaxws.handler.AnnotationHandlerChainBuilder.buildHandlerChainFromClass(AnnotationHandlerChainBuilder.java:88)
	at org.apache.cxf.jaxws.handler.AnnotationHandlerChainBuilder.buildHandlerChainFromClass(AnnotationHandlerChainBuilder.java:284)
	at org.apache.cxf.jaxws.JaxWsServerFactoryBean.buildHandlerChain(JaxWsServerFactoryBean.java:237)
	at org.apache.cxf.jaxws.JaxWsServerFactoryBean.initializeResourcesAndHandlerChain(JaxWsServerFactoryBean.java:216)
	at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:203)
	at org.apache.cxf.jaxws.EndpointImpl.getServer(EndpointImpl.java:433)
	at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:322)
	... 14 more

11:40:44,889 INFO  [org.jboss.as.server.controller] (DeploymentScanner-threads - 1) Deployment of "DemoHandlerService.war" was rolled back with failure message {"Failed services" => {"jboss.deployment.unit."DemoHandlerService.war".INSTALL" => "org.jboss.msc.service.StartException in service jboss.deployment.unit."DemoHandlerService.war".INSTALL: Failed to process phase INSTALL of deployment "DemoHandlerService.war""},"Services with missing/unavailable dependencies" => ["jboss.naming.context.java.comp.DemoHandlerService.DemoHandlerService.DemoHandlerService.Validator missing [ jboss.naming.context.java.module.DemoHandlerService.DemoHandlerService ]","jboss.naming.context.java.comp.DemoHandlerService.DemoHandlerService.DemoHandlerService.ValidatorFactory missing [ jboss.naming.context.java.module.DemoHandlerService.DemoHandlerService ]"]}
11:40:44,891 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-2) Stopped deployment DemoHandlerService.war in 3ms
11:40:44,893 ERROR [org.jboss.as.deployment] (DeploymentScanner-threads - 2) {"Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-2" => {"Failed services" => {"jboss.deployment.unit."DemoHandlerService.war".INSTALL" => "org.jboss.msc.service.StartException in service jboss.deployment.unit."DemoHandlerService.war".INSTALL: Failed to process phase INSTALL of deployment "DemoHandlerService.war""},"Services with missing/unavailable dependencies" => ["jboss.naming.context.java.comp.DemoHandlerService.DemoHandlerService.DemoHandlerService.Validator missing [ jboss.naming.context.java.module.DemoHandlerService.DemoHandlerService ]","jboss.naming.context.java.comp.DemoHandlerService.DemoHandlerService.DemoHandlerService.ValidatorFactory missing [ jboss.naming.context.java.module.DemoHandlerService.DemoHandlerService ]"]}}}

So to avoid the above kind of Exception make sure that the “handler-chain.xml” file is placed just beside the compiled webservice class. In this case Example: “DemoHandlerService.war/WEB-INF/classes/ws” directory.
.
.
Thanks
Middleware Magic Team


How to configure mod_cluster with JBoss ?


Like mod_jk, mod_cluster is also a httpd based load balancer which uses a communication channel to forward requests from the httpd to one of a set of application server nodes. So the question comes Why mod_cluster ? To answer this question we will let you know few advantages of mod_cluster over mod_jk and other httpd-based load balancers.

Hence in this article we would share you why should one use mod_cluster ? and how to configure mod_cluster with JBoss ? Hopping all our subscribers would take the advantage of this article and would help them to choose which is the best option for httpd based load balancer for there requirement.

Why should one use mod_cluster ?

  • Dynamic configuration:
  • Server side load balance:
  • AJP is optional:
  • Web application lifecycle control:

To know all the Advantages and Great features of mod_cluster refer to :

Steps to configure mod_cluster with JBoss

I have divided this configuration into two parts to, so that it would be much more easier to understand follow the steps. Here the following are the two parts

  1. Apache side configuration
  2. JBoss side configuration

Apache side configuration

  1. Download the required binaries for your OS from below link, example for RHEL x64 bit its [dynamic libraries linux2-x64]
  2. http://www.jboss.org/mod_cluster/downloads/1-1-0.html

  3. Copy following .so files to your “<Apache_Home>/modules” folder.
  4. mod_proxy.so
    mod_proxy_ajp.so
    mod_slotmem.so
    mod_manager.so
    mod_proxy_cluster.so
    mod_advertise.so

  5. Edit your httpd.conf (i.e. /conf/http.conf) and add following lines at the bottom of the file. However this virtualhost setting is a sample, you might have to make some changes as per your own environment.
  6. ############### mod_cluster Setting - STARTED ###############
    LoadModule slotmem_module modules/mod_slotmem.so
    LoadModule manager_module modules/mod_manager.so
    LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
    LoadModule advertise_module modules/mod_advertise.so
    <VirtualHost *:80>
    	<Directory />
    		Order deny,allow
    		Allow from all
    	</Directory>
    	<Location /mod_cluster_manager>
    		SetHandler mod_cluster-manager
    		Order deny,allow
    		Allow from all
    	</Location>
    	KeepAliveTimeout 60
    	MaxKeepAliveRequests 0
    	ManagerBalancerName testcluster
    	AdvertiseFrequency 5
    </VirtualHost>
    ############### mod_cluster Setting - ENDED ###############
    

    NOTE:

    You have to COMMENT the follwoing module (i.e. mod_proxy_balancer.so) in “httpd.conf” file, or else you would get error while starting your Apache, this is been done because we are now using mod_proxy_cluster.so instead of mod_proxy_balancer.so

    #LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
    
  7. Restart Apache.
  8. NOTE:

    You have to do the following things before starting the APACHE

    Command:

    setenforce 0
    

    The above command will disable SE Linux for your current running session. However if you want to disable it permanently then follow the below steps

    vi /etc/selinux/config
    
    #SELINUX=enforcing (comment this line and add the below line)
    SELINUX=disabled
    

    May be this would need to restart your system, this way you will be sure that the changes have taken place.

JBoss side configuration

  1. Copy “mod-cluster.sar” from “/home/testusr/AS6/mod_cluster” to “/server/cluster_node1/deploy”
  2. Edit “mod-cluster-jboss-beans.xml” from “<JBOSS_HOME>/server/cluster_node1/deploy/mod-cluster.sar/META-INF/mod-cluster-jboss-beans.xml” so that it has following.
  3. BELOW

    <bean name="HAModClusterConfig" class="org.jboss.modcluster.config.ha.HAModClusterConfig" mode="On Demand">
    
    <!-- START Comma separated list of address:port listing the httpd servers where mod_cluster is running. -->
        <property name="proxyList">${jboss.modcluster.proxyList:localhost:80}</property>
        <property name="domain">${jboss.Domain:DefaultDomain}</property>
    <!-- END Comma separated list of address:port listing the httpd servers where mod_cluster is running. -->
    
  4. Edit “server.xml” from “/server/all/deploy/jbossweb.sar/server.xml” so that it has following lines.
  5. <!-- START mod_cluster setting -->
         <Listener  className="org.jboss.web.tomcat.service.deployers.MicrocontainerIntegrationLifecycleListener" delegateBeanName="HAModClusterService"/>
    <!-- END mod_cluster setting -->
    

    NOTE:
    Make sure you add above line BEFORE/ABOVE

       <Service name="jboss.web">
    

    and

    <!-- START mod_cluster setting -->
         <Engine name="jboss.web" defaultHost="localhost" jvmRoute="${jboss.jvmRoute}">
    <!-- END mod_cluster setting -->
    

    NOTE:
    Make sure you replace above line instead of this line

          <Engine name="jboss.web" defaultHost="localhost">
    
  6. Edit “jboss-beans.xml” (/server/all/deploy/jbossweb.sar/META-INF/jboss-beans.xml) and add the below line in “bean” element
  7. <depends>HAModClusterService</depends>
    

Command to start the servers

Below is the command to start the serves in a cluster which are on the same Box/Physical Machine

NODE-1:

./run.sh -c cluster_node1 -g ClusterA -u 239.255.100.101 -b localhost -Djboss.Domain=test -Djboss.messaging.ServerPeerID=1 -Djboss.service.binding.set=ports-01 -Djboss.jvmRoute="node1"

NODE-2:

./run.sh -c cluster_node2 -g ClusterA -u 239.255.100.101 -b localhost -Djboss.Domain=test -Djboss.messaging.ServerPeerID=2 -Djboss.service.binding.set=ports-02 -Djboss.jvmRoute="node2"

URL to hit


http://localhost/mod_cluster_manager

Regards,

Middleware Magic


Configuring mod_jk to connect to JBoss

Hi,

Here is a simple step by step procedure to connect to JBoss instance for load balancing purpose through apache webserver. In most of the production environments this is the most common need.

The prerequisite for this exercise is to have the the Apache WebServer installed already in your Machine and the JBoss should be installed in your environment. The “mod_jk” module can be downloaded later to work on this setup. If you want to download the apache software and the mod_jk then you can refer to the link mentioned in the Step6):

JBoss Cluster Creation/Configuration Part:

Step1). As “all” and “production” profiles which are present inside the “E:jboss-AS6-5.1jboss-asserver” location are by default clustering enabled so you can chose any one of them to create your own clustered node. In this exercise we will use “all” profile to create JBoss Clusters.

So first copy the “all” profile and paste it in the same location “E:jboss-AS6-5.1jboss-asserver” with some different name like “all_node1″ and “all_node2″. like this your 2 JBoss Clustered Nodes are ready.

Step2). Now open the “server.xml” file present inside the “E:jboss-AS6-5.1jboss-asserverall_node1deployjbossweb.sar” location and then add the “jvmRoute” attribute of the Engine Tag like following:By default the line which you are going to change will look like following:
=============By default it will look like below==================

<Engine name="jboss.web" defaultHost="localhost">

=============After Change it will look like below==================

<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node1">

Step3). Same changes we need to do for “all_node2″ profile as well. So open the “server.xml” file present inside the “E:jboss-AS6-5.1jboss-asserverall_node2deployjbossweb.sar” location and then add the “jvmRoute” attribute of the Engine Tag like following:
=============By default it will look like below==================

<Engine name="jboss.web" defaultHost="localhost">

=============After Change it will look like below==================

<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node2">

Why We need “jvmRoute”?

jvmRoute Identifier must be used in load balancing scenarios to enable session affinity. The identifier, which must be unique across all Tomcat 6 servers which participate in the cluster, will be appended to the generated session identifier, therefore allowing the front end proxy to always forward a particular session to the same Tomcat 6 OR JBoss instance.

More information regarding this attribute can be found in the following link:
http://tomcat.apache.org/tomcat-6.0-doc/config/engine.html#Common_Attributes

Step4). Also please make sure that the AJP Connector Tag is uncommented in “E:jboss-AS6-5.1jboss-asserverall_node2deployjbossweb.sarserver.xml” file for both “all_node1″ & “all_node2″ profiles, Because the communication between Apache and JBoss will happen through this AJP connector port. Like following:

      <!-- A AJP 1.3 Connector on port 8009 -->
      <Connector protocol="AJP/1.3" port="8009" address="${jboss.bind.address}"
         redirectPort="8443" />

Step5). Now start Both the JBoss Instances by running the following command from the following dir “E:jboss-AS6-5.1jboss-as\bin”:

run.bat -c all_node1 -b 0.0.0.0 -g ClusterA -Djboss.service.binding.set=ports-01 -Djboss.messaging.ServerPeerID=1
run.bat -c all_node2 -b 0.0.0.0 -g ClusterA -Djboss.service.binding.set=ports-02 -Djboss.messaging.ServerPeerID=2

Here following are the meaning of the flags which we have used :
-c = The jboss profile which we want to start

-g = The name of the cluster. The same name of the cluster should be used by the profiles which want to join the same cluster formation.

-Djboss.service.binding.set = The advantage of this way is you don’t have to take (and maintain) a separate copy of the all folder if you want to, say, start up multiple instances of JBoss running as a cluster. For more information on this system property please refer to the following : http://community.jboss.org/wiki/ConfigurePorts

-Djboss.messaging.ServerPeerID = Each node must have a unique ServerPeerID for clustering to work!. It can be any unique integer value among all the cluster members. Means every cluster node should have a unique peer ID.

-b = The bind address in which you want to run your profile. o.o.o.o represents it will listen to all the IP Addresses associated with that box. better if we can specify a particular “IP Address” or “localhost” there rather than using “0.0.0.0″

So suppose if you are running your JBoss on two separate physical boxes which has different IP Addresses like 10.10.10.10 and 20.20.20.20 then please run the servers like following

run.bat -c all_node1 -b 10.10.10.10 -g ClusterA -Djboss.service.binding.set=ports-01 -Djboss.messaging.ServerPeerID=1
run.bat -c all_node2 -b 20.20.20.20 -g ClusterA -Djboss.service.binding.set=ports-02 -Djboss.messaging.ServerPeerID=2

Apache WebServer Configuration Part:

Step6). Download & Install the apache webserver from the following link along with the “mod_jk” file:
http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/clustering-http.html#clustering-http-modjk

Step7). Now paste the “mod_jk.so” file inside the modules directory of your apache which may be “C:Program FilesApache GroupApache2modules”

Step8). Now add the following line of configuration somewhere at the bottom inside your “C:Program FilesApache GroupApache2confhttpd.conf” file to include the mod_jk configuration file:

##### JBOSS #############
LoadModule jk_module modules/mod_jk.so

# Include mod_jk's specific configuration file
Include conf/mod_jk.conf
###########################

Step9). Now create a file with name “mod_jk.conf” inside the directory “C:Program FilesApache GroupApache2conf” as following:

##### JBOSS #############
# Load mod_jk module
# Specify the filename of the mod_jk lib
LoadModule jk_module modules/mod_jk.so

# Where to find workers.properties
JkWorkersFile conf/workers.properties

# Where to put jk logs
JkLogFile logs/mod_jk.log

# Set the jk log level [debug/error/info]
JkLogLevel info

# Select the log format
JkLogStampFormat  "[%a %b %d %H:%M:%S %Y]"

# JkOptions indicates to send SSK KEY SIZE
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories

# JkRequestLogFormat
JkRequestLogFormat "%w %V %T"

# Mount your applications
JkMount /* failover

# You can use external file for mount points.
# It will be checked for updates each 60 seconds.
# The format of the file is: /url=worker
# /examples/*=loadbalancer
#JkMountFile conf/uriworkermap.properties

# Add shared memory.
# This directive is present with 1.2.10 and
# later versions of mod_jk, and is needed for
# for load balancing to work properly
JkShmFile logs/jk.shm

# Add jkstatus for managing runtime data
<Location /jkstatus/>
    JkMount status
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
</Location>
###########################

Step10). Now create another most important file “worker.properties” inside “C:Program FilesApache GroupApache2conf” to tell apache to load balance between what all nodes of the JBoss clusters:

##### JBOSS #############
# Define list of workers that will be used
# for mapping requests
worker.list=failover
#,status

# Define Node2
# modify the host as your host IP or DNS name.
worker.node2.port=8209
worker.node2.host=20.20.20.20
worker.node2.type=ajp13
worker.node2.ping_mode=A
worker.node2.lbfactor=1

# Define Node1
# modify the host as your host IP or DNS name.
worker.node1.port=8109
worker.node1.host=10.10.10.10
worker.node1.type=ajp13
worker.node1.ping_mode=A
worker.node1.lbfactor=1

# Load-balancing behaviour
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node2,node1
worker.loadbalancer.sticky_session=False
worker.list=loadbalancer

# Status worker for managing load balancer
#worker.status.type=status
###########################

NOTE: Make sure that you are setting the correct “Hostname” and “AJP Port” for your JBoss in the above file.

Step 11). Now restart your apache server and then hit the following URL to access the JBoss:

http://localhost/jmx-console

OR

http://localhost/admin-console

.
.
Thanks
Middleware Magic


Using mod_jk to access multiple applications

In this article we would show you how to configure mod_jk so that one can access multiple applications using single Apache in front of JBoss application servers we would be using AS6. Many companies run n-number of applications and they might be using different Apache webservers for each applications to deal with it, hence hope this article would help you guys so that you can work with a single Apache having mod_jk to access multiple applications.

Here we would be taking the below examples in which we have a two different applications and one having a different context which would cover a huge ground for a combination of applications used by companies.

Examples

* App1 should work with url: http://abc.com/test
* App2 should work with url: http://abc.com
* App3 should work with url: http://xyz.com

Steps to configure mod_jk to access multiple applications

1. In “worker.properties” file would have the following entries

worker.list=App1,App2,App3

# Define App1
worker.App1.port=8009
worker.App1.host=localhost
worker.App1.type=ajp13
worker.App1.lbfactor=1

# Define App2
worker.App2.port=8109
worker.App2.host=localhost
worker.App2.type=ajp13
worker.App2.lbfactor=1

# Define App3
worker.App3.port=8209
worker.App3.host=localhost
worker.App3.type=ajp13
worker.App3.lbfactor=1

2. In “httpd.conf” file following should be the entries

NameVirtualHost *.80 

<VirtualHost *:80>
    ServerName abc.com
    DocumentRoot "/etc/httpd/www/html"
    DirectoryIndex home.html
    ErrorLog "/etc/httpd/conf/abc-error_log"
    CustomLog "/etc/httpd/conf/abc-access_log" common

    #Mount
    JkMount /* abc
    JkMount /abcd* abcd
</VirtualHost>

<VirtualHost *:80>
    ServerName xyz.com
    DocumentRoot "/etc/httpd/www/html"
    DirectoryIndex index.html
    ErrorLog "/etc/httpd/conf/xyz-error_log"
    CustomLog "/etc/httpd/conf/xyz-access_log" common

    #Mount
    JkMount /* xyz
</VirtualHost>

3. However to make sure that, when you hit “http://abc.com” and “http://xyz.com” URL’s the receptive applications comes up directly you should make sure that both the applications should have the following entries in there “/AppX/WEB-INF/jboss-web.xml” file

<jboss-web>
   <context-root>/</context-root>
</jboss-web>

And in there respective JBoss nodes “/NodeX/deploy/ROOT.war/WEB-INF/jboss-web.xml” file should add the following entry.
java:/jaas/jmx-console

<jboss-web>
 <security-domain>java:/jaas/jmx-console</security-domain>
 <context-root>/root</context-root>                         <!-- THIS LINE ADDED  -->
</jboss-web>

Example:
- For App-2 the JBoss Node-2 named as “node-2″
Path:
/node-2/deploy/abc.war/WEB-INF/jboss-web.xml – should have the context-root as “/”
/node-2/deploy/ROOT.war/WEB-INF/jboss-web.xml – should have context-root as “/root”

- For App-3 the JBoss Node-3 named as “node-3″
Path:
/node-3/deploy/xyz.war/WEB-INF/jboss-web.xml – should have context-root as “/”
/node-3/deploy/ROOT.war/WEB-INF/jboss-web.xml – should have context-root as “/root”

Thus now when you hit the above given URLs in the examples it would show you the respective application and that too using a single Apache in front of JBoss.


  • Receive FREE Updates


    FREE Email updates of our new posts Enter your email address:



  • Magic Archives

  • Copyright © 2010-2012 Middleware Magic. All rights reserved. | Disclaimer