JMS

Writing java based JMS Client for WildFly10 default ActiveMQ Artemis broker.

Hi,

The HornetQ codebase was donated to the Apache ActiveMQ project, and the HornetQ community joined to build a next-generation messaging broker. ActiveMQ Artemis includes many new features, and also retains protocol compatibility with the HornetQ broker. WildFly 10 includes this new exciting project as its JMS broker, and due to the protocol compatibility, it fully replaces the HornetQ project. So as part of this simple demo we will see how we can connect to the ActiveMQ broker present inside the WildFLy10 via Standalone java based client code using standard JMS APIs.

Find more about “Apache ActiveMQ Artemis” in http://hornetq.blogspot.in/2015/06/hornetq-apache-donation-and-apache.html
AND
http://activemq.apache.org/artemis/

This article is basically clone of http://middlewaremagic.com/jboss/?p=2724 with just few WildFly 10.x specific changes related to WildFly JMS configuration, However the client code will remain same.

In this example we will be learning the following things:

1. How to create a simple JMS Queue in WildFly 10.x
2. How to create a user in ApplicationRealm and assign it to “guest” role.
3. How to create the InitialContext on the standalone client side.
4. What all jars are needed on the client side in order to lookup the JNDI resources deployed on WildFly.
5. Some common issues which you might encounter while running sample java code are explained in the other article: http://middlewaremagic.com/jboss/?p=2724

Creating A Simple JMS Queue on WildFly 10 side

Step-1). Start the WildFly 10 “full” profile (which has messaging) as following:

   $ cd /PATH/TO/wildfly-10.0.0.CR3-SNAPSHOT/bin
   $ ./standalone.sh -c standalone-full.xml

Step-2). Create a simple JMS user on WildFly 10 side and this user must belong to “guest” role. Please see the “messaging subsystem” configuration of “standalone-full.xml” to know more about “guest” role.
username: jmsuser
password: jmsuser@123
user role: guest
Realm: ApplicationRealm

   $ cd /PATH/TO/wildfly-10.0.0.CR3-SNAPSHOT/bin
   $ ./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.
Using realm 'ApplicationRealm' as discovered from the existing property files.
Username : jmsuser
User 'jmsuser' already exists and is enabled, would you like to... 
 a) Update the existing user password and roles 
 b) Disable the existing user 
 c) Type a new username
(a): a
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
 - The password should be different from the username
 - The password should not be one of the following restricted values {root, admin, administrator}
 - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
Password : 
Re-enter Password : 
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[guest]: guest
Updated user 'jmsuser' to file '/Users/jsensharma/NotBackedUp/Installed/wildfly-10.0.0.CR3-SNAPSHOT/standalone/configuration/application-users.properties'
Updated user 'jmsuser' to file '/Users/jsensharma/NotBackedUp/Installed/wildfly-10.0.0.CR3-SNAPSHOT/domain/configuration/application-users.properties'
Updated user 'jmsuser' with groups guest to file '/Users/jsensharma/NotBackedUp/Installed/wildfly-10.0.0.CR3-SNAPSHOT/standalone/configuration/application-roles.properties'
Updated user 'jmsuser' with groups guest to file '/Users/jsensharma/NotBackedUp/Installed/wildfly-10.0.0.CR3-SNAPSHOT/domain/configuration/application-roles.properties'
Is this new user going to be used for one AS process to connect to another AS process? 
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value="am1zdXNlckAxMjM=" />

Step-3). Creating a simple JMS Queue using the WildFly CLI command line utility. NOTE the JNDI name should contain “java:/jboss/exported” prefix or else the JMS queue will can not be looked up remotely.

   $ cd /PATH/TO/wildfly-10.0.0.CR3-SNAPSHOT/bin
   $ ./jboss-cli.sh -c
   
   [standalone@localhost:9990 /] /subsystem=messaging-activemq/server=default/jms-queue=TestQ/:add(entries=["java:/jboss/exported/jms/queue/TestQ"])
     {"outcome" => "success"}
     
   [standalone@localhost:9990 /] :reload
     {
       "outcome" => "success",
       "result" => undefined
     }

The generated XML snippet in the “standalone-full.xml” file will look like following:

        <subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
            <server name="default">
                <security-setting name="#">
                    <role name="guest" delete-non-durable-queue="true" create-non-durable-queue="true" consume="true" send="true"/>
                </security-setting>
                <address-setting name="#" message-counter-history-day-limit="10" page-size-bytes="2097152" max-size-bytes="10485760" expiry-address="jms.queue.ExpiryQueue" dead-letter-address="jms.queue.DLQ"/>
                <http-connector name="http-connector" endpoint="http-acceptor" socket-binding="http"/>
                <http-connector name="http-connector-throughput" endpoint="http-acceptor-throughput" socket-binding="http">
                    <param name="batch-delay" value="50"/>
                </http-connector>
                <in-vm-connector name="in-vm" server-id="0"/>
                <http-acceptor name="http-acceptor" http-listener="default"/>
                <http-acceptor name="http-acceptor-throughput" http-listener="default">
                    <param name="batch-delay" value="50"/>
                    <param name="direct-deliver" value="false"/>
                </http-acceptor>
                <in-vm-acceptor name="in-vm" server-id="0"/>
                <jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
                <jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>

                <!-- Newly added JMS Queue is Here -->
                <jms-queue name="TestQ" entries="java:/jboss/exported/jms/queue/TestQ"/>

                <connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>
                <connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>
                <pooled-connection-factory name="activemq-ra" transaction="xa" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm"/>
            </server>
        </subsystem>

NOTE: The “java:/jboss/exported” JNDI prefix is needed in the JNDI name here to ensure that a remote client (a client running outside of that JVM where the JNDI name is bound) can do the lookup.

Writing WildFly JMS Client

Step-4). Create a directory somewhere in your filesystem to place the project WildFly kms client project.

  $ mkdir WildFly10_JMS_Client
  $ mkdir -p WildFly10_JMS_Client/src/client

Step-5). Lets write the “WildFlyJmsQueueSender.java” program which will send some jms messages to the JMS Queue “TestQ” deployed on WildFly and Lets place it inside the “WildFly10_JMS_Client/src/client” as following:

package client;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;

//jms stuff
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;
import java.io.IOException;

public class WildFlyJmsQueueSender {
  public final static String JMS_CONNECTION_FACTORY_JNDI="jms/RemoteConnectionFactory";
  public final static String JMS_QUEUE_JNDI="jms/queue/TestQ";
  public final static String JMS_USERNAME="jmsuser";       //  The role for this user is "guest" in ApplicationRealm
  public final static String JMS_PASSWORD="jmsuser@123";  
  public final static String WILDFLY_REMOTING_URL="http-remoting://localhost:8080";

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

  public static void main(String[] args) throws Exception {
    InitialContext ic = getInitialContext();
    WildFlyJmsQueueSender queueSender = new WildFlyJmsQueueSender();
    queueSender.init(ic, JMS_QUEUE_JNDI);
    readAndSend(queueSender);
    queueSender.close();
  }

  public void init(Context ctx, String queueName) throws NamingException, JMSException {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_CONNECTION_FACTORY_JNDI);
    
    //  If you won't pass jms credential here then you will get 
    // [javax.jms.JMSSecurityException: HQ119031: Unable to validate user: null]    
    qcon = qconFactory.createQueueConnection(this.JMS_USERNAME, this.JMS_PASSWORD);   
    
    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,int counter) throws JMSException {
    msg.setText(message);
    msg.setIntProperty("counter", counter);
    qsender.send(msg);
  }

  public void close() throws JMSException {
    qsender.close();
    qsession.close();
    qcon.close();
  }

  private static void readAndSend(WildFlyJmsQueueSender wildFlyJmsQueueSender) throws IOException, JMSException {
    String line="Test Message Body with counter = ";
    for(int i=0;i<10;i++) {
          wildFlyJmsQueueSender.send(line+i,i);
          System.out.println("JMS Message Sent: "+line+i+"\n");
       }
  }

  private static InitialContext getInitialContext() throws NamingException {
     InitialContext context=null;
     try {
           Properties props = new Properties();
           props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
           props.put(Context.PROVIDER_URL, WILDFLY_REMOTING_URL);   // NOTICE: "http-remoting" and port "8080"
           props.put(Context.SECURITY_PRINCIPAL, JMS_USERNAME);
           props.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
           //props.put("jboss.naming.client.ejb.context", true);
           context = new InitialContext(props);	
	       System.out.println("\n\tGot initial Context: "+context);		
      } catch (Exception e) {
           e.printStackTrace();
      }
    return context;
  }
}

