EE6 Feature

SAR dependency alternate approach using @Singleton in JBossAS7.1.2

Hi,

SAR files are called as Service Archives. The extension of SAR files are *.sar which contains a “META-INF/jboss-service.xml” file, this file describes the custom MBeans which has to be exposed at the time of deployment or JBoss Startup. JBoss’s service archive architecture is based on the JMX and the SAR files which are basically JBoss specific can be deployed in the jboss inorder to publish your MBean based services. At the time of JBoss startup these service archive deployer (SARDeployer) instantiates the JBoss service classes and exposes them as manageable beans through JMX.

In previous release of JBoss 5/6 the SAR provided mbeans dependency could be very easily defined using <depends> tag, as following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE server>
<server>
    <mbean code="custom.mbean.MyServerMonitor" name="service.server.monitor:service=MyMonitor">
         <attribute name="Frequency">5000</attribute>
         <depends>jboss.jca:service=DataSourceBinding,name=MySqlDS</depends>
    </mbean>
</server>

@org.jboss.ejb3.annotation.Service and @org.jboss.ejb3.annotation.Management are no longer supported which could be used to define Services. However in JBossAS7 this approach of defining the dependency is not good and you may see following kind of exceptions at the time of server startup:

JBAS014775:    New missing/unsatisfied dependencies:
      service jboss.mbean.service."jboss.as:subsystem=datasources,data-source=MySqlDS".create (missing) dependents: [service jboss.mbean.service."service.server.monitor:service=MyMonitor".create]
      service jboss.mbean.service."jboss.as:subsystem=datasources,data-source=MySqlDS".start (missing) dependents: [service jboss.mbean.service."service.server.monitor:service=MyMonitor".start]

JBossAS7 is fully EE6 certified application server and it provides a much better approach to create a Service with the help of EJB3.1 specific “javax.ejb.Startup” and “javax.ejb.Singleton” annotations. This kind of service can be made dependent to other services like DataSource. In this example we will see What is the better approach to define a service (without using container specific SAR feature).

The Source code for this demo can be found in the following github link:
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/SingletonServiceDemo

Creating DataSource in JBossAS7.1.2

As we are going make our Service dependent on a DataSource, sothat we can see how the dependency goes.

Configuration-1). So here first of all we will create a DataSource by running the following CLI script in batch mode. So create a file with name “createDataSource.cli” somewhere in your filesystem like “/home/jaysensharma/SingletonServiceDemo/createDataSource.cli” as following:

deploy  /home/jaysensharma/SingletonServiceDemo/mysql-connector-java-5.1.13-bin.jar

/subsystem=datasources/data-source="MySqlDS":add(jndi-name="java:jboss/datasources/MySqlDS",driver-name="mysql-connector-java-5.1.13-bin.jar",connection-url="jdbc:mysql://localhost:3306/testDB",user-name="root",password="redhat")

Configuration-2). Now start your “$JBOSS_HOME/bin/jboss-cli.sh” script in order to run the above deploy the mysql driver and create DataSource as following:

./jboss-cli.sh -c --controller=10.10.10.10:9999 --file=/home/jaysensharma/SingletonServiceDemo/createDataSource.cli

Configuration-3). As soon as you will run the cli script as mentioned above you will see that the following kind of datasource is created on your standalone*.xml.

                <datasource jndi-name="java:jboss/datasources/MySqlDS" pool-name="MySqlDS">
                    <connection-url>jdbc:mysql://localhost:3306/testDB</connection-url>
                    <driver>mysql-connector-java-5.1.13-bin.jar</driver>
                    <security>
                        <user-name>root</user-name>
                        <password>redhat</password>
                    </security>
                </datasource>

Creating @Singleton service dependent on the DataSource

Step1). First of all we will create a directory somewhere in our file system as “/home/jaysensharma/SingletonServiceDemo” and then we will create a directory with name “src” inside “/home/jaysensharma/SingletonServiceDemo”:

Step2). Now write a @Startup @Singleton EJB3.1 service using “SingletonServiceBean.java” inside “/home/jaysensharma/SingletonServiceDemo/src” as following:

package sar.dependency.alternative;
import javax.ejb.Startup;
import javax.ejb.Singleton;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

//commons logging
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// DataSource related
import javax.sql.DataSource;
import java.sql.Connection;

// Resource Injection related
import javax.annotation.Resource;

@Startup
@Singleton

