Tag: JMS

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 🙂


Accessing JBossAS7 HornetQ Related statistics using JMX remotely

Hi,

During initial builds of JBoss AS7 the MBean access methodology was kee changing, even the JMX subsystem XSD “jboss-as-jmx_1_1.xsd” also changed a lot from JBossAS7.0 till JBossAS7.1.1 Final. So here we are going to see How can we access the JBoss HornetQ/messaging related MBeans Remotely & Programatically. Here are the following points which we will notice as part of this article:

Point-1). Accessing MBeans using the JBoss Remoting Port 4447 on JBoss AS7.1.1.Final. In our previos demo (http://middlewaremagic.com/jboss/?p=1846) JMX code we used Native management Port 9999 in order to access the MBeans remotely. Now we will use 4447 port to do the same.

Point-2). The jmx subsystem inside our JBoss configuration file like “standalone-full.xml” should look something like following:

        <subsystem xmlns="urn:jboss:domain:jmx:1.1">
            <show-model value="true"/>
             <remoting-connector  use-management-endpoint="false" />
        </subsystem>

Here If the value of “use-management-endpoint” is “false” then this connector will use the remoting port 4447 for the jmx operations.
Point-3). Connecting to JBoss AS7 using JConsole Remotely.

Point-4). Connecting to JBoss AS7 using VisualVM Remotely.

Accessing HornetQ related MBeans Programatically Remotely/Locally

Step-1). As we know that messaging subsystem is available in “standalone-full.xml” or “standalong-full-ha.xml” profiles so after making the changes in oyur configuration file as mentioned in Point-2), Start your JBoss AS7.1.1 Final like following

     ./standalone.sh  -c standalone-full.xml -b 10.10.10.10  -bmanagement 10.10.10.10

Here wec can see that you can start JBossAS7 in a particular Bind address as well. “-b” option can be used to define the Public Interface bind address, where as “-bmanagement” is used to assign a same or different Bind Address for the Management Interface. To maintain security of your Management Interaface you can run it in a secured Host address or in localhost using -bmanagement.

Step-2). Write a Simple Class “JMSAccess.java” inside “/home/userone/JmxDemo/” as following:

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.*;

public class JMSAccess {
    public static void main(String[] args) throws Exception {
        String host = "localhost";  // Your JBoss Bind Address default is localhost
        int port = 4447;  // JBoss remoting port

        /*
          4447 can be enabled in your JBoss Configuration file with the help of the following configuration in your JBoss configuration file
          <subsystem xmlns="urn:jboss:domain:jmx:1.1">
              <show-model value="true"/>
               <remoting-connector  use-management-endpoint="false" />
          </subsystem>
        */

        String urlString ="service:jmx:remoting-jmx://" + host + ":" + port;
        System.out.println("		nnt****  urlString: "+urlString);

        JMXServiceURL serviceURL = new JMXServiceURL(urlString);
        JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceURL, null);
        MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();


        ObjectName objectName=new ObjectName("jboss.as:subsystem=messaging,hornetq-server=default");

