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 Asynchronous Servlet and Asynchronous EJB3 inside a WAR file. (Which is the New Feature of Servlet Specification 3.0). One of the major changes in the Servlet Specification 3.0 is the support for Asynchronous Servlets: http://jcp.org/en/jsr/detail?id=315 …

This feature is very much desired when we invoke a long running process (like an EJB) from our Servlet, we want that the servlet should start the EJB execution in a separate process and should get back to the client as soon as possible.

In this example we will mainly focus on following points

Point-1). Here we are using JBoss AS7 latest build “jboss-as-7.1.0.Alpha2-SNAPSHOT”

Point-2). How to use and develop Asynchronous Servlets.

Point-3). How to use and develop Asynchronous EJBs with the help of javax.ejb.Asynchronous annotation.

Point-4). Also we will see how to place an Stateless Session Bean inside a WAR file.

Point-5). How to invoke an EJB3 from a Servlet which are present inside the same application. Using javax.ejb.EJB anotations lookup attribute.

Point-6). How to develop a Web Application without writing “web.xml”, rather using the Annotations to provide the servlet mapping and declaration.

Step1). Create a directory somewhere in your filesystem like “/home/userone/EE6_Async_Servlet_Demo” where we will place our application build related stuff. Then create another directory “src” inside “/home/userone/EE6_Async_Servlet_Demo” where we will be placing our source codes and JSPs.

Step2). Create Servlet class “TestAsyncServlet.java” as following inside the “/home/userone/EE6_Async_Servlet_Demo/src” directory.

package servlets;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.servlet.AsyncContext;
import javax.servlet.annotation.WebServlet;
import javax.ejb.EJB;

@WebServlet(value="/TestAsyncServletURL", asyncSupported=true)
public class TestAsyncServlet extends HttpServlet
  {
       @EJB (lookup="java:module/TestAsyncStatelessSessionBean!ejb3.TestAsyncStatelessSessionBean")
       private ejb3.TestAsyncStatelessSessionBean testAsyncStatelessSessionBean;

       public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
        {
            Logger logger = Logger.getLogger(TestAsyncServlet.class.getName());
            PrintWriter out=response.getWriter();

            logger.log(Level.INFO, "TestAsyncServlet inside service(req,res)");
            logger.log(Level.INFO, "TestAsyncServlet inside ThreadName : "+Thread.currentThread().getName());

            // Calling startAsync() method on servlet indicates that we are associating request in Async Mode
            AsyncContext asyncContext = request.startAsync();

            // Here the main execution of the following EJB method will run in a separate thread
            testAsyncStatelessSessionBean.executeLongTask(asyncContext);
            String data="";
            for(int i=0;i<10;i++)
             {
                String threadName=Thread.currentThread().getName();
                System.out.println("\tTestAsyncServlet service() at "+new java.util.Date()+"\t"+threadName);
                try{   Thread.sleep(500); } catch(Exception e){ e.printStackTrace(); }
             }
            out.println("ServletRequest is Processed ... !!!<font color=red>But EJB still might be processing</font>");
            out.close();
        }
  }

Step3). Now we will create a Simple Stateless EJB with a Long running Method so provide a class inside “/home/userone/EE6_Async_Servlet_Demo/src” directory with name “TestAsyncStatelessSessionBean.java” as following:

package ejb3;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
import javax.servlet.AsyncContext;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;

@Stateless
public class TestAsyncStatelessSessionBean
  {
     private Logger logger = Logger.getLogger(TestAsyncStatelessSessionBean.class.getName());

     @Asynchronous
     public void executeLongTask(AsyncContext asyncContext)
      {
           String data="";
           try {
                 for(int i=0;i<10;i++)
                  {
                     String threadName=Thread.currentThread().getName();
                     logger.log(Level.INFO,i+"\t EJB3 executeLongTask(asyncContext) at "+new java.util.Date()+"\t"+threadName);
                     Thread.sleep(2000);
                     data=data+"\n"+i+"\t EJB3 executeLongTask(asyncContext) at "+new java.util.Date()+"\t"+threadName;
                  }
           System.out.println("[EJB Processing is done] : "+data);
           asyncContext.complete();

       } catch (Exception e) {
           logger.log(Level.SEVERE, e.getMessage(), e);
       }
      }
  }

