deployment

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 🙂


Allow JBoss AS7 to reflect the changes made in the JSP files

Hi,

Many times in development mode when we work then it is desired that as soon as we make any changes in the JSP based applications the the changes should be immediately reflected in the browser. So in this article we will see what configuration changes we need to make in order to tell the “JBoss AS 7.0.1 Final” container to tell the same.

We can deploy a simple JSP based application inside the “/jboss-as-7.0.1.Final/standalone/deployments” directory and then when we make any changes inside the deployed applications JSP page then in order to tell JBoss to reflect those changes in the browser we need to add the following Tag inside the web subsystem tag “<subsystem xmlns=”urn:jboss:domain:web:1.0″ default-virtual-server=”default-host”>” as following:

        <subsystem xmlns="urn:jboss:domain:web:1.0" default-virtual-server="default-host">
            <configuration>
                <jsp-configuration development="true"/>
            </configuration>
            <connector name="http" protocol="HTTP/1.1" socket-binding="http" scheme="http"/>
            <virtual-server name="default-host" enable-welcome-root="true">
                <alias name="localhost"/>
                <alias name="example.com"/>
            </virtual-server>
        </subsystem>

NOTE: we added the [jsp-configuration development=”true”] tag inside the <configuration>
.
.
Thanks
Middleware Magic Team


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