Tag: HornetQ

How to create custom Expiry Queue in JBoss AS 7.1.2 using CLI


Starting of this year we had shared a Working example of Expiry Queue in JBoss AS 5.1 which was using JBoss Messaging when JBoss AS 7 was not realised. However we all know that JBoss AS 7 is using HorrnetQ and in this article we would be sharing the steps on how to create a custom Expiry Queue for a particular queue and would be using the same working example but with few changes to get it working with JBossAS7

For this article we would be using JBoss AS 7.1.2 and the same concept would be used, which is setting up the expiry period for a messages (i.e. when setTimeToLive is been used in the code) and as per JMS specification which states that clients should not receive messages that have been expired which does not grantee that. Hence once the messages gets expiries they are been moved to the expiry queue which has been assigned to the given queue. Now these “expired” messages can later be consumed from the expiry destination for further inspection.

You can get the complete demo from this link : Demo Link

Features To Discuss

  1. We would be creating a queue using CLI
  2. Then creating a custom Expiry Queue and assign it to the newly created queue using CLI
  3. In this example we will send 1 message with a short time-to-live to a queue.
  4. We will wait for the message to expire and checks that the message is no longer in the queue it was sent to.

Steps to create a custom Expiry Queue in JBoss 7.1.2 using CLI

Using the below CLI file we are doing total 3 things at the same-time and that too with one command, now that’s called saving time 😉

  • Creating a Queue with a name MyQueue and having a remote enabled JNDI name /MyQueue which has a prefix as “java:jboss/exported”
  • Creating a custom Expiry Queue with a name MyExpiryQueue and having a local JDNI name /MyExpiryQueue
  • And configuring the custom Expiry Queue MyExpiryQueue with the queue MyQueue by creating a new address-setting particularly for MyQueue
  1. Create a file called MyExpiryQueue-add.cli in the bin folder of JBoss and copy the below content
  2. connect
    
    #Adding MyQueue
    /subsystem=messaging/hornetq-server=default/jms-queue=MyQueue/:add(entries=["java:jboss/exported/MyQueue"],durable=false)
    
    #Adding MyExpiryQueue
    /subsystem=messaging/hornetq-server=default/jms-queue=MyExpiryQueue/:add(entries=["java:/MyExpiryQueue"],durable=false)
    
    #Adding address-settings for MyQueue
    /subsystem=messaging/hornetq-server=default/address-setting=jms.queue.MyQueue/:add(expiry-address=jms.queue.MyExpiryQueue)
    
    
  3. Now we need to create a new Application User by running “${JBOSS_HOME}/bin/add-user.sh” script as following :
  4. [user@user 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.
    Realm (ApplicationRealm) :  ApplicationRealm
    Username : testuser
    Password : testpassword
    Re-enter Password : testpassword
    
    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 'testuser' for realm 'ApplicationRealm'
    
    Is this correct yes/no? yes
    
    Added user 'testuser' to file '/home/user/jboss-as-7.1.2.Final/standalone/configuration/application-users.properties'
    Added user 'testuser' to file '/home/user/jboss-as-7.1.2.Final/domain/configuration/application-users.properties'
    Added user 'testuser' with roles testrole to file '/home/user/jboss-as-7.1.2.Final/standalone/configuration/application-roles.properties'
    Added user 'testuser' with roles testrole to file '/home/user/jboss-as-7.1.2.Final/domain/configuration/application-roles.properties'
    
    
  5. Make sure that the JBoss AS 7.1.2 is running, in our case we started JBoss AS 7.1.2 standalone-full.xml profile.
  6. [user@user bin]$ ./standalone.sh -c standalone-full.xml
    
  7. Now you just have to run the below command to execute above three things
  8. [user@user bin]$ ./jboss-cli.sh --file=MyExpiryQueue-add.cli
    {"outcome" => "success"}
    {"outcome" => "success"}
    {"outcome" => "success"}
    [user@user bin]$
    

    Once your above CLI command is executed successfully you will notice the following in your JBossAS 7.1.2 configuration file “standalone-full.xml”:

    <address-settings>
        <address-setting match="#">
    	.
    	.
    	.
        </address-setting>
        <address-setting match="jms.queue.MyQueue">
           <expiry-address>jms.queue.MyExpiryQueue</expiry-address>
        </address-setting>
    </address-settings>
    .
    .
    .
    <jms-destinations>
        <jms-queue name="MyQueue">
            <entry name="java:/exported/MyQueue"/>
            <durable>false</durable>
        </jms-queue>
        <jms-queue name="MyExpiryQueue">
            <entry name="java:/MyExpiryQueue"/>
            <durable>false</durable>
        </jms-queue>
    </jms-destinations>
    
  9. That’s it !!! You are done configuring a simple queue with a custom ExpiryQueue. Let’s test this out using the sender and receiver Java code.

Testing

  1. Create a Directory somewhere in your file system like: “/urs/JBossAS7.1.2/HQ/Queue/MyExpiryQueue-test” to write the QueueSend.java and QueueReceive.java programs.
  2. In QueueSend.java copy the below program, where we are setting the first messages to live for 1s (1000ms) before expiration.
    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="org.jboss.naming.remote.client.InitialContextFactory";
    
    //*************** Connection Factory JNDI name *************************
    public final static String JMS_FACTORY="/jms/RemoteConnectionFactory";
    
    //*************** Remote enabled Queue JNDI name *************************
    public final static String QUEUE="/MyQueue";
    
    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);
    
    //*************** Creating Queue Connection using the UserName & Password *************************
    qcon = qconFactory.createQueueConnection("testuser","testpassword");   			//<------------- Change the UserName & Password
    
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    queue = (Queue) ctx.lookup(queueName);
    qsender = qsession.createSender(queue);
    
    //********* Messages sent by this sender will be live for 1s (1000ms) before expiration *********
    qsender.setTimeToLive(1000);
    
    msg = qsession.createTextMessage();
    qcon.start();
    }
    
    public void send(String message) throws JMSException {
    msg.setText(message);
    qsender.send(msg);
    System.out.println("Message="+message+ " Time to live ="+qsender.getTimeToLive());
    }
    
    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);
    
    //*************** UserName & Password for the Initial Context for JNDI lookup *************************
    env.put(Context.SECURITY_PRINCIPAL, "testuser");
    env.put(Context.SECURITY_CREDENTIALS, "testpassword");
    
    return new InitialContext(env);
    }
    }
    
  3. In QueueReceive.java copy the below program, if you notice that before we are creating the Receiver we are making sure that the program starts 5 seconds late so that the first message sent gets expired as its time to live is 1 second. So the first messages is never consumed and that messages is been moved to expiry queue. But other messages would get consumed as the consumer is up and listening to the MyQueue.
    import java.util.Hashtable;
    import javax.jms.*;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class QueueReceive implements MessageListener
    {
    public final static String JNDI_FACTORY="org.jboss.naming.remote.client.InitialContextFactory";
    
    //*************** Connection Factory JNDI name *************************
    public final static String JMS_FACTORY="/jms/RemoteConnectionFactory";
    
    //*************** Remote enabled Queue JNDI name *************************
    public final static String QUEUE="/MyQueue";
    
    private QueueConnectionFactory qconFactory;
    private QueueConnection qcon;
    private QueueSession qsession;
    private QueueReceiver qreceiver;
    private Queue queue;
    private boolean quit = false;
    
    public void onMessage(Message msg)
    {
    	try
    	{
    		String msgText;
    		if (msg instanceof TextMessage)
    		{
    			msgText = ((TextMessage)msg).getText();
    		}
    		else
    		{
    			msgText = msg.toString();
    		}
    
    		System.out.println("nt<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 init(Context ctx, String queueName) throws NamingException, JMSException
    {
    	try
    	{
    		qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
    
    		//*************** Creating Queue Connection using the UserName & Password *************************
    		qcon = qconFactory.createQueueConnection("testuser","testpassword");   			//<------------- Change the UserName & Password
    
    		qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    		queue = (Queue) ctx.lookup(queueName);
    
    		//********* Sleeping for 5's so that the message gets expired  ********
    		System.out.println("Sleeping for 5's till the message expire...");
    		Thread.sleep(5000);
    
    		qreceiver = qsession.createReceiver(queue);
    		qreceiver.setMessageListener(this);
    		qcon.start();
    	}
    	catch (InterruptedException jmse)
    	{
    		jmse.printStackTrace();
    	}
    
    }
    
    public void close()throws JMSException
    {
    qreceiver.close();
    qsession.close();
    qcon.close();
    }
    
    public static void main(String[] args) throws Exception
    {
    if (args.length != 1)
    {
    System.out.println("Usage: java QueueReceive URL");
    return;
    }
    InitialContext ic = getInitialContext(args[0]);
    QueueReceive qr = new QueueReceive();
    qr.init(ic, QUEUE);
    System.out.println("JMS Ready To Receive Messages (To quit, send a "quit" message from QueueSender.class).");
    
    synchronized(qr)
    {
    while (! qr.quit)
    {
    try
    {
    qr.wait();
    }
    catch (InterruptedException ie)
    {}
    }
    }
    qr.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);
    
    //*************** UserName & Password for the Initial Context for JNDI lookup *************************
    env.put(Context.SECURITY_PRINCIPAL, "testuser");
    env.put(Context.SECURITY_CREDENTIALS, "testpassword");
    
    return new InitialContext(env);
    }
    }
    
  4. Now open 2– command prompt and run the “. ./setJBossEnv.sh” by adding two DOTs separated by a single space, in both the prompts to set the Environment (PATH & CLASSPATH).
  5. setJBossEnv.sh

    #!/bin/sh
    echo "Exporting JBOSS_HOME...."
    export JBOSS_HOME=/Jboss/jboss-as-7.1.2.Final   #<---- Change as per your environment
    echo "JBOSS_HOME Exported....!!!"
    echo ""
    echo "Exporting JAVA_HOME...."
    export JAVA_HOME=/Jdk/jdk1.6.0_21    #<---- Change as per your environment
    echo "JBOSS_HOME Exported....!!!"
    echo ""
    echo "Exporting CLASSPATH...."
    export CLASSPATH=$JBOSS_HOME/bin/client/jboss-client.jar:$CLASSPATH:.:
    echo "CLASSPATH Exported....!!!"
    echo ""
    echo "Exporting PATH...."
    export PATH=$JAVA_HOME/bin:$PATH
    echo "PATH Exported....!!!"
    echo ""
    echo "========================================================================"
    echo "JBOSS_HOME = " $JBOSS_HOME
    echo ""
    echo "JAVA_HOME = " $JAVA_HOME
    echo ""
    echo "CLASSPATH = " $CLASSPATH
    echo ""
    echo "PATH = " $PATH
    echo "========================================================================"
    
  6. Then compile the QueueSend.java and QueueReceive.java programs.
  7. Now run the code with the following command
  8. Prompt-1

    java QueueSend remote://localhost:4447
     
  9. Now send one message when the QueueReceive is not started, this way the message which has sent to the MyQueue would have the Time To Live as 1′s second. But this time would not start till the QueueReceive has been startred
  10. Now start the QueueReceive using the below command
  11. Prompt-2

    java QueueReceive remote://localhost:4447
     
  12. Once the QueueReceive has been started for the first time it would sleep for 5 second, hence the message which was in the MyQueue would get expired as its time to live was 1 second, hence the messages would get moved to expire queue, which can be seen using two ways
  13. CLI

    [user@user bin]$ ./jboss-cli.sh -c /subsystem=messaging/hornetq-server=default/jms-queue=MyExpiryQueue/:count-messages
    {
        "outcome" => "success",
        "result" => 1L
    }
    

    OR

    Admin console path:
    Runtime – Status – JMS Destination – MyExpiryQueue – “Messages in Queue:”

  14. However other messages would get consumed as the consumer is up and listening to the MyQueue

How to create custom Dead Letter Queue in JBoss AS 7.1.2 using CLI


Starting of this year we had shared a Working example of Dead Letter Queue in JBoss AS 5.1 which was using JBoss Messaging when JBoss AS 7 was not realised. However we all know that JBoss AS 7 is using HorrnetQ and in this article we would be sharing the steps on how to create a custom DLQ for a particular queue and would be using the same working example but with few changes to get it working with JBossAS7

For this article we would be using JBoss AS 7.1.2 and the same concept would be used, which is after a specified unsuccessful delivery attempts (i.e. max-delivery-attempts in JBoss AS 7), the message is removed from the destination and moves it inside the defined custom Dead Letter Queue (DLQ) where the messages can be consumed for further investigation.

Features To Discuss

  1. We would be creating a queue using CLI
  2. Then creating a custom DLQ and assign it to the newly created queue using CLI
  3. In testing we would make sure that if a message is having a string as “Hello World”, then that message would be rolled backed after specified unsuccessful delivery attempts and would be moved in our custom created DLQ and other messages can be consumed without any issue.

Steps to create a custom Dead Letter Queue in JBoss 7.1.2 using CLI

Using the below CLI file we are doing total 3 things at the same-time and that too with one command, now that’s called saving time 😉

  • Creating a Queue with a name MyQueue and having a remote enabled JNDI name /MyQueue which has a prefix as “java:jboss/exported”
  • Creating a custom DLQ with a name MyDLQ and having a local JDNI name /MyDLQ
  • And configuring the custom DLQ MyDLQ with the queue MyQueue by creating a new address-setting particularly for MyQueue
  1. Create a file called MyQueue-add.cli in the bin folder of JBoss and copy the below content
  2. connect
    
    #Adding MyQueue
    /subsystem=messaging/hornetq-server=default/jms-queue=MyQueue/:add(entries=["java:jboss/exported/MyQueue"],durable=false)
    
    #Adding MyDLQ
    /subsystem=messaging/hornetq-server=default/jms-queue=MyDLQ/:add(entries=["java:/MyDLQ"],durable=false)
    
    #Adding address-settings for MyQueue
    /subsystem=messaging/hornetq-server=default/address-setting=jms.queue.MyQueue/:add(address-full-policy=BLOCK,dead-letter-address=jms.queue.MyDLQ,max-size-bytes=10485760,message-counter-history-day-limit=10,max-delivery-attempts=3,redelivery-delay=0)
    
  3. Now we need to create a new Application User by running “${JBOSS_HOME}/bin/add-user.sh” script as following :
  4. [user@user 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.
    Realm (ApplicationRealm) :  ApplicationRealm
    Username : testuser
    Password : testpassword
    Re-enter Password : testpassword
    
    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 'testuser' for realm 'ApplicationRealm'
    
    Is this correct yes/no? yes
    
    Added user 'testuser' to file '/home/user/jboss-as-7.1.2.Final/standalone/configuration/application-users.properties'
    Added user 'testuser' to file '/home/user/jboss-as-7.1.2.Final/domain/configuration/application-users.properties'
    Added user 'testuser' with roles testrole to file '/home/user/jboss-as-7.1.2.Final/standalone/configuration/application-roles.properties'
    Added user 'testuser' with roles testrole to file '/home/user/jboss-as-7.1.2.Final/domain/configuration/application-roles.properties'
    
    
  5. Make sure that the JBoss AS 7.1.2 is running, in our case we started JBoss AS 7.1.2 standalone-full.xml profile.
  6. [user@user bin]$ ./standalone.sh -c standalone-full.xml
    
  7. Now you just have to run the below command to execute above three things
  8. [user@user bin]$ ./jboss-cli.sh --file=MyQueue-add.cli
    {"outcome" => "success"}
    {"outcome" => "success"}
    {"outcome" => "success"}
    [user@user bin]$
    

    Once your above CLI command is executed successfully you will notice the following in your JBossAS 7.1.2 configuration file “standalone-full.xml”:

    <address-settings>
        <address-setting match="#">
    	.
    	.
    	.
        </address-setting>
        <address-setting match="jms.queue.MyQueue">
            <dead-letter-address>jms.queue.MyDLQ</dead-letter-address>
            <redelivery-delay>0</redelivery-delay>
            <max-delivery-attempts>3</max-delivery-attempts>
            <max-size-bytes>10485760</max-size-bytes>
            <address-full-policy>BLOCK</address-full-policy>
            <message-counter-history-day-limit>10</message-counter-history-day-limit>
        </address-setting>
    </address-settings>
    .
    .
    .
    <jms-destinations>
        <jms-queue name="MyQueue">
            <entry name="java:/exported/MyQueue"/>
            <durable>false</durable>
        </jms-queue>
        <jms-queue name="MyDLQ">
            <entry name="java:/MyDLQ"/>
            <durable>false</durable>
        </jms-queue>
    </jms-destinations>
    
  9. That’s it !!! You are done configuring a simple queue with a custom DLQ, having a max-delivery-attempts as 3, now if a message which is in MyQueue does not get delivered in 3 attempts then that message would be moved to MyDLQ which is a custom DLQ. Let’s test this out using the sender and receiver Java code.

Testing

  1. Create a Directory somewhere in your file system like: “/urs/JBossAS7.1.2/HQ/Queue” to write the QueueSend.java and 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="org.jboss.naming.remote.client.InitialContextFactory";
    
    //*************** Connection Factory JNDI name *************************
    public final static String JMS_FACTORY="/jms/RemoteConnectionFactory";
    
    //*************** Remote enabled Queue JNDI name *************************
    public final static String QUEUE="/MyQueue";
    
    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);
    
    //*************** Creating Queue Connection using the UserName & Password *************************
    qcon = qconFactory.createQueueConnection("testuser","testpassword");   			//<------------- Change the UserName & 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) 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(" ");
    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);
    
    //*************** UserName & Password for the Initial Context for JNDI lookup *************************
    env.put(Context.SECURITY_PRINCIPAL, "testuser");
    env.put(Context.SECURITY_CREDENTIALS, "testpassword");
    
    return new InitialContext(env);
    }
    }
    
  3. In QueueReceive.java copy the below program, which has a creating a transacted JMS Session and in “onMessage” we are checking it the text message which is been received contents “hello world” ignoring the case would get roll-backed if not would get committed to test our DLQ.
    import java.util.Hashtable;
    import javax.jms.*;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    public class QueueReceive implements MessageListener
    {
    public final static String JNDI_FACTORY="org.jboss.naming.remote.client.InitialContextFactory";
    
    //*************** Connection Factory JNDI name *************************
    public final static String JMS_FACTORY="/jms/RemoteConnectionFactory";
    
    //*************** Remote enabled Queue JNDI name *************************
    public final static String QUEUE="/MyQueue";
    
    private QueueConnectionFactory qconFactory;
    private QueueConnection qcon;
    private QueueSession qsession;
    private QueueReceiver qreceiver;
    private Queue queue;
    private boolean quit = false;
    
    public void onMessage(Message msg)
    {
    	try
    	{
    		String msgText;
    		if (msg instanceof TextMessage)
    		{
    			msgText = ((TextMessage)msg).getText();
    		}
    		else
    		{
    			msgText = msg.toString();
    		}
    		if (msgText.equalsIgnoreCase("hello world"))
    		{
    			System.out.println("nt "+ msgText +", hence rolling back");
    			// Here we are rolling back the session.
    			// The "Hello World" message which we received is not committed, hence it's undelivered and goes back to the TestQ
    			qsession.rollback();
    		}
    		else
    		{
    			System.out.println("nt "+ msgText );
    			// Here we are committing the session to acknowledge that we have received the message from the TestQ
    			qsession.commit();
    		}
    
    		if (msgText.equalsIgnoreCase("quit"))
    		{
    			synchronized(this)
    			{
    				quit = true;
    				this.notifyAll();
    			}
    		}
    	}
    	catch (JMSException jmse)
    	{
    	jmse.printStackTrace();
    	}
    }
    
    public void init(Context ctx, String queueName) throws NamingException, JMSException
    {
    	qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
    
            //*************** Creating Queue Connection using the UserName & Password *************************
    	qcon = qconFactory.createQueueConnection("testuser","testpassword");   			//<------------- Change the UserName & Password
    
    	//Creating a *transacted* JMS Session to test our DLQ
    	qsession = qcon.createQueueSession(true, 0);
    
    	queue = (Queue) ctx.lookup(queueName);
    	qreceiver = qsession.createReceiver(queue);
    	qreceiver.setMessageListener(this);
    	qcon.start();
    }
    
    public void close()throws JMSException
    {
    qreceiver.close();
    qsession.close();
    qcon.close();
    }
    
    public static void main(String[] args) throws Exception
    {
    if (args.length != 1)
    {
    System.out.println("Usage: java QueueReceive URL");
    return;
    }
    InitialContext ic = getInitialContext(args[0]);
    QueueReceive qr = new QueueReceive();
    qr.init(ic, QUEUE);
    System.out.println("JMS Ready To Receive Messages (To quit, send a "quit" message from QueueSender.class).");
    
    synchronized(qr)
    {
    while (! qr.quit)
    {
    try
    {
    qr.wait();
    }
    catch (InterruptedException ie)
    {}
    }
    }
    qr.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);
    
    //*************** UserName & Password for the Initial Context for JNDI lookup *************************
    env.put(Context.SECURITY_PRINCIPAL, "testuser");
    env.put(Context.SECURITY_CREDENTIALS, "testpassword");
    
    return new InitialContext(env);
    }
    }
    
  4. Now open 2– command prompt and run the “. ./setJBossEnv.sh” by adding two DOTs separated by a single space, in both the prompts to set the Environment (PATH & CLASSPATH).
  5. setJBossEnv.sh

    #!/bin/sh
    echo "Exporting JBOSS_HOME...."
    export JBOSS_HOME=/Jboss/jboss-as-7.1.2.Final   #<---- Change as per your environment
    echo "JBOSS_HOME Exported....!!!"
    echo ""
    echo "Exporting JAVA_HOME...."
    export JAVA_HOME=/Jdk/jdk1.6.0_21    #<---- Change as per your environment
    echo "JBOSS_HOME Exported....!!!"
    echo ""
    echo "Exporting CLASSPATH...."
    export CLASSPATH=$JBOSS_HOME/bin/client/jboss-client.jar:$CLASSPATH:.:
    echo "CLASSPATH Exported....!!!"
    echo ""
    echo "Exporting PATH...."
    export PATH=$JAVA_HOME/bin:$PATH
    echo "PATH Exported....!!!"
    echo ""
    echo "========================================================================"
    echo "JBOSS_HOME = " $JBOSS_HOME
    echo ""
    echo "JAVA_HOME = " $JAVA_HOME
    echo ""
    echo "CLASSPATH = " $CLASSPATH
    echo ""
    echo "PATH = " $PATH
    echo "========================================================================"
    
  6. Then compile the QueueSend.java and QueueReceive.java programs.
  7. Now run the code with the following command
  8. Prompt-1

    java QueueSend remote://localhost:4447
     

    Prompt-2

    java QueueReceive remote://localhost:4447
     

  9. Once this is been done try to send some messages (i.e. with “hello world” one of them ) in the Prompt-1 which can be revived on Prompt-2. , however the message which is “hellow world” would be rollbacked and as per the “max-delivery-attempts” value 3 times it would be re-sent and then it would be moved to the DLQ.

    CLI

    [user@user bin]$ ./jboss-cli.sh -c /subsystem=messaging/hornetq-server=default/jms-queue=MyDLQ/:count-messages
    {
        "outcome" => "success",
        "result" => 1L
    }
    

    OR

    Admin console path:
    Runtime – Status – JMS Destination – MyDLQ – “Messages in Queue:”


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


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