Step-6). Lets write the “WildFlyJmsQueueReceive.java” program which will consume messages from the JMS Queue deployed in WildFly and Lets place it inside the “WildFly10_JMS_Client/src/client” as following:

package client;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;

//jms stuff
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Message;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.IOException;

public class WildFlyJmsQueueReceive  implements MessageListener {
  public final static String JMS_CONNECTION_FACTORY_JNDI="jms/RemoteConnectionFactory";
  public final static String JMS_QUEUE_JNDI="jms/queue/TestQ";
  public final static String JMS_USERNAME="jmsuser";       //  The role for this user is "guest" in ApplicationRealm
  public final static String JMS_PASSWORD="jmsuser@123";  
  public final static String WILDFLY_REMOTING_URL="http-remoting://localhost:8080";


  private QueueConnectionFactory qconFactory;
  private QueueConnection qcon;
  private QueueSession qsession;
  private QueueReceiver qReceiver;
  private Queue queue;
  private TextMessage msg;
  private boolean quit = false;

  public static void main(String[] args) throws Exception {
    InitialContext ic = getInitialContext();
    WildFlyJmsQueueReceive wildflyJmsQueueReceive = new WildFlyJmsQueueReceive();
    wildflyJmsQueueReceive.init(ic, JMS_QUEUE_JNDI);
    System.out.println("JMS Ready To Receive Messages (To quit, send a \"quit\" message from QueueSender.class).");
    // Waiting until a "quit" message has been received.
    synchronized(wildflyJmsQueueReceive) {
         while (! wildflyJmsQueueReceive.quit) {
             try {
                   wildflyJmsQueueReceive.wait();
             }
             catch (InterruptedException ie) {
                   ie.printStackTrace();
             }
         }
     }
     wildflyJmsQueueReceive.close();
  }
  
  public void init(Context ctx, String queueName) throws NamingException, JMSException {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_CONNECTION_FACTORY_JNDI);

    //  If you won't pass jms credential here then you will get 
    // [javax.jms.JMSSecurityException: HQ119031: Unable to validate user: null]    
    qcon = qconFactory.createQueueConnection(this.JMS_USERNAME, this.JMS_PASSWORD);   
    
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    queue = (Queue) ctx.lookup(queueName);
    qReceiver = qsession.createReceiver(queue);
    qReceiver.setMessageListener(this);
    qcon.start();
  }

  public void onMessage(Message msg) {
     try {
           String msgText;
           if (msg instanceof TextMessage) {
              msgText = ((TextMessage)msg).getText();
           } else {
              msgText = msg.toString();
           }
           System.out.println("\n<Msg_Receiver> "+ msgText );
           if (msgText.equalsIgnoreCase("quit")) {
             synchronized(this) {
             	 quit = true;
             	 this.notifyAll(); // Notify main thread to quit
             }
           }
      } catch (JMSException jmse) {
          jmse.printStackTrace();
     }
  }

  public void close() throws JMSException {
    qReceiver.close();
    qsession.close();
    qcon.close();
  }
  
  private static InitialContext getInitialContext() throws NamingException {
     InitialContext context=null;
     try {
           Properties props = new Properties();
           props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
           props.put(Context.PROVIDER_URL, WILDFLY_REMOTING_URL);   // NOTICE: "http-remoting" and port "8080"
           props.put(Context.SECURITY_PRINCIPAL, JMS_USERNAME);
           props.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
           //props.put("jboss.naming.client.ejb.context", true);
           context = new InitialContext(props);	
	   System.out.println("\n\tGot initial Context: "+context);		
      } catch (Exception e) {
           e.printStackTrace();
      }
    return context;
  }
}

Step-7). In order to run the above program easily we are going to use ANT, However users can also run the above programs manually by adding the “$JBOSS_HOME/bin/client/jboss-client.jar” in the class path of the client. Here we will be writing the following ind of “build.xml” file inside the “WildFly10_JMS_Client” as following:

<project name="WildFly_Jms_Client" default="runSender">
<property name="jboss.home" value="/Users/jsensharma/NotBackedUp/Installed/wildfly-10.0.0.CR3-SNAPSHOT" />
<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="client.jar.name" value="wildfly_jms_client.jar" />

        <!-- Client Needs the following Jar to be present in the CLASSPATH including -->
        <path id="jboss.new.client.classpath">
           <fileset dir="${jboss.home}/bin/client">
               <include name="jboss-client.jar" />
           </fileset>  
        </path>

        <target name="runSender">
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
           <javac srcdir="${src.dir}/client" destdir="${tmp.dir}" includes="WildFlyJmsQueueSender.java" classpathref="jboss.new.client.classpath"/> 
           <copy file="${src.dir}/client/WildFlyJmsQueueSender.java" todir="${tmp.dir}/client"/>        
           <jar jarfile="${output.dir}/${client.jar.name}" basedir="${tmp.dir}" compress="true" />
           <delete dir="${tmp.dir}"/>
           <java classname="client.WildFlyJmsQueueSender" fork="true" classpathref="jboss.new.client.classpath">
               <classpath>
                  <pathelement location="${output.dir}/${client.jar.name}"/>
               </classpath>
           </java>
        </target>     

        <target name="runReceive">
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
           <javac srcdir="${src.dir}/client" destdir="${tmp.dir}" includes="WildFlyJmsQueueReceive.java" classpathref="jboss.new.client.classpath"/> 
           <copy file="${src.dir}/client/WildFlyJmsQueueReceive.java" todir="${tmp.dir}/client"/>        
           <jar jarfile="${output.dir}/${client.jar.name}" basedir="${tmp.dir}" compress="true" />
           <delete dir="${tmp.dir}"/>
           <java classname="client.WildFlyJmsQueueReceive" fork="true" classpathref="jboss.new.client.classpath">
               <classpath>
                  <pathelement location="${output.dir}/${client.jar.name}"/>
               </classpath>
           </java>
        </target>             
</project>

Running the WildFly 10 JMS client

Step-8). We can run the above ANT based kms client project simply by setting the ANT_HOME, JAVA_HOME and PATH as following :

For Unix Based OS:

$ export ANT_HOME=/PATH/TO/apache_ant_1.9.2
$ export JAVA_HOME=/PATH/TO/jdk1.8.0_60
$ export PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$PATH
$ cd /PATH/TO/WildFly10_JMS_Client


<strong>For Windows Based OS</strong>
$ set ANT_HOME=C:\PATH\TO\apache_ant_1.9.2
$ set JAVA_HOME=C:\PATH\TO\jdk1.8.0_60
$ set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%PATH%
$ cd C:\WildFly10_JMS_Client

Step-9). In the same above command prompt, Lets run the “WildFlyJmsQueueSender.java” program which will send to messages to the “TestQ” present on WildFly 8 as following :

$ ant runSender

Buildfile: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/build.xml