        Integer threadPoolMaxSize=(Integer)connection.getAttribute(objectName, "threadPoolMaxSize");
        Boolean clustered=(Boolean)connection.getAttribute(objectName, "clustered");
        Boolean createBindingsDir=(Boolean)connection.getAttribute(objectName, "createBindingsDir");
        Long journalBufferSize=(Long)connection.getAttribute(objectName, "journalBufferSize");
        Long securityInvalidationInterval=(Long)connection.getAttribute(objectName, "securityInvalidationInterval");
        Boolean messageCounterEnabled=(Boolean)connection.getAttribute(objectName, "messageCounterEnabled");
        Integer journalCompactMinFiles=(Integer)connection.getAttribute(objectName, "journalCompactMinFiles");
        String journalType=(String)connection.getAttribute(objectName, "journalType");
        Boolean journalSyncTransactional=(Boolean)connection.getAttribute(objectName, "journalSyncTransactional");
        Integer scheduledThreadPoolMaxSize=(Integer)connection.getAttribute(objectName, "scheduledThreadPoolMaxSize");
        Boolean securityEnabled=(Boolean)connection.getAttribute(objectName, "securityEnabled");
        String jmxDomain=(String)connection.getAttribute(objectName, "jmxDomain");
        Long transactionTimeout=(Long)connection.getAttribute(objectName, "transactionTimeout");
        String clusterPassword=(String)connection.getAttribute(objectName, "clusterPassword");
        Boolean createJournalDir=(Boolean)connection.getAttribute(objectName, "createJournalDir");
        Long messageCounterSamplePeriod=(Long)connection.getAttribute(objectName, "messageCounterSamplePeriod");
        Boolean persistenceEnabled=(Boolean)connection.getAttribute(objectName, "persistenceEnabled");
        Boolean allowFailback=(Boolean)connection.getAttribute(objectName, "allowFailback");
        Long transactionTimeoutScanPeriod=(Long)connection.getAttribute(objectName, "transactionTimeoutScanPeriod");
        Boolean jmxManagementEnabled=(Boolean)connection.getAttribute(objectName, "jmxManagementEnabled");
        String securityDomain=(String)connection.getAttribute(objectName, "securityDomain");
        Long serverDumpInterval=(Long)connection.getAttribute(objectName, "serverDumpInterval");	
        Long failbackDelay=(Long)connection.getAttribute(objectName, "failbackDelay");
        Integer idCacheSize=(Integer)connection.getAttribute(objectName, "idCacheSize");
        Long messageExpiryScanPeriod=(Long)connection.getAttribute(objectName, "messageExpiryScanPeriod");
        Boolean wildCardRoutingEnabled=(Boolean)connection.getAttribute(objectName, "wildCardRoutingEnabled");
        Integer messageCounterMaxDayHistory=(Integer)connection.getAttribute(objectName, "messageCounterMaxDayHistory");
        Boolean started=(Boolean)connection.getAttribute(objectName, "started");


        System.out.println("	threadPoolMaxSize              = "+threadPoolMaxSize);
        System.out.println("	clustered                      = "+clustered);
        System.out.println("	createBindingsDir              = "+createBindingsDir);
        System.out.println("	journalBufferSize              = "+journalBufferSize);
        System.out.println("	securityInvalidationInterval   = "+securityInvalidationInterval);
        System.out.println("	messageCounterEnabled          = "+messageCounterEnabled);
        System.out.println("	journalType                    = "+journalType);
        System.out.println("	journalSyncTransactional       = "+journalSyncTransactional);
        System.out.println("	scheduledThreadPoolMaxSize     = "+scheduledThreadPoolMaxSize);
        System.out.println("	securityEnabled                = "+securityEnabled);
        System.out.println("	jmxDomain                      = "+jmxDomain);
        System.out.println("	transactionTimeout             = "+transactionTimeout);
        System.out.println("	clusterPassword                = "+clusterPassword);
        System.out.println("	createJournalDir               = "+createJournalDir);
        System.out.println("	messageCounterSamplePeriod     = "+messageCounterSamplePeriod);
        System.out.println("	persistenceEnabled             = "+persistenceEnabled);
        System.out.println("	allowFailback                  = "+allowFailback);
        System.out.println("	transactionTimeoutScanPeriod   = "+transactionTimeoutScanPeriod);
        System.out.println("	jmxManagementEnabled           = "+jmxManagementEnabled);
        System.out.println("	securityDomain                 = "+securityDomain);
        System.out.println("	serverDumpInterval             = "+serverDumpInterval);
        System.out.println("	failbackDelay                  = "+failbackDelay);
        System.out.println("	idCacheSize                    = "+idCacheSize);
        System.out.println("	messageExpiryScanPeriod        = "+messageExpiryScanPeriod);
        System.out.println("	wildCardRoutingEnabled         = "+wildCardRoutingEnabled);
        System.out.println("	messageCounterMaxDayHistory    = "+messageCounterMaxDayHistory);
        System.out.println("	started                        = "+started);


        jmxConnector.close();
    }
}

