Hi,

AS 7 does classloading right. It uses JBoss Modules to provide true application isolation, hiding server implementation classes from the application and only loading the classes your application needs. Modules, packaged as collections of classes, are peers that remain isolated unless explicitly defined as a dependency of another module. Visibility rules have sensible defaults, yet can be customized.

Modular classloading is one of the greatest and amazing feature of JBossAS7, but some application server admins are not much aware of this new feature. So here we are going to see a practicle demo of creating a module on JBoss AS7.1.1.Final.

Few Points Which we are going to discuss here:

Point-1). How to create our own custom modules?

Point-2). What is the need of “module.xml” and where to place it?

Point-3). What is “slot” and Why and When to define “slot” in our “module.xml” file?

Point-4). How to reference a module inside our webapplication for classloading purpose?

Point-5). How and why to use the “META-INF/jboss-deployment-structure.xml” or “WEB-INF/jboss-deployment-structure.xml” file?

***NOTE*** This demo is also available in Github:
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/JBossAS7_module_slot_Demo

Developing a Custom Module:

Step-1). Create a directory somewhere in your file system where we will develop our own custom Module with some different versions of class files. Suppose the directory is “/home/userone/CustomModuleTest”

Step-2). Now create a directories structure as “aaa/bbb/1.0” and “aa/bbb/main” inside the directory “/home/userone/CustomModuleTest”.

Step-3). Now write a class with name “Test.java” inside “/home/userone/CustomModuleTest/aaa/bbb/1.0” as following:

package aaa.bbb;
public class Test
  {
     static {
          System.out.println("nntaaa.bbb.Test class Loaded  [VERSION-1.0]");
      }
     public String sayHello(String name)
      {
          System.out.println("nntaaa.bbb.Test sayHello() called");
          return "Mr. " +name;
      }
  }

Step-4). Similarly write a “Test.java” program as following inside the directory “/home/userone/CustomModuleTest/aaa/bbb/main” :

package aaa.bbb;
public class Test
  {
     static {
          System.out.println("nnt[1.2] aaa.bbb.Test class Loaded  [VERSION-1.2]");
      }
     public String sayHello(String name)
      {
          System.out.println("nnt[1.2] aaa.bbb.Test sayHello() called");
          return "Mr. [1.2] " +name;
      }
  }

***NOTE***: The class “aaa.bbb.Test” is same as mentioned in Step3 and Step4 but there is a slight different in the implementation of these classes like the Version of the class is 1.0 and 1.2 as you can see in the static block of the code. This is just to demonstrate that how we can load any version of the same class inside our application with the help of “slot” concept of JBoss Modules.

Step-5). Now we will need to write a file with name “module.xml” inside the directory “/home/userone/CustomModuleTest/aaa/bbb/1.0” as following:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="aaa.bbb" slot="1.0">
    <resources>
        <resource-root path="Test1.0.jar"/>
    </resources>
</module>

Step-6). Now we will need to write another file with name “module.xml” inside the directory “/home/userone/CustomModuleTest/aaa/bbb/main” as following:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="aaa.bbb">
    <resources>
        <resource-root path="Test1.2.jar"/>
    </resources>
</module>

***NOTE*** If we have the same Jars of different versions defined as part of a module then the Jar which is present inside the “main” directory of the module will be utilized by default until the application uses “META-INF/jboss-deployment-structure.xml” or “WEB-INF/jboss-deployment-structure.xml” to mention which “slot” (version) it want to use.

Step-7). Now it’s turn to compile the Test.java class. So open a shell prompt and then make sure that your PATH variable is set properly to point to the JDK bin directory as following:

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

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

Step-8). In the abobe shell prompt now move inside the directory “/home/userone/CustomModuleTest/aaa/bbb/main” to compile the Test.java program and to create a Test1.2.jar file as following:

[userone@localhost 1.0]$ cd /home/userone/CustomModuleTest/aaa/bbb/main

[userone@localhost main]$  javac -d . Test.java 

[userone@localhost main]$  jar cvf Test1.2.jar Test.java aaa/
added manifest
adding: Test.java(in = 321) (out= 174)(deflated 45%)
adding: aaa/(in = 0) (out= 0)(stored 0%)
adding: aaa/bbb/(in = 0) (out= 0)(stored 0%)
adding: aaa/bbb/Test.class(in = 766) (out= 455)(deflated 40%)

Step-9). Similarly we wiill compile the Test.java present inside the “/home/userone/CustomModuleTest/aaa/bbb/1.0”. So in the abobe shell prompt now move inside the directory “/home/userone/CustomModuleTest/aaa/bbb/1.0” to compile the Test.java program and to create a Test1.0.jar file as following:

[userone@localhost 1.0]$ cd /home/userone/CustomModuleTest/aaa/bbb/1.0

[userone@localhost 1.0]$ javac -d . Test.java 

[userone@localhost 1.0]$ jar cvf Test1.0.jar Test.java aaa/
added manifest
adding: Test.java(in = 303) (out= 168)(deflated 44%)
adding: aaa/(in = 0) (out= 0)(stored 0%)
adding: aaa/bbb/(in = 0) (out= 0)(stored 0%)
adding: aaa/bbb/Test.class(in = 748) (out= 448)(deflated 40%)

Step-10). Now just copy and paste your custom module directory “aaa” directory placed inside the “/home/userone/CustomModuleTest” to destination directory “/home/userone/jboss-as-7.1.1.Final/modules”