runSender:
    [mkdir] Created dir: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/tmp
    [javac] /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/build.xml:20: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/tmp
     [copy] Copying 1 file to /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/tmp/client
      [jar] Building jar: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/build/wildfly_jms_client.jar
   [delete] Deleting directory /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/tmp
      Nov 08, 2015 4:15:53 PM org.xnio.Xnio <clinit>
      INFO: XNIO version 3.3.2.Final
      Nov 08, 2015 4:15:53 PM org.xnio.nio.NioXnio <clinit>
      INFO: XNIO NIO Implementation Version 3.3.2.Final
      
      	Got initial Context: javax.naming.InitialContext@5e7f2a19
      Nov 08, 2015 4:15:53 PM org.jboss.remoting3.EndpointImpl <clinit>
      INFO: JBoss Remoting version 4.0.14.Final
      Nov 08, 2015 4:15:54 PM org.jboss.ejb.client.remoting.VersionReceiver handleMessage
      INFO: EJBCLIENT000017: Received server version 2 and marshalling strategies [river]
      Nov 08, 2015 4:15:54 PM org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver associate
      INFO: EJBCLIENT000013: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext@785ae27e, receiver=Remoting connection EJB receiver [connection=Remoting connection <5720171f>,channel=jboss.ejb,nodename=banl13bca644a-3]} on channel Channel ID dfdae415 (outbound) of Remoting connection 13c57d7d to localhost/127.0.0.1:8080
      SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
      SLF4J: Defaulting to no-operation (NOP) logger implementation
      SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
      Nov 08, 2015 4:15:54 PM org.jboss.ejb.client.EJBClient <clinit>
      INFO: JBoss EJB Client version 2.1.2.Final
      JMS Message Sent: Test Message Body with counter = 0
      
      JMS Message Sent: Test Message Body with counter = 1
      
      JMS Message Sent: Test Message Body with counter = 2
      
      JMS Message Sent: Test Message Body with counter = 3
      
      JMS Message Sent: Test Message Body with counter = 4
      
      JMS Message Sent: Test Message Body with counter = 5
      
      JMS Message Sent: Test Message Body with counter = 6
      
      JMS Message Sent: Test Message Body with counter = 7
      
      JMS Message Sent: Test Message Body with counter = 8
      
      JMS Message Sent: Test Message Body with counter = 9
      

BUILD SUCCESSFUL
Total time: 2 seconds

Step-10). In the same above command prompt, Lets run the “WildFlyJmsQueueReceive.java” program which will receive the jms messages which are present in the “TestQ” present on WildFly 8 as following :

$ ant runReceive
Buildfile: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/build.xml

runReceive:
    [mkdir] Created dir: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/tmp
    [javac] /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/build.xml:34: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/tmp
     [copy] Copying 1 file to /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/tmp/client
      [jar] Building jar: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/build/wildfly_jms_client.jar
   [delete] Deleting directory /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly10_JMS_Client/tmp
      Nov 08, 2015 4:28:23 PM org.xnio.Xnio <clinit>
      INFO: XNIO version 3.3.2.Final
      Nov 08, 2015 4:28:23 PM org.xnio.nio.NioXnio <clinit>
      INFO: XNIO NIO Implementation Version 3.3.2.Final
      Nov 08, 2015 4:28:23 PM org.jboss.remoting3.EndpointImpl <clinit>
      INFO: JBoss Remoting version 4.0.14.Final
      
      	Got initial Context: javax.naming.InitialContext@129458ea
      Nov 08, 2015 4:28:23 PM org.jboss.ejb.client.remoting.VersionReceiver handleMessage
      INFO: EJBCLIENT000017: Received server version 2 and marshalling strategies [river]
      Nov 08, 2015 4:28:23 PM org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver associate
      INFO: EJBCLIENT000013: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext@67d07b41, receiver=Remoting connection EJB receiver [connection=Remoting connection <533a0538>,channel=jboss.ejb,nodename=banl13bca644a-3]} on channel Channel ID c898038c (outbound) of Remoting connection 7a73ad16 to localhost/127.0.0.1:8080
      SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
      SLF4J: Defaulting to no-operation (NOP) logger implementation
      SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
      Nov 08, 2015 4:28:23 PM org.jboss.ejb.client.EJBClient <clinit>
      INFO: JBoss EJB Client version 2.1.2.Final
      JMS Ready To Receive Messages (To quit, send a "quit" message from QueueSender.class).
      
      <Msg_Receiver> Test Message Body with counter = 0
      
      <Msg_Receiver> Test Message Body with counter = 1
      
      <Msg_Receiver> Test Message Body with counter = 2
      
      <Msg_Receiver> Test Message Body with counter = 3
      
      <Msg_Receiver> Test Message Body with counter = 4
      
      <Msg_Receiver> Test Message Body with counter = 5
      
      <Msg_Receiver> Test Message Body with counter = 6
      
      <Msg_Receiver> Test Message Body with counter = 7
      
      <Msg_Receiver> Test Message Body with counter = 8
      
      <Msg_Receiver> Test Message Body with counter = 9

Issues which you may encounter

You might see some error/exceptions while running this demo in that case you can refer to the following article which explains some common issues which you might encounter while running this code. The following link also contains the remedies of those common exceptions.

Wildfly 8 based standalone JMS client code common issues and remedies ?
http://middlewaremagic.com/jboss/?p=2724

Monitoring JMS Queue using CLI

If we want to monitor the JMS Queue using jboss-cli.sh script then we can do it as following:

/subsystem=messaging-activemq/server=default/jms-queue=TestQ/:read-resource(recursive=true,include-runtime=true)
{
    "outcome" => "success",
    "result" => {
        "consumer-count" => 0,
        "dead-letter-address" => "jms.queue.DLQ",
        "delivering-count" => 0,
        "durable" => true,
        "entries" => ["java:/jboss/exported/jms/queue/TestQ"],
        "expiry-address" => "jms.queue.ExpiryQueue",
        "legacy-entries" => undefined,
        "message-count" => 20L,
        "messages-added" => 30L,
        "paused" => false,
        "queue-address" => "jms.queue.TestQ",
        "scheduled-count" => 0L,
        "selector" => undefined,
        "temporary" => false
    }
}

.
.
The Source code of this demo can be found at: (The code should remain same for WildFly 8/9/10)
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WildFly/JMS/WildFly_JMS_Client

.
.

Regards
Jay SenSharma


Wildfly 8 based standalone JMS client code common issues and remedies ?

Hi,

WildFly 8.x has become little bit old however it had bring some major changes in way we used to lookup resources in JBossAS7, hence as part of this article we will see what those changes were in the remoting based JNDI lookup approach.

In this article we will see what all different issues we may face while looking up a JMS resource from a Standalone java client and what al things we should keep in mind while doing so. We will also see what all jars are needed at the client classpath. Also how to creation the InitialContext object and which protocol should we use like “remoting” or “http-remoting” etc.

In this example we will be learning the following things:

1. How to create a simple JMS Queue on WildFly 8.x
2. How to create a user in ApplicationRealm and assign it to “guest” role.
3. How to create the InitialContext on the standalone client side.
4. What all jars are needed on the client side in order to lookup the JNDI resources deployed on WildFly.
5. Some common issues which you might encounter while running such java code.

Creating A Simple JMS Queue on WildFly 8.2 side

Step-1). Start the WildFly 8.2 “full” profile (which has messaging) as following:

   $ cd /PATH/TO/wildfly-8.2.1.Final/bin
   $ ./standalone.sh -c standalone-full.xml

Step-2). Create a simple JMS user on WildFly 8.2 side and this user must belong to “guest” role. Please see the “messaging subsystem” configuration of “standalone-full.xml” to know more about “guest” role.
username: jmsuser
password: jmsuser@123
user role: guest
Realm: ApplicationRealm

   $ cd /PATH/TO/wildfly-8.2.1.Final/bin
   $ ./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.
Using realm 'ApplicationRealm' as discovered from the existing property files.
Username : jmsuser
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
 - The password should not be one of the following restricted values {root, admin, administrator}
 - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
 - The password should be different from the username