***NOTE***: In the above program we are trying to access various attributes present inside the ObjectName “jboss.web:type=Manager,path=/Log4jDemo,host=default-host” where “Log4jDemo” is the Context-Root of My WebApplication which i wanted to monitor. And th edefault Host-Name is “default-host”, In your case these values might be different so better use the JConsole to connect to JBoss Locally and then get the exact Object name from it.

Step-3). Now oipen a Terminal where we need to set the PATh and CLASSPATH like following:

For UNIX Based Operating System:

export PATH=/home/userone/jdk1.6.0_21/bin:$PATH
export CLASSPATH=/home/userone/jboss-as-7.1.1.Final/bin/client/jboss-client.jar:$CLASSPATH:.:

++++++++++++++++++++++++++++++++
For Windows Based Operating System

set PATH=C:jdk1.6.0_21bin;%PATH%
set CLASSPATH=c:jboss-as-7.1.1.Finalbinclientjboss-client.jar;%CLASSPATH%;.;

***NOTE***: It is must that your JMX Client should include the “jboss-client.jar” in it’s classpath as above.

Step-4). Now compile and run the above program:

[userone@localhost JmxDemo]$ javac JMSAccess.java
[userone@localhost JmxDemo]$ java JMSAccess

		

	****  urlString: service:jmx:remoting-jmx://localhost:4447
Jun 3, 2012 8:13:27 PM org.xnio.Xnio <clinit>
INFO: XNIO Version 3.0.3.GA
Jun 3, 2012 8:13:28 PM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.0.3.GA
Jun 3, 2012 8:13:28 PM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 3.2.3.GA
	threadPoolMaxSize              = 30
	clustered                      = false
	createBindingsDir              = true
	journalBufferSize              = null
	securityInvalidationInterval   = 10000
	messageCounterEnabled          = false
	journalType                    = ASYNCIO
	journalSyncTransactional       = true
	scheduledThreadPoolMaxSize     = 5
	securityEnabled                = true
	jmxDomain                      = org.hornetq
	transactionTimeout             = 300000
	clusterPassword                = CHANGE ME!!
	createJournalDir               = true
	messageCounterSamplePeriod     = 10000
	persistenceEnabled             = true
	allowFailback                  = true
	transactionTimeoutScanPeriod   = 1000
	jmxManagementEnabled           = false
	securityDomain                 = other
	serverDumpInterval             = -1
	failbackDelay                  = 5000
	idCacheSize                    = 2000
	messageExpiryScanPeriod        = 30000
	wildCardRoutingEnabled         = true
	messageCounterMaxDayHistory    = 10
	started                        = true

Accessing MBeans using JConsole LOCALLY

Start the Server and Open the “$JAVA_HOME/bin/jconsole” . jconsole will be able to detect any locally running JAVA process just connect to your JBoss process through it then you will be able to see the following kind of JBoss MBeans inside jconsole:

JConsole_WebContainerMBean_Access_JBossAS711

Accessing MBeans using JConsole REMOTELY

If you want to start your JConsole in order to connect to JBoss remotely then you should use the “jboss-as-7.1.1.Final/bin/jconsole.sh” script provided by JBoss, which does additional classpath settings which is required in order to use the JBoss implementation of the mbeans.

Oncew you run the “jboss-as-7.1.1.Final/bin/jconsole.sh” then you can choose the “Remote Process” option in “New Connection” wizard of your JConsole then you can use the following kind of address in order to connect to JBoss AS7

service:jmx:remoting-jmx://jbossHost:4447
OR
service:jmx:remoting-jmx://jbossHost:9999

The port can be decided based on the Point-2). mentioned above.

Accessing MBeans using VisualVM REMOTELY

There is a good script developed by “Mr. John O’Hara” as mentioned in the community link: https://community.jboss.org/thread/196428 Which can be used to connect to JBoss using VisualVM.

https://github.com/johnaoahra80/jboss-as-tool-integration/blob/master/visualvm/visualvm.sh

For below script all the credit goes to “Mr. John O’Hara”