public class SingletonServiceBean
 {
     private static Log logger = LogFactory.getLog(SingletonServiceBean.class);
     Connection con=null;


     public SingletonServiceBean()
            {
               logger.info("SingletonServiceBean constructor invoked.");
            }


     @Resource(name = "java:jboss/datasources/MySqlDS")
     DataSource ds;
     /* This @PostConstruct annotation is required to tell JBoss to invoke the "performOperations" immediately after the "SingletonServiceBean" creation. */
     @PostConstruct
     public void performOperations()
	    {
               logger.info("SingletonServiceBean performOperations() invoked.");
               try{
                     con=ds.getConnection();
                     logger.info("***** DataSource = "+ds+" . Connection con = "+con+" retrieved from the ConnectionPool.*****");
                  }
               catch(Exception e)
                 {
                     logger.error("Unable to get Connection From DataSource = "+ds+" ERROR: "+e.getMessage());
                     e.printStackTrace();
                 }
	    }


	@PreDestroy
	public void cleanUp() throws Exception {
	  logger.info("cleaning up connections.");
          if(con!=null)
            {
               try{
                     con.close();
                     logger.info("Connection con = "+con+" is successfully returned to the ConnectionPool.");
                  }
               catch(Exception e)
                 {
                     logger.error("Unable to Close Connection con = "+con+" ERROR: "+e.getMessage());
                     e.printStackTrace();
                 }
               finally{
                        try{   con.close(); }
                        catch(Exception ee) { ee.printStackTrace(); }
                      }
            }
	}
 }

Step3). Now the most important part of building / deploying the Singleton Service which we created, so in order to achieve that we will create a simple ant build script, So Create a “build.xml” file inside the “/home/jaysensharma/SingletonServiceDemo” directory as following:

<project name="SingletonStartupService" default="all">
<property name="jboss.home" value="/home/jaysensharma/jboss-as-7.1.2.Final" />
<property name="jboss.module.dir" value="${jboss.home}/modules" />
<property name="basedir" value="." />
<property name="tmp.dir" value="tmp" />
<property name="src.dir" value="src" />
<property name="output.dir" value="build" />
<property name="ear.name" value="TestSingletonService.ear" />
<property name="ejb.jar" value="singletonServiceEJB.jar" />


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

        <target name="all" depends="deploy" />

        <target name="build_ear">
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
           <javac srcdir="${src.dir}" destdir="${tmp.dir}"  includes="*.java" classpathref="jboss.classpath"/>

           <jar jarfile="${tmp.dir}/${ejb.jar}" basedir="${tmp.dir}" compress="true" />

           <delete includeEmptyDirs="true">
              <fileset dir="${tmp.dir}/sar"/>
           </delete>
           <mkdir dir="${tmp.dir}/META-INF"/>
           <copy todir="${tmp.dir}/META-INF">
                <fileset dir="${src.dir}/">
                  <include name="application.xml"/>
                </fileset>
           </copy>
           <jar jarfile="${tmp.dir}/${ear.name}" basedir="${tmp.dir}" compress="true" />
           <delete includeEmptyDirs="true">
              <fileset dir="${tmp.dir}/META-INF"/>
           </delete>
           <delete file="${tmp.dir}/${ejb.jar}"/>

           <copy file="${tmp.dir}/${ear.name}" tofile="${output.dir}/${ear.name}"/>
           <delete dir="${tmp.dir}"/>
        </target>


        <target name="deploy" depends="build_ear">
            <echo message="*******************  Deploying the EAR file ${ear.name} *********************" />
            <echo message="********** ${output.dir}/${ear.name} to ${jboss.home}/standalone/deployments **********" />
            <copy todir="${jboss.home}/standalone/deployments/">
                <fileset dir="${output.dir}/">
                  <include name="${ear.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.

Step-4). 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/jaysensharma/jdk1.6.0_21/bin:/home/jaysensharma/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%

Step-5). Now once the PATH is set In the command/Shell prompt you can move inside the directory “/home/jaysensharma/SingletonServiceDemo” and then run the ant to build and deploy the EJB based EAR applicationon your JBoss Standalone full profile, by running the command “ant deploy”

[jaysensharma@localhost SingletonServiceDemo]$ ant
Buildfile: build.xml

build_ear:
    [mkdir] Created dir: /home/jaysensharma/SingletonServiceDemo/tmp
    [javac] Compiling 1 source file to /home/jaysensharma/SingletonServiceDemo/tmp
      [jar] Building jar: /home/jaysensharma/SingletonServiceDemo/tmp/singletonServiceEJB.jar
    [mkdir] Created dir: /home/jaysensharma/SingletonServiceDemo/tmp/META-INF
      [jar] Building jar: /home/jaysensharma/SingletonServiceDemo/tmp/TestSingletonService.ear
   [delete] Deleting: /home/jaysensharma/SingletonServiceDemo/tmp/singletonServiceEJB.jar
     [copy] Copying 1 file to /home/jaysensharma/SingletonServiceDemo/build
   [delete] Deleting directory /home/jaysensharma/SingletonServiceDemo/tmp

deploy:
     [echo] *******************  Deploying the EAR file TestSingletonService.ear *********************
     [echo] ********** build/TestSingletonService.ear to /home/jaysensharma/jboss-as-7.1.2.Final/standalone/deployments **********
     [copy] Copying 1 file to /home/jaysensharma/jboss-as-7.1.2.Final/standalone/deployments
     [echo] *******************  Deployed Successfully   *********************

all:

BUILD SUCCESSFUL
Total time: 1 second