Password :  jmsuser@123
Re-enter Password :  jmsuser@123
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[  ]: guest
About to add user 'jmsuser' for realm 'ApplicationRealm'
Is this correct yes/no? yes
Added user 'jmsuser' to file '/PATH/TO/wildfly-8.2.1.Final/standalone/configuration/application-users.properties'
Added user 'jmsuser' to file '/PATH/TO/wildfly-8.2.1.Final/domain/configuration/application-users.properties'
Added user 'jmsuser' with groups guest to file '/PATH/TO/wildfly-8.2.1.Final/standalone/configuration/application-roles.properties'
Added user 'jmsuser' with groups guest to file '/PATH/TO/wildfly-8.2.1.Final/domain/configuration/application-roles.properties'
Is this new user going to be used for one AS process to connect to another AS process? 
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value="am1zdXNlckAxMjM=" />

Step-3). Creating a simple JMS Queue using the WildFly CLI command line utility. NOTE the JNDI name should contain “java:/jboss/exported” prefix or else the JMS queue will can not be looked up remotely.

   $ cd /PATH/TO/wildfly-8.2.1.Final/bin
   $ ./jboss-cli.sh -c
   
   [standalone@localhost:9990 /] /subsystem=messaging/hornetq-server=default/jms-queue=TestQ/:add(entries=["java:/jboss/exported/jms/queue/TestQ"],durable=false)
     {"outcome" => "success"}
     
   [standalone@localhost:9990 /] :reload
     {
       "outcome" => "success",
       "result" => undefined
     }

The generated XML snippet in the “standalone-full.xml” file will look like following:

    <jms-destinations>
          <jms-queue name="ExpiryQueue">
                <entry name="java:/jms/queue/ExpiryQueue"/>
          </jms-queue>
          <jms-queue name="DLQ">
                <entry name="java:/jms/queue/DLQ"/>
          </jms-queue>
          <jms-queue name="TestQ">
               <entry name="java:/jboss/exported/jms/queue/TestQ"/>   <!-- Added JMS Destination -->
          </jms-queue>                   
    </jms-destinations>

NOTE: The “java:/jboss/exported” JNDI prefix is needed in the JNDI name here to ensure that a remote client (a client running outside of that JVM where the JNDI name is bound) can do the lookup.

Writing WildFly JMS Client

Step-4). Create a directory somewhere in your filesystem to place the project WildFly kms client project.

  $ mkdir WildFly_JMS_Client
  $ mkdir -p WildFly_JMS_Client/src/client

Step-5). Lets write the “WildFlyJmsQueueSender.java” program which will send some jms messages to the JMS Queue “TestQ” deployed on WildFly and Lets place it inside the “WildFly_JMS_Client/src/client” as following:

package client;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;

//jms stuff
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;
import java.io.IOException;

public class WildFlyJmsQueueSender {
  public final static String JMS_CONNECTION_FACTORY_JNDI="jms/RemoteConnectionFactory";
  public final static String JMS_QUEUE_JNDI="jms/queue/TestQ";
  public final static String JMS_USERNAME="jmsuser";       //  The role for this user is "guest" in ApplicationRealm
  public final static String JMS_PASSWORD="jmsuser@123";  
  public final static String WILDFLY_REMOTING_URL="http-remoting://localhost:8080";

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

  public static void main(String[] args) throws Exception {
    InitialContext ic = getInitialContext();
    WildFlyJmsQueueSender queueSender = new WildFlyJmsQueueSender();
    queueSender.init(ic, JMS_QUEUE_JNDI);
    readAndSend(queueSender);
    queueSender.close();
  }

  public void init(Context ctx, String queueName) throws NamingException, JMSException {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_CONNECTION_FACTORY_JNDI);
    
    //  If you won't pass jms credential here then you will get 
    // [javax.jms.JMSSecurityException: HQ119031: Unable to validate user: null]    
    qcon = qconFactory.createQueueConnection(this.JMS_USERNAME, this.JMS_PASSWORD);   
    
    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,int counter) throws JMSException {
    msg.setText(message);
    msg.setIntProperty("counter", counter);
    qsender.send(msg);
  }

  public void close() throws JMSException {
    qsender.close();
    qsession.close();
    qcon.close();
  }

  private static void readAndSend(WildFlyJmsQueueSender wildFlyJmsQueueSender) throws IOException, JMSException {
    String line="Test Message Body with counter = ";
    for(int i=0;i<10;i++) {
          wildFlyJmsQueueSender.send(line+i,i);
          System.out.println("JMS Message Sent: "+line+i+"\n");
       }
  }

  private static InitialContext getInitialContext() throws NamingException {
     InitialContext context=null;
     try {
           Properties props = new Properties();
           props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
           props.put(Context.PROVIDER_URL, WILDFLY_REMOTING_URL);   // NOTICE: "http-remoting" and port "8080"
           props.put(Context.SECURITY_PRINCIPAL, JMS_USERNAME);
           props.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
           //props.put("jboss.naming.client.ejb.context", true);
           context = new InitialContext(props);	
	       System.out.println("\n\tGot initial Context: "+context);		
      } catch (Exception e) {
           e.printStackTrace();
      }
    return context;
  }
}

Step-6). Lets write the “WildFlyJmsQueueReceive.java” program which will consume messages from the JMS Queue deployed in WildFly and Lets place it inside the “WildFly_JMS_Client/src/client” as following:

package client;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;

//jms stuff
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Message;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.IOException;

public class WildFlyJmsQueueReceive  implements MessageListener {
  public final static String JMS_CONNECTION_FACTORY_JNDI="jms/RemoteConnectionFactory";
  public final static String JMS_QUEUE_JNDI="jms/queue/TestQ";
  public final static String JMS_USERNAME="jmsuser";       //  The role for this user is "guest" in ApplicationRealm
  public final static String JMS_PASSWORD="jmsuser@123";  
  public final static String WILDFLY_REMOTING_URL="http-remoting://localhost:8080";


  private QueueConnectionFactory qconFactory;
  private QueueConnection qcon;
  private QueueSession qsession;
  private QueueReceiver qReceiver;
  private Queue queue;
  private TextMessage msg;
  private boolean quit = false;

  public static void main(String[] args) throws Exception {
    InitialContext ic = getInitialContext();
    WildFlyJmsQueueReceive wildflyJmsQueueReceive = new WildFlyJmsQueueReceive();
    wildflyJmsQueueReceive.init(ic, JMS_QUEUE_JNDI);
    System.out.println("JMS Ready To Receive Messages (To quit, send a \"quit\" message from QueueSender.class).");
    // Waiting until a "quit" message has been received.
    synchronized(wildflyJmsQueueReceive) {
         while (! wildflyJmsQueueReceive.quit) {
             try {
                   wildflyJmsQueueReceive.wait();
             }
             catch (InterruptedException ie) {
                   ie.printStackTrace();
             }
         }
     }
     wildflyJmsQueueReceive.close();
  }
  
  public void init(Context ctx, String queueName) throws NamingException, JMSException {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_CONNECTION_FACTORY_JNDI);

    //  If you won't pass jms credential here then you will get 
    // [javax.jms.JMSSecurityException: HQ119031: Unable to validate user: null]    
    qcon = qconFactory.createQueueConnection(this.JMS_USERNAME, this.JMS_PASSWORD);   
    
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    queue = (Queue) ctx.lookup(queueName);
    qReceiver = qsession.createReceiver(queue);
    qReceiver.setMessageListener(this);
    qcon.start();
  }

  public void onMessage(Message msg) {
     try {
           String msgText;
           if (msg instanceof TextMessage) {
              msgText = ((TextMessage)msg).getText();
           } else {
              msgText = msg.toString();
           }
           System.out.println("\n<Msg_Receiver> "+ msgText );
           if (msgText.equalsIgnoreCase("quit")) {
             synchronized(this) {
             	 quit = true;
             	 this.notifyAll(); // Notify main thread to quit
             }
           }
      } catch (JMSException jmse) {
          jmse.printStackTrace();
     }
  }

  public void close() throws JMSException {
    qReceiver.close();
    qsession.close();
    qcon.close();
  }
  
  private static InitialContext getInitialContext() throws NamingException {
     InitialContext context=null;
     try {
           Properties props = new Properties();
           props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
           props.put(Context.PROVIDER_URL, WILDFLY_REMOTING_URL);   // NOTICE: "http-remoting" and port "8080"
           props.put(Context.SECURITY_PRINCIPAL, JMS_USERNAME);
           props.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
           //props.put("jboss.naming.client.ejb.context", true);
           context = new InitialContext(props);	
	   System.out.println("\n\tGot initial Context: "+context);		
      } catch (Exception e) {
           e.printStackTrace();
      }
    return context;
  }
}