#!/bin/sh

DIRNAME=`dirname "$0"`
GREP="grep"

# Use the maximum available, or set MAX_FD != -1 to use that
MAX_FD="maximum"

# OS specific support (must be 'true' or 'false').
cygwin=false;
darwin=false;
linux=false;
case "`uname`" in
    CYGWIN*)
        cygwin=true
        ;;

    Darwin*)
        darwin=true
        ;;

    Linux)
        linux=true
        ;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
    [ -n "$JBOSS_HOME" ] &&
        JBOSS_HOME=`cygpath --unix "$JBOSS_HOME"`
    [ -n "$JAVA_HOME" ] &&
        JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
    [ -n "$JAVAC_JAR" ] &&
        JAVAC_JAR=`cygpath --unix "$JAVAC_JAR"`
fi

# Setup JBOSS_HOME
RESOLVED_JBOSS_HOME=`cd "$DIRNAME/.."; pwd`
if [ "x$JBOSS_HOME" = "x" ]; then
    # get the full path (without any relative bits)
    JBOSS_HOME=$RESOLVED_JBOSS_HOME
else
 SANITIZED_JBOSS_HOME=`cd "$JBOSS_HOME"; pwd`
 if [ "$RESOLVED_JBOSS_HOME" != "$SANITIZED_JBOSS_HOME" ]; then
   echo "WARNING JBOSS_HOME may be pointing to a different installation - unpredictable results may occur."
   echo ""
 fi
fi
export JBOSS_HOME

# Setup the JVM
if [ "x$JAVA" = "x" ]; then
    if [ "x$JAVA_HOME" != "x" ]; then
        JAVA="$JAVA_HOME/bin/java"
    else
        JAVA="java"
    fi
fi

if [ "x$JBOSS_MODULEPATH" = "x" ]; then
    JBOSS_MODULEPATH="$JBOSS_HOME/modules"
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
    JBOSS_HOME=`cygpath --path --windows "$JBOSS_HOME"`
    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
    JBOSS_CLASSPATH=`cygpath --path --windows "$JBOSS_CLASSPATH"`
    JBOSS_ENDORSED_DIRS=`cygpath --path --windows "$JBOSS_ENDORSED_DIRS"`
    JBOSS_MODULEPATH=`cygpath --path --windows "$JBOSS_MODULEPATH"`
fi

CLASSPATH=""
# CLASSPATH=$CLASSPATH:$JAVA_HOME/lib/tools.jar

MODULES="org/jboss/remoting3/remoting-jmx org/jboss/remoting3 org/jboss/logging org/jboss/xnio org/jboss/xnio/nio org/jboss/sasl org/jboss/marshalling org/jboss/marshalling/river"

for MODULE in $MODULES
do
    for JAR in `cd "$JBOSS_MODULEPATH/$MODULE/main/" && ls -1 *.jar`
    do
        CLASSPATH="$CLASSPATH:$JBOSS_MODULEPATH/$MODULE/main/$JAR"
    done
done


jvisualvm -cp:a $CLASSPATH


.
.
Thanks 🙂
Middleware Magic Team


How to configure EJB3 MDBs on JBoss AS 7 for remote IBM Websphere MQ 7 ?

Almost a month back we had written an article Steps to Create A Remote Queue in WebSphere MQ 7 in which we had given the steps to configure a remote queue in WebSphere MQ and in the article How to configure EJB3 MDBs on JBoss AS 5.1 for remote IBM Websphere MQ 7? which showed the steps to connect with WebSphere MQ using AS 5.1.

However in this article we would be doing the same but using JBoss AS 7.1.1 final which is the latest version of JBoss AS 7.  We would be sharing the configuration from JBoss AS 7.1.1 final side which would help everyone to consume messages from Websphere MQ 7 which is residing on a remote box. We will also see how can one send messages (i.e. using a JAVA standalone code) to a remote queue on Box-1 having Websphere MQ 7 and those messages can be received by the consumer (i.e. using EJB3 MDB deployed on JBoss) from Box-2 which is a very basic scenario in most of the people.