Step-6). As the application is deployed on your JBoss so now try restarting your JBoss and then see whether the Above service us successfully get the DataSource and JDBC Connection or not. If the Dependency is correctly working then after restarting your JBoss you will see the following kind of message on your JBoss console / logs.

22:41:51,569 INFO  [sar.dependency.alternative.SingletonServiceBean] (MSC service thread 1-1) ***** DataSource = org.jboss.jca.adapters.jdbc.WrapperDataSource@43877c42 . Connection con = org.jboss.jca.adapters.jdbc.jdk6.WrappedConnectionJDK6@5424bf0 retrieved from the ConnectionPool.*****

.
.
Thanks
MiddlewareMagic Team 🙂


Creating JMS Queue/Topic via Application using *-jms.xml in JBossAS7

Hi,

In our some of the previous demos how to effeciently use the JBoss Messaging feature which is implemented over Best Messagng System HornetQ. We created JMS Queue and topics using CLI and using the Admin Console previously. Here in this demo we will see how to create a JMS Queue/Topic using *-jms.xml file and how to deploy it as part of our simple Application like .war file.

Although it is not recommended to use the application specific JMS Queue / Topic deployment because of it’s less managability. We should not use it for production purpose because it will not be possible to monitor it using the console or to manage it. But as a reference and a possibility we are going to discuss application level JMS Queue/Topic deployment as part of this article.

Points We will Discuss

Point-1) How to deploy a JMS Queue/Topic via *-jms.xml file placed inside our “WEB-INF” directory.

Point-2) How to place our MDBs inside the WAR file and deploy it as part of our Web Application (WAR).

Point-3) How to write a simple Standalone program in order to send some JMS Messages to the JMS Queue.

NOTE: the Codes related to this demo are available in the Github repository:
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/JMS_Demo

Step-1). Here we are using JBoss AS7.1.1 Final (“jboss-as-7.1.1.Final”) which can be downloaded from the following link: http://www.jboss.org/jbossas/downloads

Step-2). Create a directory with the name “src” somewhere in your file system like “/home/userone/JMS_Demo/”. Inside the “src” directory we are going to place our all source code and xml files for development.

Step-3). Now we will write a simple file “test-jms.xml” where we will define our JMS Queue and Topics. Place this file inside “/home/userone/JMS_Demo/src” as following

<?xml version="1.0" encoding="UTF-8"?>
<messaging-deployment xmlns="urn:jboss:messaging-deployment:1.0">
    <hornetq-server>
        <jms-destinations>
            <jms-queue name="QueueOne">
                <entry name="java:jboss/exported/TestQueueOne"/>
                <durable>true</durable>
            </jms-queue>
            <jms-topic name="TopicOne">
                <entry name="java:jboss/exported/TestTopicOne"/>
            </jms-topic>
        </jms-destinations>
    </hornetq-server>
</messaging-deployment>

Step-4). Now we will write a Simple Servlet program “QueueSendServlet.java” which will send some messages to the JMS queue “TestQueueOne” Place this file inside “/home/userone/JMS_Demo/src” as following:

import java.io.*;
import javax.jms.*;
import javax.naming.*;
import javax.servlet.http.*;
import javax.servlet.ServletException;

public class QueueSendServlet extends HttpServlet
{
	static PrintWriter out;
	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
 	 {
		try
		{
			out=response.getWriter();
			InitialContext ic = getInitialContext();
			init(ic, QUEUE_NAME);
			sendMsg(request.getParameter("jmsMessage"));
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	public final static String CNN_FACTORY="/ConnectionFactory";
	public final static String QUEUE_NAME="java:jboss/exported/TestQueueOne";

	private QueueConnectionFactory qconFactory;
	private QueueConnection qcon;
	private QueueSession qsession;
	private QueueSender qsender;
	private Queue queue;
	private TextMessage msg;

	public void init(Context ctx, String queueName)throws NamingException, JMSException
	{
		qconFactory = (QueueConnectionFactory) ctx.lookup(CNN_FACTORY);
		qcon = qconFactory.createQueueConnection();
		qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
		queue = (Queue) ctx.lookup(queueName);
		qsender = qsession.createSender(queue);
		msg = qsession.createTextMessage();
		qcon.start();
	}

	private  void sendMsg(String userMessage) throws IOException, JMSException
	{
		boolean readFlag=true;
		out.println("");
		out.println("");
		out.println("");
		out.println("<h1>Queue Sender Servlet</h1>");
		out.println("Following Messages has been sent !!!");
		out.println("<BR>====================================<BR>");
                        msg.setText(userMessage);
                        qsender.send(msg);
   			out.println("Message Sent => "+userMessage);
		out.println("<BR>====================================");
		out.println("");
		out.println("");
		out.println("");
                qcon.close();
	}

	private static InitialContext getInitialContext() throws NamingException
	{
		return new InitialContext();
	}
}

Step-5). Now we will Write a simple “Message Driven Bean “MyMDB.java” which will consume messages from TestQueueOne file,Place this file inside “/home/userone/JMS_Demo/src” as following

import javax.jms.Message;
import javax.jms.TextMessage;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.ejb.MessageDriven;
import javax.ejb.ActivationConfigProperty;

@MessageDriven(activationConfig =
        {
        @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
        @ActivationConfigProperty(propertyName="destination", propertyValue="java:jboss/exported/TestQueueOne")
        })

public class MyMDB implements MessageListener
{
    public void onMessage(Message message)
    {
        TextMessage textMessage = (TextMessage) message;
        try
       {
            System.out.println("===> MyMDB Received: "+ textMessage.getText());
        }
        catch (JMSException e)
        {
            e.printStackTrace();
        }
    }
}

Step-6). Now we will write a simple “index.jsp” page so that users can send their JMS Messages to the QueueSendServlet. Place this index.jsp file inside “/home/userone/JMS_Demo/src” as following:

<html>
   <head>
          <title> Simple App Level JMS Queue/Topic Demo </title>
   </head>
   <body>
      <center>
         <form action="QueueSendServlet">
            Enter Message to Send: <textarea name="jmsMessage"cols="20" rows="10"> Please Enter Your JMS Message Here !!! </textarea>
            <BR>
                <input type="Submit" value="Send JMS Message" /> 
                <input type="Reset" value="Clear" />
         </form>
      </center>
   </body>
</html>

Step-7). Now we will write a simple “web.xml” file inside “/home/userone/JMS_Demo/src” as following:

  <web-app>
     <servlet>
	<servlet-name>QueueSendServlet</servlet-name>
	<servlet-class>QueueSendServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
     </servlet>
     <servlet-mapping>
	<servlet-name>QueueSendServlet</servlet-name>
	<url-pattern>/QueueSendServlet</url-pattern>
     </servlet-mapping>
  </web-app>

Step-8). As we may want to send some messages to the JMS Queue from a remote Client as well using a Standalone program so we will also write a simple program “StandaloneQueueSend.java”, Place this file as well inside “/home/userone/JMS_Demo/src” as following:

import java.io.*;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.jms.*;
public class StandaloneQueueSend
{
public final static String JNDI_FACTORY="org.jboss.naming.remote.client.InitialContextFactory";

public static void main(String[] args) throws Exception
  {
     if (args.length != 1) {
         System.out.println("Usage: java StandaloneQueueSend URL");
         System.out.println("Example:  java StandaloneQueueSend remote://localhost:4447");
         return;
     } 

     InitialContext ic = getInitialContext(args[0]);
     StandaloneQueueSend demo = new StandaloneQueueSend();

     System.out.println("nnt *** Following shows Looking up a Primitive Datatype located in the JNDI ***");
     demo.init(ic,"TestQueueOne");
  }

private static InitialContext getInitialContext(String url) throws NamingException
     {
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
        env.put(Context.PROVIDER_URL, url);

        //*************** UserName & Password for the Initial Context for JNDI lookup *************************
        // ** Make sure that you create a user using "$JBOSS_HOME/bin/add-user.sh" with 
        // **  following userName & Password and the Rolename="guest"

        env.put(Context.SECURITY_PRINCIPAL, "TestJMSUser");
        env.put(Context.SECURITY_CREDENTIALS, "password");
        InitialContext ic=new InitialContext(env);
        System.out.println("nnt Got InitialContext ic: "+ic);
        return ic;
     }

	private QueueConnectionFactory qconFactory;
	private QueueConnection qcon;
	private QueueSession qsession;
	private QueueSender qsender;
	private Queue queue;
	private TextMessage msg;

	public void init(Context ctx, String queueName)throws NamingException, JMSException
	{
		qconFactory = (QueueConnectionFactory) ctx.lookup("/jms/RemoteConnectionFactory");
		qcon = qconFactory.createQueueConnection("TestJMSUser","password");
		qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
		queue = (Queue) ctx.lookup(queueName);
		qsender = qsession.createSender(queue);
		msg = qsession.createTextMessage();
		qcon.start();

                for(int i=1;i<=5;i++)
                  {
                    String message="Hello Message - "+i+" at "+ new java.util.Date();
                    msg.setText(message);
                    System.out.println("nt Message Sent : "+message); 
                    qsender.send(msg);
                  }
               qcon.close();                
	}

  }

Step-9). Now in order to build and deploy the above application we will write a very simple ant build script “build.xml” inside “/home/userone/JMS_Demo” as following:

<project name="ApplicationLevelJMSDemo" default="deploy">
<property name="jboss.home" value="/NotBackedUp/JBoss_All/jboss-as-7.1.1.Final" />
<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="ApplicationLevelJMSDemo.war" />

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

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

        <target name="build" depends="init">
           <javac srcdir="${src.dir}" destdir="${tmp.dir}/WEB-INF/classes" excludes="StandaloneQueueSend.java"
                  includes="*.java" classpathref="jboss.classpath" />
           <copy todir="${tmp.dir}/WEB-INF/classes">
                <fileset dir="${src.dir}" includes="**/*.java"/>
           </copy>
           <copy file="${src.dir}/index.jsp" tofile="${tmp.dir}/index.jsp"/>
           <copy file="${src.dir}/web.xml" tofile="${tmp.dir}/WEB-INF/web.xml"/>      
           <copy file="${src.dir}/test-jms.xml" tofile="${tmp.dir}/WEB-INF/test-jms.xml"/>      
           <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>

        <target name="run">
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
           <javac srcdir="${src.dir}" destdir="${tmp.dir}"  includes="StandaloneQueueSend.java" classpathref="jboss.classpath"/>
           <jar jarfile="${output.dir}/${client.jar.name}" basedir="${tmp.dir}" compress="true" />
           <java classname="StandaloneQueueSend" fork="true">
               <classpath>
                  <pathelement location="${tmp.dir}"/>
                  <path refid="jboss.classpath"/>
               </classpath>
               <arg value="remote://localhost:4447"/>
           </java>
           <delete dir="${tmp.dir}" />
        </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.

Step-9). 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%

Step-10). Now once the PATH is set In the command/Shell prompt you can move inside the directory “/home/userone/JMS_Demo” and then run the ant to build & deploy the webapplication. by running the command “ant”

[userone@localhost JMS_Demo]$ ant 
ant
Buildfile: /home/userone/JMS_Demo/build.xml

init:
   [delete] Deleting directory /home/userone/JMS_Demo/build
    [mkdir] Created dir: /home/userone/JMS_Demo/build
    [mkdir] Created dir: /home/userone/JMS_Demo/tmp
    [mkdir] Created dir: /home/userone/JMS_Demo/tmp/WEB-INF/classes

build:
    [javac] /home/userone/JMS_Demo/build.xml:29: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 2 source files to /home/userone/JMS_Demo/tmp/WEB-INF/classes
     [copy] Copying 3 files to /home/userone/JMS_Demo/tmp/WEB-INF/classes
     [copy] Copying 1 file to /home/userone/JMS_Demo/tmp
     [copy] Copying 1 file to /home/userone/JMS_Demo/tmp/WEB-INF
     [copy] Copying 1 file to /home/userone/JMS_Demo/tmp/WEB-INF
      [jar] Building jar: /home/userone/JMS_Demo/tmp/ApplicationLevelJMSDemo.war
     [copy] Copying 1 file to /home/userone/JMS_Demo/build

deploy:
     [echo] *******************  Deploying the WAR file ApplicationLevelJMSDemo.war *********************
     [echo] ********** build/ApplicationLevelJMSDemo.war to /home/userone/jboss-as-7.1.1.Final/standalone/deployments **********
     [copy] Copying 1 file to /home/userone/jboss-as-7.1.1.Final/standalone/deployments
     [echo] *******************  Deployed Successfully   *********************

BUILD SUCCESSFUL
Total time: 2 seconds

Step-11). Now you will able to access your application. “http://localhost:8080/ApplicationLevelJMSDemo/index.jsp” then you will be able to send some mesages from this page.

Sending JMS Messages using Standalone Client.

Step-12). Make sure that you create a new User using “$JBOSS_HOME/bin/add-user.sh” where:

UserName: TestJMSUser
Password: password
RoleName: guest

./add-user.sh 

What type of user do you wish to add? 
 a) Management User (mgmt-users.properties) 
 b) Application User (application-users.properties)
(a): b

Enter the details of the new user to add.
Realm (ApplicationRealm) : 
Username : TestJMSUser
Password : password
Re-enter Password : password
What roles do you want this user to belong to? (Please enter a comma separated list, or leave blank for none) : guest
About to add user 'TestJMSUser' for realm 'ApplicationRealm'
Is this correct yes/no? yes
Added user 'TestJMSUser' to file '/home/userone/jboss-as-7.1.1.Final/standalone/configuration/application-users.properties'
Added user 'TestJMSUser' to file '/home/userone/jboss-as-7.1.1.Final/domain/configuration/application-users.properties'
Added user 'TestJMSUser' with roles guest to file '/home/userone/jboss-as-7.1.1.Final/standalone/configuration/application-roles.properties'
Added user 'TestJMSUser' with roles guest to file '/home/userone/jboss-as-7.1.1.Final/domain/configuration/application-roles.properties'

Step-12). Now we will need to run the ANT script in order to compile and run the “StandaloneQueueSend.java” program to send 5 Messages to the JMS Queue as following : (just type ant run)

ant run
Buildfile: /home/userone/JMS_Demo/build.xml