Step-7). In order to run the above program easily we are going to use ANT, However users can also run the above programs manually by adding the “$JBOSS_HOME/bin/client/jboss-client.jar” in the class path of the client. Here we will be writing the following ind of “build.xml” file inside the “WildFly_JMS_Client” as following:

<project name="WildFly_Jms_Client" default="runSender">
<property name="jboss.home" value="/Users/jsensharma/NotBackedUp/Installed/wildfly-8.2.1.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="client.jar.name" value="wildfly_jms_client.jar" />

        <!-- Client Needs the following Jar to be present in the CLASSPATH including -->
        <path id="jboss.new.client.classpath">
           <fileset dir="${jboss.home}/bin/client">
               <include name="jboss-client.jar" />
           </fileset>  
        </path>

        <target name="runSender">
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
           <javac srcdir="${src.dir}/client" destdir="${tmp.dir}"  includes="WildFlyJmsQueueSender.java" classpathref="jboss.new.client.classpath"/> 
           <copy file="${src.dir}/client/WildFlyJmsQueueSender.java" todir="${tmp.dir}/client"/>        
           <jar jarfile="${output.dir}/${client.jar.name}" basedir="${tmp.dir}" compress="true" />
           <delete dir="${tmp.dir}"/>
           <java classname="client.WildFlyJmsQueueSender" fork="true" classpathref="jboss.new.client.classpath">
               <classpath>
                  <pathelement location="${output.dir}/${client.jar.name}"/>
               </classpath>
           </java>
        </target>     

        <target name="runReceive">
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
           <javac srcdir="${src.dir}/client" destdir="${tmp.dir}"  includes="WildFlyJmsQueueReceive.java" classpathref="jboss.new.client.classpath"/> 
           <copy file="${src.dir}/client/WildFlyJmsQueueReceive.java" todir="${tmp.dir}/client"/>        
           <jar jarfile="${output.dir}/${client.jar.name}" basedir="${tmp.dir}" compress="true" />
           <delete dir="${tmp.dir}"/>
           <java classname="client.WildFlyJmsQueueReceive" fork="true" classpathref="jboss.new.client.classpath">
               <classpath>
                  <pathelement location="${output.dir}/${client.jar.name}"/>
               </classpath>
           </java>
        </target>             
</project>

Running the WildFly 8 JMS client

Step-8). We can run the above ANT based kms client project simply by setting the ANT_HOME, JAVA_HOME and PATH as following :

####### For  Unix Based OS:

$ export ANT_HOME=/PATH/TO/apache_ant_1.9.2
$ export JAVA_HOME=/PATH/TO/jdk1.8.0_60
$ export PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$PATH
$ cd /PATH/TO/WildFly_JMS_Client


######## For Windows Based OS
$ set ANT_HOME=C:\PATH\TO\apache_ant_1.9.2
$ set JAVA_HOME=C:\PATH\TO\jdk1.8.0_60
$ set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%PATH%
$ cd C:\WildFly_JMS_Client

Step-9). In the same above command prompt, Lets run the “WildFlyJmsQueueSender.java” program which will send to messages to the “TestQ” present on WildFly 8 as following :

$ ant runSender
Buildfile: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/build.xml

runSender:
    [mkdir] Created dir: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/tmp
    [javac] /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/build.xml:20: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/tmp
     [copy] Copying 1 file to /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/tmp/client
      [jar] Building jar: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/build/wildfly_jms_client.jar
   [delete] Deleting directory /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/tmp
      Nov 08, 2015 12:31:22 PM org.xnio.Xnio <clinit>
      INFO: XNIO version 3.3.0.Final
      Nov 08, 2015 12:31:22 PM org.xnio.nio.NioXnio <clinit>
      INFO: XNIO NIO Implementation Version 3.3.0.Final
      Nov 08, 2015 12:31:22 PM org.jboss.remoting3.EndpointImpl <clinit>
      INFO: JBoss Remoting version 4.0.7.Final
      
      	Got initial Context: javax.naming.InitialContext@aaf5002
      Nov 08, 2015 12:31:23 PM org.jboss.ejb.client.remoting.VersionReceiver handleMessage
      INFO: EJBCLIENT000017: Received server version 2 and marshalling strategies [river]
      Nov 08, 2015 12:31:23 PM org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver associate
      INFO: EJBCLIENT000013: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext@57a37ec1, receiver=Remoting connection EJB receiver [connection=Remoting connection <e244821>,channel=jboss.ejb,nodename=banl13bca644a-3]} on channel Channel ID fb329c1b (outbound) of Remoting connection 45106993 to localhost/127.0.0.1:8080
      Nov 08, 2015 12:31:23 PM org.jboss.ejb.client.EJBClient <clinit>
      INFO: JBoss EJB Client version 2.0.1.Final
      JMS Message Sent: Test Message Body with counter = 0
      
      JMS Message Sent: Test Message Body with counter = 1
      
      JMS Message Sent: Test Message Body with counter = 2
      
      JMS Message Sent: Test Message Body with counter = 3
      
      JMS Message Sent: Test Message Body with counter = 4
      
      JMS Message Sent: Test Message Body with counter = 5
      
      JMS Message Sent: Test Message Body with counter = 6
      
      JMS Message Sent: Test Message Body with counter = 7
      
      JMS Message Sent: Test Message Body with counter = 8
      
      JMS Message Sent: Test Message Body with counter = 9
      

BUILD SUCCESSFUL
Total time: 3 seconds

Step-10). In the same above command prompt, Lets run the “WildFlyJmsQueueReceive.java” program which will receive the jms messages which are present in the “TestQ” present on WildFly 8 as following :

$ ant runReceive
Buildfile: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/build.xml

runReceive:
    [mkdir] Created dir: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/tmp
    [javac] /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/build.xml:34: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/tmp
     [copy] Copying 1 file to /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/tmp/client
      [jar] Building jar: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/build/wildfly_jms_client.jar
   [delete] Deleting directory /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/WildFly_JMS_Client/tmp
      Nov 08, 2015 12:33:39 PM org.xnio.Xnio <clinit>
      INFO: XNIO version 3.3.0.Final
      Nov 08, 2015 12:33:39 PM org.xnio.nio.NioXnio <clinit>
      INFO: XNIO NIO Implementation Version 3.3.0.Final
      
      	Got initial Context: javax.naming.InitialContext@4a3e91e7
      Nov 08, 2015 12:33:39 PM org.jboss.remoting3.EndpointImpl <clinit>
      INFO: JBoss Remoting version 4.0.7.Final
      Nov 08, 2015 12:33:39 PM org.jboss.ejb.client.remoting.VersionReceiver handleMessage
      INFO: EJBCLIENT000017: Received server version 2 and marshalling strategies [river]
      Nov 08, 2015 12:33:39 PM org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver associate
      INFO: EJBCLIENT000013: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext@1c7f2b3c, receiver=Remoting connection EJB receiver [connection=Remoting connection <526d2bf>,channel=jboss.ejb,nodename=banl13bca644a-3]} on channel Channel ID db01bd53 (outbound) of Remoting connection 365655d3 to localhost/127.0.0.1:8080
      Nov 08, 2015 12:33:40 PM org.jboss.ejb.client.EJBClient <clinit>
      INFO: JBoss EJB Client version 2.0.1.Final
      JMS Ready To Receive Messages (To quit, send a "quit" message from QueueSender.class).
      
      <Msg_Receiver> Test Message Body with counter = 0
      
      <Msg_Receiver> Test Message Body with counter = 1
      
      <Msg_Receiver> Test Message Body with counter = 2
      
      <Msg_Receiver> Test Message Body with counter = 3
      
      <Msg_Receiver> Test Message Body with counter = 4
      
      <Msg_Receiver> Test Message Body with counter = 5
      
      <Msg_Receiver> Test Message Body with counter = 6
      
      <Msg_Receiver> Test Message Body with counter = 7
      
      <Msg_Receiver> Test Message Body with counter = 8
      
      <Msg_Receiver> Test Message Body with counter = 9