The main concept for this is that we would be sending messages to the remote queue of Websphere MQ 7 on box-1 and on box-2 we would be creating a resource adapter which would be using wmq.jmsra.rar to communicate with Websphere MQ having the queue on box-1. Using the same resource adapter and Websphere MQ’s hostName, port, queueManager, destination and transportType in the MDB we would be able to consume message from box-2 easily.

In Box-1 (10.10.10.10)

Lets say you have your Websphere MQ 7 running in this box and you can configure the remote queue in MQ 7 by following the steps given in the below article

Steps to Create A Remote Queue in WebSphere MQ 7

In Box-2 (20.20.20.20)

Below are the steps to consume messages from WebShere MQ using a MDB deployed on JBoss AS 7.1.1 final and we would be using the “standalone-full.xml”

  1. In “standalone-full.xml” following things has to be done
    1. Need to add the resource adapter under subsystem
    2. Replace

       <subsystem xmlns="urn:jboss:domain:resource-adapters:1.0"/>
      

      With

      <subsystem xmlns="urn:jboss:domain:resource-adapters:1.0">
      	<resource-adapters>
      		<resource-adapter>
      			<archive>
      				wmq.jmsra.rar
      			</archive>
      		</resource-adapter>
      	</resource-adapters>
      </subsystem>
      
    3. Need to add the resource adapter reference under mdb
    4. Replace

      <mdb>
      	<resource-adapter-ref resource-adapter-name="hornetq-ra"/>
      	<bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
      </mdb>
      

      With

      <mdb>
      	<resource-adapter-ref resource-adapter-name="wmq.jmsra.rar"/>
      	<bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
      </mdb>
      
  2. Deploy “wmq.jmsra.rar” in the “/jboss-as-7.1.1.Final/standalone/deployments/” folder
  3. We would create a MDB now having the following ActivationConfigProperty and ResourceAdapter, which has to be kept “MDB_30.jar” file in the “/jboss-as-7.1.1.Final/standalone/deployments/” folder
    1. Create a folder called “MDB_30.jar
    2. Inside “MDB_30.jar” create a “MyMDB.java” file and update this file with the below details
    3. import javax.ejb.*;
      import javax.jms.Message;
      import javax.jms.TextMessage;
      import javax.jms.JMSException;
      import javax.ejb.MessageDriven;
      import javax.jms.MessageListener;
      import javax.ejb.ActivationConfigProperty;
      import org.jboss.ejb3.annotation.ResourceAdapter;
      
      @MessageDriven( name="MyMDB",
              activationConfig = 
              { 
                  @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"),
                  @ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "false"),
                  @ActivationConfigProperty(propertyName = "hostName", propertyValue = "MQ.HOST.NAME"),
                  @ActivationConfigProperty(propertyName = "port", propertyValue = "MQ.PORT"),
                  @ActivationConfigProperty(propertyName = "channel", propertyValue = "MQ.CHANNEL.NAME"),
                  @ActivationConfigProperty(propertyName = "queueManager", propertyValue = "MQ.QUEUE.MANAGER"),
                  @ActivationConfigProperty(propertyName = "destination", propertyValue = "MQ.QUEUE.NAME"),
                  @ActivationConfigProperty(propertyName = "transportType", propertyValue = "MQ.CLIENT")
              }) 
      @ResourceAdapter(value = "wmq.jmsra.rar")
      @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
      
      public class MyMDB implements MessageListener{
      
          public void onMessage(Message message) {
              TextMessage textMessage = (TextMessage) message;
              try {
                  System.out.println("nnt Message Received by MDB : "+ textMessage.getText());
              } catch (JMSException e) {
                  e.printStackTrace();
              }
          }
      }
      
    4. Once every thing has been put at its place, then you compile the MyMDB.java code and if you want then you can also create an JAR archive file for above folder

After following the above given steps, we have successfully configured all the setting from JBoss end. Now its time to test our configuration by following the below steps.