run:
    [mkdir] Created dir: /home/userone/JMS_Demo/tmp
    [javac] Compiling 1 source file to /home/userone/JMS_Demo/tmp
    [javac] Note: /home/userone/JMS_Demo/src/StandaloneQueueSend.java uses unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.
      [jar] Building jar: /home/userone/JMS_Demo/build/${client.jar.name}
      log4j:WARN No appenders could be found for logger (org.jboss.logging).
      log4j:WARN Please initialize the log4j system properly.
      log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
      
      
      	 Got InitialContext ic: javax.naming.InitialContext@5f49d886
      
      
      	 *** Following shows Looking up a Primitive Datatype located in the JNDI ***
      
      	 Message Sent : Hello Message - 1 at Fri Jun 29 01:11:49 IST 2012
      
      	 Message Sent : Hello Message - 2 at Fri Jun 29 01:11:49 IST 2012
      
      	 Message Sent : Hello Message - 3 at Fri Jun 29 01:11:49 IST 2012
      
      	 Message Sent : Hello Message - 4 at Fri Jun 29 01:11:49 IST 2012
      
      	 Message Sent : Hello Message - 5 at Fri Jun 29 01:11:49 IST 2012
   [delete] Deleting directory /home/userone/JMS_Demo/tmp

BUILD SUCCESSFUL
Total time: 5 seconds

Some Issues You Might Face

Issue-1). Whiel running / writing your Remote JMS Client code you may see the following exception:

    Exception in thread "main" javax.jms.JMSSecurityException: Unable to validate user: null
    	at org.hornetq.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:312)
    	at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSessionInternal(ClientSessionFactoryImpl.java:780)
    	at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSession(ClientSessionFactoryImpl.java:279)
    	at org.hornetq.jms.client.HornetQConnection.authorize(HornetQConnection.java:601)
    	at org.hornetq.jms.client.HornetQConnectionFactory.createConnectionInternal(HornetQConnectionFactory.java:684)
    	at org.hornetq.jms.client.HornetQConnectionFactory.createQueueConnection(HornetQConnectionFactory.java:131)
    	at org.hornetq.jms.client.HornetQConnectionFactory.createQueueConnection(HornetQConnectionFactory.java:126)
    	at StandaloneQueueSend.init(Unknown Source)
    	at StandaloneQueueSend.main(Unknown Source)
    Caused by: HornetQException[errorCode=105 message=Unable to validate user: null]

In order to resolve above Error you will need to make sure that you Create an ApplicationRealm User using “$JBOSS_HOME/bin/add-user.sh” and the User should have the “guest” role. Also You should pass the same username and password while creating the “QueueConnection” as following:

queueConnection = queueConnectionFactory.createQueueConnection(“TestJMSUser”,”password”);

.
.
Thanks
Middleware Magic Team 🙂


RestEasy WebService & RestEasy Client with CDI injection in JBoss AS7


As we are already aware that JBossAS 7.1 is a Fully EE6 certified Application Server. It provides implementations of most needed features like “RestEasy WebService” And “CDI” injection. You might have already seen/read some of the demos of RestEast webservices in our previous articles. But here in this article we are going to focus on following points .

Point-1). How to developand use the JAX-RS resteasy implementations and various annotations associated with it on JBoss AS7.1.1.Final.

Point-2). How to use the CDI Injection of @javax.inject.Named Beans using @javax.enterprise.context.ApplicationScoped inside our RestEasy WebServices. And will see that why do we need “beans.xml” file.

Point-3). How and why to use the annotations like @javax.xml.bind.annotation.XmlRootElement.

Point-4). How to write a Pure RestEasy Standalone Client to access the RestEasy WebService.

The Source Code of this Demo can be Downloaded from the following link: “Github”
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/RestfulService_With_CDI_AS7

Writing RestEasy WebService with CDI Injection.

Step-1). Create a directory somewhere in your file system like “home/userone/RestfulService_With_CDI_AS7” then in this directory create a “src” directory where we will place all our source codes and application components.

Step-2). Write a Simple Class “Customer.java” inside “home/userone/RestfulService_With_CDI_AS7/src” with the help of “@javax.xml.bind.annotation.XmlRootElement” annotation sothat its value can be represented as XML element in an XML document.

package test;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {

	private int id;
	private String name;
	private String address;

	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}
}

Step-3). As above write another Simple Class “Customers.java” inside “home/userone/RestfulService_With_CDI_AS7/src” with the help of “@javax.xml.bind.annotation.XmlRootElement” annotation sothat its value also can be represented as XML element in an XML document.

package test;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.*;
@XmlRootElement
public class Customers {

	private List customer;

	public List getCustomer() {
		return customer;
	}

	public void setCustomer(List customer) {
		this.customer = customer;
	}
}

Step-4). Now we will write “TestBean.java” inorder to populate it’s property “java.util.TreeMap” with the Customer Objects. Write the “TestBean.java” program inside “home/userone/RestfulService_With_CDI_AS7/src”

package beans;
import java.io.Serializable;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
import java.util.TreeMap;
import test.Customer;