.
.
What next …… ? See below
.
.
.
.
.

Common Issues

In this section we will discuss some common issues which you will encounter while running this project:

Missing jboss-client.jar in classpath

On the wildly client side we need to make sure that the “$JBOSS_HOME/bin/client/jboss-client.jar” is added to the classpath. Else we will see the following kind of exception:

 javax.naming.NoInitialContextException: Cannot instantiate class: org.jboss.naming.remote.client.InitialContextFactory [Root exception is java.lang.ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory]
 	at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:674)
 	at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
 	at javax.naming.InitialContext.init(InitialContext.java:242)
 	at javax.naming.InitialContext.<init>(InitialContext.java:216)
 	at client.WildFlyJmsQueueSender.getInitialContext(Unknown Source)
 	at client.WildFlyJmsQueueSender.main(Unknown Source)
 Caused by: java.lang.ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory
 	at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
 	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
 	at java.security.AccessController.doPrivileged(Native Method)
 	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
 	at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
 	at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
 	at java.lang.Class.forName0(Native Method)
 	at java.lang.Class.forName(Class.java:274)
 	at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:72)
 	at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:61)
 	at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:671)
  	... 5 more
 Exception in thread "main" java.lang.NullPointerException
 	at client.WildFlyJmsQueueSender.init(Unknown Source)
 	at client.WildFlyJmsQueueSender.main(Unknown Source)
 Java Result: 1

Incorrect protocol issue

If you will use incorrect protocol to communicate with WildFly then while running the client you will receive the following kind of exception on the client side. The following error indicates that user is trying to use the JBossAS7 specific “remote:” protocol in WildFly where as in WildFly it is changed to “http-remoting”.

 Exception in thread "main" javax.naming.CommunicationException: Failed to connect to any server. Servers tried: [remote://localhost:4447 (java.net.ConnectException: Connection refused)]
 	at org.jboss.naming.remote.client.HaRemoteNamingStore.failOverSequence(HaRemoteNamingStore.java:244)
 	at org.jboss.naming.remote.client.HaRemoteNamingStore.namingStore(HaRemoteNamingStore.java:149)
 	at org.jboss.naming.remote.client.HaRemoteNamingStore.namingOperation(HaRemoteNamingStore.java:130)
 	at org.jboss.naming.remote.client.HaRemoteNamingStore.lookup(HaRemoteNamingStore.java:272)
 	at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:87)
 	at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:129)
 	at javax.naming.InitialContext.lookup(InitialContext.java:411)
 	at client.WildFlyJmsQueueSender.init(Unknown Source)
 	at client.WildFlyJmsQueueSender.main(Unknown Source)
 Java Result: 1

Incorrect InitialContext creation issue

While using the Remoting based approach for JNDI lookup if users are not creating the JNDI name properly then they may see the following error, So users need to see how they are creating the InitialContext using appropriate Context Factory class and the protocols and making sure that the “jboss-client.jar” is added to the classpath of the client. So please check the above code and create the InitialContext as described above for WildFly 8.

If you are planning to use the “EJB Client API” based approach to invoke the EJBs deployed on WildFly then please have a look at : http://middlewaremagic.com/jboss/?p=2744 to know how to create the InitialContext.

If you are planning to use the “Remote-Naming project” based approach to invoke the EJBs deployed on WildFly then please have a look at : http://middlewaremagic.com/jboss/?p=2704 to know how to create the InitialContext.

 Exception in thread "main" javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
 	at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
 	at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
 	at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:344)
 	at javax.naming.InitialContext.lookup(InitialContext.java:411)
 	at client.WildFlyJmsQueueSender.init(Unknown Source)
 	at client.WildFlyJmsQueueSender.main(Unknown Source)
      Java Result: 1

Not Passing the JMS user while getting JMS Connection

If we are not passing the jams user name and password while creation the connection we will see the following kind of exception (Notice the “user: null” issue)

So make sure to pass the JMS credentials while creation JMS Connection:

queueConnection = queueConnectionFactory(“jmsuser”, “jmsuser@123”);

WildFly Side
############
13:03:34,727 ERROR [org.hornetq.core.server] (default I/O-7) HQ224018: Failed to create session: HornetQSecurityException[errorType=SECURITY_EXCEPTION message=HQ119031: Unable to validate user: null]
	at org.hornetq.core.security.impl.SecurityStoreImpl.authenticate(SecurityStoreImpl.java:143)
	at org.hornetq.core.server.impl.HornetQServerImpl.createSession(HornetQServerImpl.java:1020)
	at org.hornetq.core.protocol.core.impl.HornetQPacketHandler.handleCreateSession(HornetQPacketHandler.java:149)
	at org.hornetq.core.protocol.core.impl.HornetQPacketHandler.handlePacket(HornetQPacketHandler.java:77)
	at org.hornetq.core.protocol.core.impl.ChannelImpl.handlePacket(ChannelImpl.java:641)
	at org.hornetq.core.protocol.core.impl.RemotingConnectionImpl.doBufferReceived(RemotingConnectionImpl.java:556)
	at org.hornetq.core.protocol.core.impl.RemotingConnectionImpl.bufferReceived(RemotingConnectionImpl.java:532)
	at org.hornetq.core.remoting.server.impl.RemotingServiceImpl$DelegatingBufferHandler.bufferReceived(RemotingServiceImpl.java:658)
	at org.hornetq.core.remoting.impl.netty.HornetQChannelHandler.channelRead(HornetQChannelHandler.java:73)
	at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338)
	at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:153)
	at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338)
	at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
	at org.xnio.netty.transport.AbstractXnioSocketChannel$ReadListener.handleEvent(AbstractXnioSocketChannel.java:435)
	at org.xnio.netty.transport.AbstractXnioSocketChannel$ReadListener.handleEvent(AbstractXnioSocketChannel.java:371)
	at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92) [xnio-api-3.3.0.Final.jar:3.3.0.Final]
	at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66) [xnio-api-3.3.0.Final.jar:3.3.0.Final]
	at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88) [xnio-nio-3.3.0.Final.jar:3.3.0.Final]
	at org.xnio.nio.WorkerThread.run(WorkerThread.java:539) [xnio-nio-3.3.0.Final.jar:3.3.0.Final]


Client Side
############
 Exception in thread "main" javax.jms.JMSSecurityException: HQ119031: Unable to validate user: null
  	at org.hornetq.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:399)
  	at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSessionInternal(ClientSessionFactoryImpl.java:891)
 	at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSessionInternal(ClientSessionFactoryImpl.java:800)
 	at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSession(ClientSessionFactoryImpl.java:337)
 	at org.hornetq.jms.client.HornetQConnection.authorize(HornetQConnection.java:719)
 	at org.hornetq.jms.client.HornetQConnectionFactory.createConnectionInternal(HornetQConnectionFactory.java:762)
 	at org.hornetq.jms.client.HornetQConnectionFactory.createQueueConnection(HornetQConnectionFactory.java:181)
 	at org.hornetq.jms.client.HornetQConnectionFactory.createQueueConnection(HornetQConnectionFactory.java:176)
 	at client.WildFlyJmsQueueSender.init(Unknown Source)
 	at client.WildFlyJmsQueueSender.main(Unknown Source)
 Caused by: HornetQSecurityException[errorType=SECURITY_EXCEPTION message=HQ119031: Unable to validate user: null]
 	... 10 more
 Java Result: 1