Step-11). Now restart your JBossAS7 server as following:

     ./standalone.sh  -c standalone-full.xml

Testing the Custom Module and it’s slot:

Now we are going to develop a simple web application which will demonstrate how we can load the module, which has name “aaa.bbb” inside our application. And how to load various versions of the same class “aaa.bbb.Test” with the help of “slot” using “WEB-INF/jboss-deployment-structure.xml”

Step-12). Just create a WebApplication directory “TestCustomModule.war” somewhere in your file system like inside “/home/userone/CustomModuleTest”

Step-14). Write the following kind of simple “index.jsp” page inside our Web Application directory “/home/userone/CustomModuleTest/TestCustomModule.war”

<html>
  <head><title>JBoss Module Testing </title></head>
  <body>

    <%
       aaa.bbb.Test test=new aaa.bbb.Test();
       System.out.println("test.sayHello(JBossAS7) = "+test.sayHello("JBossAS7"));   
       out.println("test.sayHello(JBossAS7) = "+test.sayHello("JBossAS7"));      
    %>
       Hi Check the Console/Log  of your JBoss
  </body>
</html>

Step-15). Create another directory “WEB-INF” as “/home/userone/CustomModuleTest/TestCustomModule.war/WEB-INF” and then palce the following kind of “web.xml” file inside it :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Module Demo JBposs AS7 </display-name>
 
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>

Step-16). Create another file with name “jboss-deployment-structure.xml” inside “/home/userone/CustomModuleTest/TestCustomModule.war/WEB-INF”, Now with the help of this file we will specify which version of the “aaa.bbb.Test ” class we want to use in our application.

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="aaa.bbb" slot="1.0" />
    </dependencies>
  </deployment>
</jboss-deployment-structure>

Step-17). Copy and paste the “TestCustomModule.war” directory inside your JBossAS7 standalone deployment directory “/home/userone/jboss-as-7.1.1.Final/standalone/deployments”

Step-18). Now write a file with name “TestCustomModule.war.dodeploy” inside the JBoss deployment directory “/home/userone/jboss-as-7.1.1.Final/standalone/deployments” to tell JBoss AS7 to deploy our application. (NOTE: as our application is Exploaded directory so we need to create this file otherwise war/jar/ear “FILES” are automatically deployed without creating *.dodeploy file.)

Step-19). Access the application as “http://localhost:8080/TestCustomModule/index.jsp” to see if your JSP file is able to access the “aaa.bbb.Test” class or not? In the JBoss Console (command prompt output/STDOUT) you will see following kind of output.

12:19:37,036 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "TestCustomModule.war"
12:22:54,946 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:22:54,947 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:22:54,947 INFO  [stdout] (http--127.0.0.1-8080-2) 	aaa.bbb.Test class Loaded  [VERSION-1.0]
12:22:54,947 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:22:54,948 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:22:54,949 INFO  [stdout] (http--127.0.0.1-8080-2) 	aaa.bbb.Test sayHello() called
12:22:54,950 INFO  [stdout] (http--127.0.0.1-8080-2) test.sayHello(JBossAS7) = Mr. JBossAS7
12:22:54,950 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:22:54,951 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:22:54,951 INFO  [stdout] (http--127.0.0.1-8080-2) 	aaa.bbb.Test sayHello() called

Further Testing & Verification :

Step-20). At the time of application deployment based on the version of module which you mentioned in your “jboss-deployment-structure.xml”, If your module is loaded and deployed successfully then you will see a file with name “Test1.0.jar.index” or “Test1.2.jar.index” name inside the “/home/userone/jboss-as-7.1.1.Final/modules/aaa/bbb/1.0” or “/home/userone/jboss-as-7.1.1.Final/modules/aaa/bbb/main”

Step-21). Remove the “slot=1.0” attribute in your “” file as following then redeploy your WebApplication then see access the same index.jsp page ….. you will notice that now JBoss AS7 will load the 1.2 version of aaa.bbb.Text class as this is the default version.

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="aaa.bbb"/>
    </dependencies>
  </deployment>
</jboss-deployment-structure>

Folllowing kind of output your will see now after redeployment of your application :

12:24:52,293 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-4) JBAS015877: Stopped deployment TestCustomModule.war in 165ms
12:24:52,295 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-4) JBAS015876: Starting deployment of "TestCustomModule.war"
12:24:52,365 INFO  [org.jboss.web] (MSC service thread 1-5) JBAS018210: Registering web context: /TestCustomModule
12:24:52,482 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018562: Redeployed "TestCustomModule.war"
12:25:00,697 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:25:00,698 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:25:00,698 INFO  [stdout] (http--127.0.0.1-8080-2) 	[1.2] aaa.bbb.Test class Loaded  [VERSION-1.2]
12:25:00,698 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:25:00,699 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:25:00,700 INFO  [stdout] (http--127.0.0.1-8080-2) 	[1.2] aaa.bbb.Test sayHello() called
12:25:00,700 INFO  [stdout] (http--127.0.0.1-8080-2) test.sayHello(JBossAS7) = Mr. [1.2] JBossAS7
12:25:00,701 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:25:00,701 INFO  [stdout] (http--127.0.0.1-8080-2) 
12:25:00,701 INFO  [stdout] (http--127.0.0.1-8080-2) 	[1.2] aaa.bbb.Test sayHello() called

Notice that this time a 1.2 version of aaa.bbb.Test class is loaded by JBoss.

.
.
Thanks 🙂
Middleware Magic Team

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.