@Named
@ApplicationScoped
public class TestBean implements Serializable
   {
    private static final long serialVersionUID = 1L;
    private TreeMap customerMap;

    public TestBean()
         {
           System.out.println("nt TestBean which is CDI Bean instantiated.");
           customerMap=new TreeMap();
         }

    public TreeMap getCustomerMap()
         {
            System.out.println("nt[TestBean] getCustomerMap() called.");
            return customerMap;
         }

    public void setCustomerMap(TreeMap customerMap)
         {
           System.out.println("nt[TestBean] setCustomerMap(TreeMap) called.");
           this.customerMap = customerMap;
         }
   }

Step-5). As in the above TestBean we have used the @Named annotation and we have declared it’s scope as “ApplicationScoped” so now we will create a “beans.xml” file which is finally going to be placed inside “WEB-INF” directory of our webapplication for the CDI to wrok. So here we will need to create a file with name “beans.xml” inside “home/userone/RestfulService_With_CDI_AS7/src” as following:

*** NOTE: An application that uses CDI must have a file named beans.xml. The file can be completely empty (it has content only in certain limited situations), but it must be present.

<beans 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/beans_1_0.xsd">


</beans>

Step-6). In order to develop RestEasy WebService we should provide a class which extends “javax.ws.rs.core.Application” so write a Program “MyRestService.java” inside “home/userone/RestfulService_With_CDI_AS7/src” as following:

package ws.test;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("test")
public class MyRestService  extends Application {

}

Step-7). Now the Most important Step Here we will write a Class “CustomersResource.java” with the help of “javax.ws.rs.*” packages in order to process the Client Requests. so write a Program “CustomersResource.java” inside “home/userone/RestfulService_With_CDI_AS7/src” as following:

package test;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import javax.servlet.ServletContext;
import javax.ws.rs.core.Context;
import javax.inject.Inject;

@Produces("application/xml")
@Path("customers")
public class CustomersResource {

        @Inject
        private beans.TestBean testBean;

	private TreeMap customerMap = new TreeMap();

	public CustomersResource() {
                System.out.println("[CustomerResource] Instantiated  "+this);
		Customer customer1 = new Customer();
		customer1.setId(1111);
		customer1.setName("CustomerOne");
		customer1.setAddress("Bombay, India");

		Customer customer2 = new Customer();
		customer2.setId(2222);
		customer2.setName("CustomerTwo");
		customer2.setAddress("Pune, India");

		Customer customer3 = new Customer();
		customer3.setId(3333);
		customer3.setName("CustomerThree");
		customer3.setAddress("Bangalore, India");

                customerMap.put(customer1.getId(),customer1);
                customerMap.put(customer2.getId(),customer2);
                customerMap.put(customer3.getId(),customer3);

                if(testBean!=null)
                    {
                       System.out.println("[CustomersResource] testBean NOT NULL "+testBean);
                       testBean.setCustomerMap(customerMap);
                    }
                else
                    {
                       System.out.println("[CustomersResource] testBean IS NULL");
                    }
	}

	@GET
	@Produces(MediaType.APPLICATION_XML)
	@Path("all")
	public Customers getCustomers() {
		List customers = new ArrayList();
		customers.addAll(testBean.getCustomerMap().values());
                Customers allCustomers=new Customers();
                allCustomers.setCustomer(customers);
                return allCustomers;
	}

	@GET
	@Path("{id}")
	public Customer getCustomer(@PathParam("id") int customerId) {
		return customerMap.get(customerId);
	}

	public String addDefaultCustomer(Customer customer) {
		customerMap.put(customer.getId(), customer);
		return "Customer ID: " +  customer.getId() +" Name: "+ customer.getName()+" Address: "+customer.getAddress();
	}

	@POST
	@Path("add")
	@Produces(MediaType.APPLICATION_XML)
	@Consumes("application/x-www-form-urlencoded")
	public Customer addCustomer(@FormParam("custId")int id,@FormParam("custName")String name,@FormParam("custAddress")String address) {
		Customer customer = new Customer();
                customer.setId(id);
                customer.setName(name);
                customer.setAddress(address);
                customerMap.put(customer.getId(),customer);
                testBean.setCustomerMap(customerMap);
		return customer;
	}

}

Step-8). Now we will write following kind of JSP file “index.jsp” inside “home/userone/RestfulService_With_CDI_AS7/src” in order to allow users to provide/enter the customer details.


    CDI Demo
<table border="10%">
<form action="test/customers/add" method="POST"></form>
<tbody>
<tr>
<td>Customer ID:</td>
<td> <input name="custId" type="text" /></td>
</tr>
<tr>
<td>Customer Name:</td>
<td> <input name="custName" type="text" /></td>
</tr>
<tr>
<td>Customer Address:</td>
<td> <input name="custAddress" type="text" /></td>
</tr>
<tr>
<td><input type="submit" value="Add Customer" /></td>
<td><input type="reset" value="Reset" /></td>
</tr>
</tbody>
</table>