JMS user does not have correct role

If JMS user which we created in the ApplicationRealm does not have the correct role (in our case default role “guest”) then we will see the following exception while sending/receiving messages to/from JMS destinations.

 Exception in thread "main" javax.jms.JMSSecurityException: HQ119032: User: abcd doesnt have permission=SEND on address {2}
 	at org.hornetq.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:399)
 	at org.hornetq.core.client.impl.ClientProducerImpl.sendRegularMessage(ClientProducerImpl.java:334)
 	at org.hornetq.core.client.impl.ClientProducerImpl.doSend(ClientProducerImpl.java:304)
 	at org.hornetq.core.client.impl.ClientProducerImpl.send(ClientProducerImpl.java:135)
	at org.hornetq.jms.client.HornetQMessageProducer.doSendx(HornetQMessageProducer.java:524)
 	at org.hornetq.jms.client.HornetQMessageProducer.send(HornetQMessageProducer.java:187)
 	at client.WildFlyJmsQueueSender.send(Unknown Source)
 	at client.WildFlyJmsQueueSender.readAndSend(Unknown Source)
 	at client.WildFlyJmsQueueSender.main(Unknown Source)
 Caused by: HornetQSecurityException[errorType=SECURITY_EXCEPTION message=HQ119032: User: abcd doesnt have permission=SEND on address {2}]
 	... 9 more
 Java Result: 1

So make sure that the user (in above case “abcd”) has the proper role (like “guest” and belongs to correct realm like ApplicationRealm), better see the wildly configuration “standalone-full.xml” to see

                <security-settings>
                    <security-setting match="#">
                        <permission type="send" roles="guest"/>
                        <permission type="consume" roles="guest"/>
                        <permission type="createNonDurableQueue" roles="guest"/>
                        <permission type="deleteNonDurableQueue" roles="guest"/>
                    </security-setting>
                </security-settings>

The Source code of this demo can be found at:
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WildFly/JMS/WildFly_JMS_Client

.
.

Regards
Jay SenSharma


Using Apache Camel to send messages to WildFly 10 default ActiveMQ broker

Hi,

As we all know that the HornetQ codebase was donated to the Apache ActiveMQ project, and the HornetQ community joined to build a next-generation messaging broker. ActiveMQ Artemis includes many new features, and also retains protocol compatibility with the HornetQ broker. WildFly 10 includes this new exciting project as its JMS broker, and due to the protocol compatility, it fully replaces the HornetQ project. So as part of this simple demo we will see how we can connect to the ActiveMQ broker present inside the WildFLy10 via Standalone Apache Camel Route.

Find more about “Apache ActiveMQ Artemis” in http://hornetq.blogspot.in/2015/06/hornetq-apache-donation-and-apache.html
AND
http://activemq.apache.org/artemis/

Lets start WildFly 10 “standalone-full.xml” profile which has the “messaging-activemq” subsystem.

WildFLy 10 side configuration

Step-1). Now create a simple JMS Queue “TestQ” by running the following CLI command:

$ cd /PATH/TO/wildfly-10.0.0.CR3-SNAPSHOT/bin

$ ./jboss-cli.sh -c 
[standalone@localhost:9990 /] /subsystem=messaging-activemq/server=default/jms-queue=TestQ/:add(entries=["java:jboss/exported/TestQ"])
{"outcome" => "success"}

Following is the XML version of the same configuration which we just did via JBoss CLI:

        <subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
            <server name="default">
                <security-setting name="#">
                    <role name="guest" delete-non-durable-queue="true" create-non-durable-queue="true" consume="true" send="true"/>
                </security-setting>
                <address-setting name="#" message-counter-history-day-limit="10" page-size-bytes="2097152" max-size-bytes="10485760" expiry-address="jms.queue.ExpiryQueue" dead-letter-address="jms.queue.DLQ"/>
                <http-connector name="http-connector" endpoint="http-acceptor" socket-binding="http"/>
                <http-connector name="http-connector-throughput" endpoint="http-acceptor-throughput" socket-binding="http">
                    <param name="batch-delay" value="50"/>
                </http-connector>
                <in-vm-connector name="in-vm" server-id="0"/>
                <http-acceptor name="http-acceptor" http-listener="default"/>
                <http-acceptor name="http-acceptor-throughput" http-listener="default">
                    <param name="batch-delay" value="50"/>
                    <param name="direct-deliver" value="false"/>
                </http-acceptor>
                <in-vm-acceptor name="in-vm" server-id="0"/>
                <jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
                <jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
                
                <!-- NOTICE BELOW -->
                <jms-queue name="TestQ" entries="java:jboss/exported/TestQ"/>
                
                <connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>
                <connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>
                <pooled-connection-factory name="activemq-ra" transaction="xa" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm"/>
            </server>
        </subsystem>

==============

Step-2). Now next step is to add a user “jmsuser” with password “jmsuser@1” as part of “guest” role in the “ApplicationRealm” using the “$WildFly_Home/bin/add-user.sh” script

./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.
Using realm 'ApplicationRealm' as discovered from the existing property files.
Username : jmsuser
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
 - The password should be different from the username
 - The password should not be one of the following restricted values {root, admin, administrator}
 - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
Password : 
Re-enter Password : 
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[  ]: guest
About to add user 'jmsuser' for realm 'ApplicationRealm'
Is this correct yes/no? yes
Added user 'jmsuser' to file '/PATH/TO/wildfly-10.0.0.CR3-SNAPSHOT/standalone/configuration/application-users.properties'
Added user 'jmsuser' to file '/PATH/TO/wildfly-10.0.0.CR3-SNAPSHOT/domain/configuration/application-users.properties'
Added user 'jmsuser' with groups guest to file '/PATH/TO/wildfly-10.0.0.CR3-SNAPSHOT/standalone/configuration/application-roles.properties'
Added user 'jmsuser' with groups guest to file '/PATH/TO/wildfly-10.0.0.CR3-SNAPSHOT/domain/configuration/application-roles.properties'
Is this new user going to be used for one AS process to connect to another AS process? 
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? no

Apache Camel Route Setup

Step-3). Now we will create a very simple Apache Camel based route which will send some messages (XML files) present in the local file system to the ActiveMQ “TestQ”.

So create the following directory structure in your file system:

$ mkdir -p Camel_With_ActiveMQ_On_WildFly10/src/data
$ mkdir -p Camel_With_ActiveMQ_On_WildFly10/src/main/resources/META-INF/spring