Step4). Now we will write a simple “index.jsp” page just to point to the Servlet, Place this file as wll inside the “/home/userone/EE6_Async_Servlet_Demo/src” directory as following:

<html>
   <body>
     <center>
        <h1> Welcome Page </h1>
        <h3><font color=maroon><a href="TestAsyncServletURL">Click Here to Access TestAsyncServlet</a></font></h3>
     </center>
  </body>
</html>

Step5). Now the most important part, here we are going to develop “build.xml” ANT file, which will build, deployour webapplication on the JBoss AS7.1 Server, so write the following “build.xml” file inside “/home/userone/EE6_Async_Servlet_Demo” directory.

<project name="SingletonStartupService" default="deploy">
<property name="jboss.home" value="/home/userone/jboss-as-7.1.0.Alpha2-SNAPSHOT" />
<property name="jboss.module.dir" value="${jboss.home}/modules" />
<property name="basedir" value="." />
<property name="tmp.dir" value="tmp" />
<property name="output.dir" value="build" />
<property name="src.dir" value="src" />
<property name="war.name" value="EE6Feature_AsyncServletAndEJB.war" />

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

        <target name="init">
           <delete dir="${output.dir}" />
           <mkdir dir="${output.dir}" />
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
        </target>

        <target name="build" depends="init">
           <mkdir dir="${tmp.dir}/WEB-INF/classes"/>
           <javac srcdir="${src.dir}" destdir="${tmp.dir}/WEB-INF/classes"  includes="*.java" classpathref="jboss.classpath" />

          <copy file="${src.dir}/index.jsp" tofile="${tmp.dir}/index.jsp"/>
          <copy file="${src.dir}/TestAsyncServlet.java" tofile="${tmp.dir}/WEB-INF/classes"/>
          <copy file="${src.dir}/TestAsyncStatelessSessionBean.java" tofile="${tmp.dir}/WEB-INF/classes"/>

           <jar jarfile="${tmp.dir}/${war.name}" basedir="${tmp.dir}" compress="true" />
           <copy file="${tmp.dir}/${war.name}" tofile="${output.dir}/${war.name}"/>
           <delete includeEmptyDirs="true">
              <fileset dir="${tmp.dir}"/>
           </delete>
        </target>

        <target name="deploy" depends="build">
            <echo message="*******************  Deploying the WAR file ${war.name} *********************" />
            <echo message="********** ${output.dir}/${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="*******************  Deployed Successfully   *********************" />
        </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.

Step6). Now before running your ANT script to build and deploy the above webapplication 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%

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

[userone@localhost EE6_Async_Servlet_Demo]$ ant deploy
Buildfile: build.xml

init:
   [delete] Deleting directory /home/userone/EE6_Async_Servlet_Demo/build
    [mkdir] Created dir: /home/userone/EE6_Async_Servlet_Demo/build
    [mkdir] Created dir: /home/userone/EE6_Async_Servlet_Demo/tmp

build:
    [mkdir] Created dir: /home/userone/EE6_Async_Servlet_Demo/tmp/WEB-INF/classes
    [javac] Compiling 2 source files to /home/userone/EE6_Async_Servlet_Demo/tmp/WEB-INF/classes
     [copy] Copying 1 file to /home/userone/EE6_Async_Servlet_Demo/tmp
      [jar] Building jar: /home/userone/EE6_Async_Servlet_Demo/tmp/EE6Feature_AsyncServletAndEJB.war
     [copy] Copying 1 file to /home/userone/EE6_Async_Servlet_Demo/build

deploy:
     [echo] *******************  Deploying the WAR file EE6Feature_AsyncServletAndEJB.war *********************
     [echo] ********** build/EE6Feature_AsyncServletAndEJB.war to /home/userone/jboss-as-7.1.0.Alpha2-SNAPSHOT/standalone/deployments **********
     [copy] Copying 1 file to /home/userone/jboss-as-7.1.0.Alpha2-SNAPSHOT/standalone/deployments
     [echo] *******************  Deployed Successfully   *********************