Step-9). Now write the following kind of “web.xml” file inside “home/userone/RestfulService_With_CDI_AS7/src” directord make sure that you are using the web.xml 3.0 version XSD (web-app_3_0.xsd) declaration in your web.xml file as following


        javax.ws.rs.core.Application
        javax.ws.rs.core.Application

        javax.ws.rs.core.Application
        /*

Step-10). Now we will write the ANT “build.xml” file inside “home/userone/RestfulService_With_CDI_AS7” directory in order to build and deploy and test our WebService .


           <!-- Need to place at lease one empty "beans.xml" file inside WEB-INF -->

Step-11). 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%
.

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

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

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

build:
    [mkdir] Created dir: /userone/RestfulService_With_CDI_AS7/tmp/WEB-INF/classes
    [javac] Compiling 5 source files to /userone/RestfulService_With_CDI_AS7/tmp/WEB-INF/classes
     [copy] Copying 1 file to /userone/RestfulService_With_CDI_AS7/tmp
     [copy] Copying 1 file to /userone/RestfulService_With_CDI_AS7/tmp
     [copy] Copying 1 file to /userone/RestfulService_With_CDI_AS7/tmp/WEB-INF/classes
     [copy] Copying 1 file to /userone/RestfulService_With_CDI_AS7/tmp/WEB-INF/classes
     [copy] Copying 1 file to /userone/RestfulService_With_CDI_AS7/tmp/WEB-INF
      [jar] Building jar: /userone/RestfulService_With_CDI_AS7/tmp/RestServiceWithCDI.war
     [copy] Copying 1 file to /userone/RestfulService_With_CDI_AS7/build

deploy:
     [echo] *******************  Deploying the WAR file RestServiceWithCDI.war *********************
     [echo] ********** build/RestServiceWithCDI.war to /home/userone/jboss-as-7.1.1.Final/standalone/deployments **********
     [copy] Copying 1 file to /home/userone/jboss-as-7.1.1.Final/standalone/deployments
     [echo] *******************  Deployed Successfully   *********************

BUILD SUCCESSFUL
Total time: 2 seconds

Testing The RestEasy WebService from WebBrowser

Step-13). Once the WebService is deployed successfully you can access it using the following URL: “http://localhost:8080/RestServiceWithCDI//index.jsp” As following:

RestEasyWebService_CDI_Inserting Customer Data

If you want to access all the Customers Details then access te following URL “http://localhost:8080/RestServiceWithCDI/test/customers/all” :

RestEasyWebService_With_CDI_Retrieving all Customers Record

Writing and Testing a Pure RestEasy WebService Client

Step-13). Now we are going to use our own Standalone RestEasy WebService Client in order to access the WebService. So write program with name “RestEasyClient.java” inside “home/userone/RestfulService_With_CDI_AS7/src” directory as following:

package client;
import java.io.*;
import javax.ws.rs.core.MediaType;
import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;

public class RestEasyClient
{
      public static void main(String ar[]) throws Exception
       {
        String url="http://localhost:8080/RestServiceWithCDI/test/customers/all";
        MediaType mediaType=MediaType.APPLICATION_XML_TYPE;
        String result = "";

        try
        {
            ClientRequest request = new ClientRequest(url);
            request.accept(mediaType);
            ClientResponse response = request.get(String.class);
            if (response.getStatus() != 200)
            {
                System.out.println("***** BAD RESPONSE *****");
                throw new RuntimeException("Request Processing Failed with HTTP status: "+ response.getStatus());
            }

            BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(response.getEntity().getBytes())));
            String output = null;
            while ((output = br.readLine()) != null)
            {
                result = result+output+"n";
            }

            result=result.replaceAll("><",">n<");
            System.out.println("nn********** RESULT **********n"+result);
        }
        catch (Exception e)
        {
            System.err.println("nt Exception Occured: "+e);
            e.printStackTrace();
        }
    }
}

Step-14). Now run the command “ant client” in order compile and run the Client program from the following directory “home/userone/RestfulService_With_CDI_AS7” as following:

[userone@localhost RestfulService_With_CDI_AS7]$ ant client
Buildfile: build.xml

client:
     [echo] *******************  Client Accessing RestEasy Service *********************
    [javac] Compiling 6 source files to /NotBackedUp/Downloads/RestfulService_With_CDI_AS7/build
      log4j:WARN No appenders could be found for logger (org.jboss.resteasy.plugins.providers.DocumentProvider).
      log4j:WARN Please initialize the log4j system properly.
      log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
      
      
      ********** RESULT **********
      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <customers>
      <customer>
      <address>Bombay, India</address>
      <id>1111</id>
      <name>CustomerOne</name>
      </customer>
      <customer>
      <address>Pune, India</address>
      <id>2222</id>
      <name>CustomerTwo</name>
      </customer>
      <customer>
      <address>Bangalore, India</address>
      <id>3333</id>
      <name>CustomerThree</name>
      </customer>
      <customer>
      <address>Pune, India</address>
      <id>8888</id>
      <name>MiddlewareMagic</name>
      </customer>
      </customers>
      

BUILD SUCCESSFUL
Total time: 3 seconds

.
.
Thanks 🙂
Middleware Magic Team


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