Step-4). We will use the following kind of “Camel_With_ActiveMQ_On_WildFly10/pom.xml” file to define the necessary repositories and the camel version along with the necessary plugins.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

	<modelVersion>4.0.0</modelVersion>
	<groupId>middleware.magic</groupId>
	<artifactId>ApacheCamel_With_ActiveMQ_WilfFly</artifactId>
	<packaging>jar</packaging>
	<version>1.0</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<camel.version>2.15.3</camel.version>
		<wildfly.jms.client.bom>10.0.0.CR2</wildfly.jms.client.bom>
	</properties>

   <repositories>
        <repository>
            <id>jboss-enterprise-techpreview-group</id>
            <name>JBoss Enterprise Technology Preview  Maven Repository Group</name>
            <url>http://maven.repository.redhat.com/techpreview/all/</url>
            <layout>default</layout>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>jboss-public-repository-group</id>
            <name>JBoss Public Maven Repository Group</name>
            <url>https://repository.jboss.org/nexus/content/groups/public/</url>
            <layout>default</layout>
            <releases>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <updatePolicy>never</updatePolicy>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

	<dependencies>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-core</artifactId>
			<version>${camel.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-jms</artifactId>
			<version>${camel.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-spring</artifactId>
			<version>${camel.version}</version>
		</dependency>
		
		<!-- logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.5</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.5</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>


		<!-- testing -->
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-test-spring</artifactId>
			<version>${camel.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.wildfly</groupId>
			<artifactId>wildfly-jms-client-bom</artifactId>
			<version>${wildfly.jms.client.bom}</version>
			<type>pom</type>
		</dependency>
	</dependencies>

	<build>
		<defaultGoal>install</defaultGoal>

		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>

			<!-- allows the route to be ran via 'mvn camel:run' -->
			<plugin>
				<groupId>org.apache.camel</groupId>
				<artifactId>camel-maven-plugin</artifactId>
				<version>${camel.version}</version>
			</plugin>
		</plugins>
	</build>

</project>

Step-5). Now we will define the Camel Context inside the “Camel_With_ActiveMQ_On_WildFly10/src/main/resources/META-INF/spring/camel-context.xml” file. In this file we are referring to the “jmsQueueConnectionFactory” connection Factory and the “TestQ” which is present inside the Default Broker of WildFLy10:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <!-- Configuring Spring Jndi Template -->	
	<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
		<property name="environment">
			<props>
				<prop key="java.naming.factory.initial">org.jboss.naming.remote.client.InitialContextFactory</prop>
				<prop key="java.naming.provider.url">http-remoting://localhost:8080</prop>
			</props>
		</property>
	</bean>
	
    <!-- Getting ConnectionFactory using Spring Jndi Template -->	
	<bean id="jmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="jndiName">
			<value>jms/RemoteConnectionFactory</value>
		</property>
	</bean>

    <!-- Spring based Security Part, Those are the users created in ApplicationRealm of WildFLy -->
	<bean id="authenticatedConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
		<property name="targetConnectionFactory" ref="jmsQueueConnectionFactory" />
		<property name="username" value="jmsuser" />
		<property name="password" value="jmsuser@1" />
	</bean>


	<bean name="jms" class="org.apache.camel.component.jms.JmsComponent">
		<property name="connectionFactory" ref="authenticatedConnectionFactory" />
	</bean>

	<camelContext xmlns="http://camel.apache.org/schema/spring">
		<route>
			<from uri="file:src/data?noop=true" />  <!-- Any file placed in this dir will be send to TestQ -->
			<to uri="jms:TestQ" />
		</route>
	</camelContext>
</beans>

Step-6). Lets put some XML files like “Camel_With_ActiveMQ_On_WildFly10/src/data/message.xml” which will be sent to the ActiveMQ broker using the Camel Route. As our Apache Camel Route is using the “?noop=true” so it will keep scanning the “src/data” directory for any new file processing. So as soon as you put any file in this directory it will be processed.

<?xml version="1.0" encoding="UTF-8"?>
<company>
   <name>MiddlewareMagic</name>
   <country>India</country>
   <city>Bangalore</city>
</company>

Step-7). Open a terminal and build the above mentioned Maven project. and then run the camel context as following:

export M2_HOME=/PATH/TO/apache_maven_3.2.3

export PATH=$JAVA_HOME/bin:/PATH/TO/apache_maven_3.2.3/bin:$SOAPUI_HOME/bin:$PATH:

cd Camel_With_ActiveMQ_On_WildFly10

$ mvn clean install

$ mvn camel:run
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building ApacheCamel_With_ActiveMQ_WilfFly 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> camel-maven-plugin:2.15.3:run (default-cli) > test-compile @ ApacheCamel_With_ActiveMQ_WilfFly >>>
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ ApacheCamel_With_ActiveMQ_WilfFly ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ ApacheCamel_With_ActiveMQ_WilfFly ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ ApacheCamel_With_ActiveMQ_WilfFly ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /PATH/TO/Camel_With_ActiveMQ_On_WildFly10/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ ApacheCamel_With_ActiveMQ_WilfFly ---
[INFO] No sources to compile
[INFO] 
[INFO] <<< camel-maven-plugin:2.15.3:run (default-cli) < test-compile @ ApacheCamel_With_ActiveMQ_WilfFly <<<
[INFO] 
[INFO] --- camel-maven-plugin:2.15.3:run (default-cli) @ ApacheCamel_With_ActiveMQ_WilfFly ---
[INFO] Using org.apache.camel.spring.Main to initiate a CamelContext
[INFO] Starting Camel ...
[pache.camel.spring.Main.main()] MainSupport                    INFO  Apache Camel 2.15.3 starting
[pache.camel.spring.Main.main()] xnio                           INFO  XNIO version 3.3.2.Final
[pache.camel.spring.Main.main()] nio                            INFO  XNIO NIO Implementation Version 3.3.2.Final
[pache.camel.spring.Main.main()] remoting                       INFO  JBoss Remoting version 4.0.14.Final
[pache.camel.spring.Main.main()] SpringCamelContext             INFO  Apache Camel 2.15.3 (CamelContext: camel-1) is starting
[pache.camel.spring.Main.main()] ManagedManagementStrategy      INFO  JMX is enabled
[pache.camel.spring.Main.main()] DefaultTypeConverter           INFO  Loaded 183 type converters
[pache.camel.spring.Main.main()] SpringCamelContext             INFO  AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn this option off as it may improve performance.
[pache.camel.spring.Main.main()] SpringCamelContext             INFO  StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
[pache.camel.spring.Main.main()] FileEndpoint                   INFO  Endpoint is configured with noop=true so forcing endpoint to be idempotent as well
[pache.camel.spring.Main.main()] FileEndpoint                   INFO  Using default memory based idempotent repository with cache max size: 1000
[pache.camel.spring.Main.main()] SpringCamelContext             INFO  Route: route1 started and consuming from: Endpoint[file://src/data?noop=true]
[pache.camel.spring.Main.main()] SpringCamelContext             INFO  Total 1 routes, of which 1 is started.
[pache.camel.spring.Main.main()] SpringCamelContext             INFO  Apache Camel 2.15.3 (CamelContext: camel-1) started in 0.259 seconds

The “mvn camel:run” command will run the camel route and until the route is running any file which is placed inside the “Camel_With_ActiveMQ_On_WildFly10/src/data” directory will be processed by camel route (means will be send to the ActiveMQ Broker)

How to validate on WildFLy Side?

Try running the following “jboss-cli” command on the WildFly to list all the messages sent to the TestQ
List messages using CLI script:

[standalone@localhost:9990 /] /subsystem=messaging-activemq/server=default/jms-queue=TestQ:list-messages
{
    "outcome" => "success",
    "result" => [
        {
            "CamelFileLastModified" => 1393559256000L,
            "CamelFileParent" => "src/data",
            "JMSMessageID" => "ID:32212ff0-6b8b-11e5-8511-e3d2c5e4416f",
            "address" => "jms.queue.TestQ",
            "CamelFilePath" => "src/data/message1.xml",
            "JMSExpiration" => 0,
            "CamelFileLength" => 156,
            "JMSTimestamp" => 1444068129033L,
            "messageID" => 21,
            "JMSDeliveryMode" => "PERSISTENT",
            "CamelFileAbsolute" => false,
            "CamelFileName" => "message1.xml",
            "JMSPriority" => 4,
            "__AMQ_CID" => "32182f3d-6b8b-11e5-8511-e3d2c5e4416f",
            "CamelFileNameConsumed" => "message1.xml",
            "breadcrumbId" => "ID-BANL13bca644a-2-local-57971-1444068127436-0-1",
            "CamelFileRelativePath" => "message1.xml",
            "CamelFileAbsolutePath" => "/Camel_With_HornetQ/camelHornetq/src/data/message1.xml",
            "CamelFileNameOnly" => "message1.xml"
        },

SourceCode: Please find the source code of this project in MiddlewareMagic github repo:

https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WildFly/JMS/Camel_With_ActiveMQ_On_WildFly10

Thanks
Jay SenSharma


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