BUILD SUCCESSFUL

Step8). Now you will see the following kind of output on your JBoss AS7.1 console which means the application is deployed successfully:

12:46:26,905 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-8) Starting deployment of "EE6Feature_AsyncServletAndEJB.war"
12:46:26,928 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-6) JNDI bindings for session bean named TestAsyncStatelessSessionBean in deployment unit deployment "EE6Feature_AsyncServletAndEJB.war" are as follows:

	java:global/EE6Feature_AsyncServletAndEJB/TestAsyncStatelessSessionBean!ejb3.TestAsyncStatelessSessionBean
	java:app/EE6Feature_AsyncServletAndEJB/TestAsyncStatelessSessionBean!ejb3.TestAsyncStatelessSessionBean
	java:module/TestAsyncStatelessSessionBean!ejb3.TestAsyncStatelessSessionBean
	java:global/EE6Feature_AsyncServletAndEJB/TestAsyncStatelessSessionBean
	java:app/EE6Feature_AsyncServletAndEJB/TestAsyncStatelessSessionBean
	java:module/TestAsyncStatelessSessionBean

12:46:26,966 INFO  [org.jboss.web] (MSC service thread 1-2) registering web context: /EE6Feature_AsyncServletAndEJB
12:46:26,974 INFO  [org.jboss.as.server.controller] (DeploymentScanner-threads - 1) Replaced deployment "EE6Feature_AsyncServletAndEJB.war" with deployment "EE6Feature_AsyncServletAndEJB.war"

Step9). Now access the WebApplication like following : http://localhost:8080/EE6Feature_AsyncServletAndEJB

As soon as you will access the Servlet “http://localhost:8080/EE6Feature_AsyncServletAndEJB/TestAsyncServletURL” you will see the following kind of output …which indicates that the Servlet is being executed by Thread “http-localhost-127.0.0.1-8080-3″ whereas the EJB invocation which is done through the Servlet is being executed by a Separate Thread “pool-8-thread-10″

12:48:13,063 INFO  [servlets.TestAsyncServlet] (http-localhost-127.0.0.1-8080-3) TestAsyncServlet inside service(req,res)
12:48:13,064 INFO  [servlets.TestAsyncServlet] (http-localhost-127.0.0.1-8080-3) TestAsyncServlet inside ThreadName : http-localhost-127.0.0.1-8080-3
12:48:13,065 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:13 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:13,065 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 0	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:13 IST 2011	pool-8-thread-10
12:48:13,566 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:13 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:14,067 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:14 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:14,567 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:14 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:15,066 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 1	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:15 IST 2011	pool-8-thread-10
12:48:15,068 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:15 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:15,608 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:15 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:16,108 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:16 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:16,609 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:16 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:17,067 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 2	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:17 IST 2011	pool-8-thread-10
12:48:17,110 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:17 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:17,610 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) 	TestAsyncServlet service() at Sun Nov 20 12:48:17 IST 2011	http-localhost-127.0.0.1-8080-3
12:48:19,068 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 3	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:19 IST 2011	pool-8-thread-10
12:48:21,068 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 4	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:21 IST 2011	pool-8-thread-10
12:48:23,069 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 5	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:23 IST 2011	pool-8-thread-10
12:48:25,070 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 6	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:25 IST 2011	pool-8-thread-10
12:48:27,071 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 7	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:27 IST 2011	pool-8-thread-10
12:48:29,072 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 8	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:29 IST 2011	pool-8-thread-10
12:48:31,073 INFO  [ejb3.TestAsyncStatelessSessionBean] (pool-8-thread-10) 9	 EJB3 executeLongTask(asyncContext) at Sun Nov 20 12:48:31 IST 2011	pool-8-thread-10

NOTE:  JBoss AS7 is a Community release  and we always recommend you to use the RedHat Supported JBoss Enterprise Application Platform, There are various reasons behind this. Please refer to the Video:  http://www.youtube.com/watch?v=iNFV0r9v14g&feature=player_detailpage

.
Thanks
Middleware Magic Team