Testing

  1. Create a Directory somewhere in your file system like: “/urs/JBoss/Queue” to write the QueueSend.java and as we have an MDB we would not need a QueueReceive.java programs.
  2. In QueueSend.java copy the below program
    import java.io.*;
    import java.io.*;
    import java.util.Hashtable;
    import javax.jms.JMSException;
    import javax.jms.Queue;
    import javax.jms.QueueConnection;
    import javax.jms.QueueConnectionFactory;
    import javax.jms.QueueSender;
    import javax.jms.QueueSession;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class QueueSend
    {
    public final static String JNDI_FACTORY="com.ibm.mq.jms.context.WMQInitialContextFactory";
    
    //*************** Connection Factory JNDI name *************************
    public final static String JMS_FACTORY="MyRemoteMQMgr"; 
    
    //*************** Queue Factory JNDI name *************************
    public final static String QUEUE="MyRemoteQueue";
    
    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_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();
    }
    
    public void send(String message) throws JMSException {
    msg.setText(message);
    qsender.send(msg);
    }
    
    public void close() throws JMSException {
    qsender.close();
    qsession.close();
    qcon.close();
    }
    
    public static void main(String[] args) throws Exception {
    if (args.length != 1) {
    System.out.println("Usage: java QueueSend URL");
    return;
    }
    InitialContext ic = getInitialContext(args[0]);
    QueueSend qs = new QueueSend();
    qs.init(ic, QUEUE);
    readAndSend(qs);
    qs.close();
    }
    
    private static void readAndSend(QueueSend qs) throws IOException, JMSException
    {
    String line="Test Message Body with counter = ";
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    boolean readFlag=true;
    System.out.println("ntStart Sending Messages (Enter QUIT to Stop):n");
    while(readFlag)
    {
    System.out.print("<Msg_Sender> ");
    String msg=br.readLine();
    if(msg.equals("QUIT") || msg.equals("quit"))
    {
    qs.send(msg);
    System.exit(0);
    }
    qs.send(msg);
    System.out.println();
    }
    br.close();
    }
    
    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);
    return new InitialContext(env);
    }
    }
    
  3. Now open just 1 – command prompt and run the “. ./setMQ_CLASSPATH.sh” by adding two DOTs separated by a single space, in both the prompts to set the Environment (PATH & CLASSPATH).
  4. Note: You would need the following jar files from Websphere MQ side to run the above program, hence change the path given in the below script under MQ_LIB

    1. dhbcore.jar
    2. mqcontext.jar
    3. com.ibm.mq.jar
    4. com.ibm.mqjms.jar
    5. com.ibm.mq.pcf.jar
    6. com.ibm.mq.jmqi.jar
    7. com.ibm.mq.headers.jar
    8. com.ibm.mq.commonservices.jar

    setMQ_CLASSPATH.sh

    #!/bin/sh
    
    echo "Exporting CLASSPATH for IBM MQ...."
    
    MQ_LIB=/home/urs/Remote_MQ/lib
    
    export CLASSPATH=$CLASSPATH:$MQ_LIB/com.ibm.mq.commonservices.jar:$MQ_LIB/com.ibm.mq.headers.jar:$MQ_LIB/com.ibm.mq.jmqi.jar:$MQ_LIB/com.ibm.mq.pcf.jar:$MQ_LIB/com.ibm.mqjms.jar:$MQ_LIB/dhbcore.jar:$MQ_LIB/mqcontext.jar:$MQ_LIB/com.ibm.mq.jar:.:
    echo "====================================="
    echo "CLASSPATH =" $CLASSPATH
    echo "====================================="
    
  5. Then compile the QueueSend.java programs.
  6. Now run the code with the following command
  7. Prompt-1

    java QueueSend 10.10.10.10:1415/MyRemoteChannel
     

Once everything is up and running properly you just have to send around few messages in “Prompt-1” and you would notice that those messages would be shown in shell on which the standalone-full is running which is on Box-2. Hence when you are sending a messages to the Websphere MQ 7 queue which is on Box-1 the same messages are been consumed by the MDB which is been deployed on standalone-full shell is running on Box-2.


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