Tag: JBoss Messaging

How to set JBoss Message Sucker Password in JBoss AS 6

Hi,

JBoss messaging system uses the concept of Message Sucker Passwords. This a password used by the message sucker connections to create new connections. While moving your JBoss profile for production purpose it is highly recommended that we should change this password. This password is defined and mapped in the following two files “$PROFILE/deploy/messaging/messaging-jboss-beans.xml” and “$PROFILE/deploy/messaging/messaging-service.xml” files.

The First file “messaging-jboss-beans.xml” contains the clear text sucker password, where as the second file “messaging-service.xml” should contain the encrypted value of the sucker password. the password encryption can be done using the class “org.jboss.messaging.util.SecurityUtil” class. This class resides inside the “$JBOSS_HOME/client/jboss-messaging-client.jar” file.

If the Sucker password is not set/changed then we will get the following kind of WARNNING message while starting the JBoss profile.

13:38:56,422 WARN  [JBossASSecurityMetadataStore] WARNING! POTENTIAL SECURITY RISK. It has been detected that the MessageSucker component which sucks messages from one node to another has not had its password changed from the installation default. Please see the JBoss Messaging user guide for instructions on how to do this.

Following are the steps to change the Sucker password for JBoss messaging system.

Step1). Change the sucker password in “deploy/messaging/messaging-jboss-beans.xml”. Suppose your SuckerPassword is “ABCEDEFGHI” then we can do the following:

<property name="suckerPassword">ABCEDEFGHI</property>

Step2). Generate an encrypted version of this password (jboss-messaging-client.jar’s location is relative to jboss-as/client directory):

java -cp $JBOSS_HOME/client/jboss-messaging-client.jar org.jboss.messaging.util.SecurityUtil ABCEDEFGHI

Output:
-------------
key len: 14 length max: 128
Encoded password: 4cd5ab1456781b311

Step3). Place the encodedPassword of above command in “deploy/messaging/messaging-service.xml”

<attribute name="SuckerPassword">4cd5ab1456781b311</attribute>

Step4). Restart your JBoss Profile.

.
.
Thanks
Middleware Magic Team


How to configure an MDB to access a remote queue in JBoss AS 6?

In this article we will see how can one send messages to a queue on box-1 and those messages can be received by the consumer from box-2 which is a very basic scenario in most of the people. The main concept for this is that we would be sending messages to the queue on box-1 and on box-2 we would be creating a remote-queue which would have the URL of the JBoss having the queue on box-1 and using that URL remote-queue would connect to the connection factory and would connect to the queue for JBoss which is on box-1. Once we get the access of connection factory and queue we would just create an MDB which would use the same details from remote-queue and would be able to consume message from box-2 easily.

This article has the full configuration for the set-up of remote queue as well as we would also be doing testing to check if our configuration is working fine which the sender code.

Steps to configure an MDB to access a Remote Queue

As we would be access a remote queue we would be need two different physical Machine (i.e. Box-1 and Box-2) for this example as shown below.

In Box-1

Lets say we have a JBoss node in this box called Node-1 and following things has to be done on this box-1

  1. Just put “TestQueue-service.xml” file in the “Node-1/deploy” folder
  2. TestQueue-service.xml

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <server>
        <mbean xmbean-dd="xmdesc/Queue-xmbean.xml" name="jboss.messaging.destination:service=Queue,name=TestQueue" code="org.jboss.jms.server.destination.QueueService">
            <attribute name="JNDIName">TestQueue</attribute>
            <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
            <depends>jboss.messaging:service=PostOffice</depends>
        </mbean>
    </server>
    

In Box-2

In this box we have another JBoss node called Node-2 and following things has to be done on this box

  1. Put the “remote-jms-ds.xml” file in the “Node-2/deploy” folder
  2. remote-jms-ds.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <connection-factories>
      <!-- 1. Search XXX in this file and replace it with your remote server name -->
      <!-- Remote JMS Provider configuration -->
      <mbean code="org.jboss.naming.ExternalContext" name="jboss.jndi:service=ExternalContext,jndiName=remote">
        <attribute name="JndiName">remote</attribute>
        <attribute name="Properties">
          java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
          java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
          java.naming.provider.url=jnp://XXX:1099
        </attribute>
      </mbean>
      <mbean code="org.jboss.jms.jndi.JMSProviderLoader" name="jboss.jms:service=JMSProviderLoader,name=RemoteJMSProvider">
        <attribute name="ProviderName">RemoteJMSProvider</attribute>
        <attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JNDIProviderAdapter</attribute>
        <attribute name="FactoryRef">remote/XAConnectionFactory</attribute>
        <attribute name="QueueFactoryRef">remote/XAConnectionFactory</attribute>
        <attribute name="TopicFactoryRef">remote/XAConnectionFactory</attribute>
        <depends>jboss.jndi:service=ExternalContext,jndiName=remote</depends>
      </mbean>
      <tx-connection-factory>
        <jndi-name>RemoteJmsXA</jndi-name>
        <track-connection-by-tx/>
        <xa-transaction/>
        <rar-name>jms-ra.rar</rar-name>
        <connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition>
        <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Queue</config-property>
        <config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/RemoteJMSProvider</config-property>
        <security-domain>RemoteJmsXARealm</security-domain>
        <max-pool-size>20</max-pool-size>
      </tx-connection-factory>
    </connection-factories>
    

    Note: In “remote-jms-ds.xml” file you have to change the XXX with the your remote server name/IP address of the remote server

  3. Put the “MDB3_EAR.ear” files in the “Node-2/deploy” folder
    1. Create a folder called “MDB3_EAR.ear
    2. Under it create 2 folders called “MDB3.jar” and “META-INF
    3. Inside “META-INF” create a “application.xml” file and update this file with the below details
    4. <?xml version="1.0" encoding="UTF-8"?>
      <application version="5" xmlns="http://java.sun.com/xml/ns/javaee"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                    http://java.sun.com/xml/ns/javaee/application_5.xsd">
         <module>
             <ejb>MDB3.jar</ejb>
         </module>
      </application>
      
    5. Inside “MDB3.jar” create a “MyMDB.java” file and update this file with the below details
    6. import javax.ejb.MessageDriven;
      import javax.jms.JMSException;
      import javax.jms.Message;
      import javax.jms.MessageListener;
      import javax.jms.TextMessage;
      import javax.ejb.ActivationConfigProperty;
      // To consume messages from REMOTE destination in JBoss AS 6
      @MessageDriven(
          activationConfig={
              @ActivationConfigProperty(propertyName="providerAdapterJNDI", propertyValue="java:/RemoteJMSProvider"),
              @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
              @ActivationConfigProperty(propertyName="destination", propertyValue="remote/TestQueue"),   //<--  JNDI Name of the Queue on the Remote destionation here its "TestQueue"
              @ActivationConfigProperty(propertyName="useDLQ", propertyValue="false")
      	//************************* RECONNECT PARAMERTERS  *****************************
      	@ActivationConfigProperty(propertyName="reconnectAttempts", propertyValue="60"),
      	@ActivationConfigProperty(propertyName="reconnectInterval", propertyValue="10")
          }
      )
      public class MyMDB implements MessageListener{
          public void onMessage(Message message) {
              TextMessage textMessage = (TextMessage) message;
              try {
                  System.out.println("nnt Message has been Received by MDB : "+ textMessage.getText());
              } catch (JMSException e) {
                  e.printStackTrace();
              }
          }
      }
      
    7. Once every think has been put at its place, then you can compile the java code and if wanted create an EAR archive file for above folder
  4. You would have to put the following “application-policy” block to the “conf/login-config.xml
  5. <application-policy name="RemoteJmsXARealm">
      <authentication>
        <login-module code="org.jboss.resource.security.ConfiguredIdentityLoginModule" flag="required">
          <module-option name="principal">guest</module-option>
          <module-option name="userName">guest</module-option>
          <module-option name="password">guest</module-option>
          <module-option name="managedConnectionFactoryName">jboss.jca:service=TxCM,name=RemoteJmsXA</module-option>
        </login-module>
      </authentication>
    </application-policy>
    

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

Testing

  1. Create a Directory somewhere in your file system like: “/urs/JBoss/JBM/Queue” to write the QueueSend.java and as we have an MDB we would not need a QueueReceive.java programs.
  2. In QueueSend.java copy the below program
    import java.io.*;
    import java.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.jnp.interfaces.NamingContextFactory";
    //*************** Connection Factory JNDI name *************************
    public final static String JMS_FACTORY="/ConnectionFactory";
    //*************** Queue JNDI name *************************
    public final static String QUEUE="/TestQueue";
    
    private QueueConnectionFactory qconFactory;
    private QueueConnection qcon;
    private QueueSession qsession;
    private QueueSender qsender;
    private Queue queue;
    private TextMessage msg;
    
    public void init(Context ctx, String queueName)throws NamingException, JMSException
    {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
    qcon = qconFactory.createQueueConnection();
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    queue = (Queue) ctx.lookup(queueName);
    qsender = qsession.createSender(queue);
    msg = qsession.createTextMessage();
    qcon.start();
    }
    
    public void send(String message) throws JMSException {
    msg.setText(message);
    qsender.send(msg);
    }
    
    public void close() throws JMSException {
    qsender.close();
    qsession.close();
    qcon.close();
    }
    
    public static void main(String[] args) throws Exception {
    if (args.length != 1) {
    System.out.println("Usage: java QueueSend URL");
    return;
    }
    InitialContext ic = getInitialContext(args[0]);
    QueueSend qs = new QueueSend();
    qs.init(ic, QUEUE);
    readAndSend(qs);
    qs.close();
    }
    
    private static void readAndSend(QueueSend qs) throws IOException, JMSException
    {
    String line="Test Message Body with counter = ";
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    boolean readFlag=true;
    System.out.println("ntStart Sending Messages (Enter QUIT to Stop):n");
    while(readFlag)
    {
    System.out.print("<Msg_Sender> ");
    String msg=br.readLine();
    if(msg.equals("QUIT") || msg.equals("quit"))
    {
    qs.send(msg);
    System.exit(0);
    }
    qs.send(msg);
    System.out.println();
    }
    br.close();
    }
    
    private static InitialContext getInitialContext(String url) throws NamingException
    {
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
    env.put(Context.PROVIDER_URL, url);
    return new InitialContext(env);
    }
    }
    
  3. Now open just 1– command prompt and run the “. ./setJBossEnv.sh” by adding two DOTs separated by a single space, in both the prompts to set the Environment (PATH & CLASSPATH).
  4. setJBossEnv.sh

    #!/bin/sh
    echo "Exporting JBOSS_HOME...."
    export JBOSS_HOME=/Jboss/AS6/jboss-as   #<---- 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/client/jbossall-client.jar:$JBOSS_HOME/client/jboss-javaee.jar:$JBOSS_HOME/common/lib/jnpserver.jar:$JBOSS_HOME/client/jboss-logging-spi.jar:$JBOSS_HOME/lib/jboss-javaee.jar:$JBOSS_HOME/common/lib/servlet-api.jar:$JBOSS_HOME/common/lib/log4j.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 "========================================================================"
    
  5. Then compile the QueueSend.java programs.
  6. Now run the code with the following command
  7. Prompt-1

    java QueueSend jnp://IP_BOX-1:1099
     
  8. Once this is been done try to send some messages in the Prompt-1 which can be revived on Prompt-2.

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


How to create a Queue in JBoss AS 6 ?

In this article we would show how to create a queue in JBoss AS 6 which uses JBoss Messaging, in this  example we would use MySQL as the persistence as we all know that Hypersonic SQL database is not recommended in production environment. Here we would be referring profile which can be “all” or “production”.

Before we start creating a queue would suggest you to follow the article How to switch Hypersonic with an alternative database in JBoss ? which would guide you to switch the non-supported database and once that’s done you can follow the below procedure.

Steps for creating a Queue in JBoss

1)  Replace “hsqldb-persistence-service.xml” with “mysql-persistence-service.xml” file which can be picked up from “/jboss-as/docs/examples/jms” directory and have to put in “/profile/deploy/messaging” folder

2)  Now you can create a queue from the Admin-console or even create “*-service.xml” file and place it in the “/profile/deploy” directory. Where * means your Queue name as shown in the below example

TestQ-service.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<server>
    <mbean xmbean-dd="xmdesc/Queue-xmbean.xml" name="jboss.messaging.destination:service=Queue,name=TestQ" code="org.jboss.jms.server.destination.QueueService">
        <attribute name="JNDIName">TestQ</attribute>
        <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
        <depends>jboss.messaging:service=PostOffice</depends>
    </mbean>
</server>

3) That’s it !!! You are done configuring a simple queue, now you can test it using the sender and receiver java code.

Testing

  1. Create a Directory somewhere in your file system like: “/urs/JBoss/JBM/Queue” to write the QueueSend.java and QueueReceive.java programs.
  2. In QueueSend.java copy the below program
    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.jnp.interfaces.NamingContextFactory";
    //*************** Connection Factory JNDI name *************************
    public final static String JMS_FACTORY="/ConnectionFactory";
    //*************** Queue JNDI name *************************
    public final static String QUEUE="/TestQ";
    
    private QueueConnectionFactory qconFactory;
    private QueueConnection qcon;
    private QueueSession qsession;
    private QueueSender qsender;
    private Queue queue;
    private TextMessage msg;
    
    public void init(Context ctx, String queueName)throws NamingException, JMSException
    {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
    qcon = qconFactory.createQueueConnection();
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    queue = (Queue) ctx.lookup(queueName);
    qsender = qsession.createSender(queue);
    msg = qsession.createTextMessage();
    qcon.start();
    }
    
    public void send(String message) throws JMSException {
    msg.setText(message);
    qsender.send(msg);
    }
    
    public void close() throws JMSException {
    qsender.close();
    qsession.close();
    qcon.close();
    }
    
    public static void main(String[] args) throws Exception {
    if (args.length != 1) {
    System.out.println("Usage: java QueueSend URL");
    return;
    }
    InitialContext ic = getInitialContext(args[0]);
    QueueSend qs = new QueueSend();
    qs.init(ic, QUEUE);
    readAndSend(qs);
    qs.close();
    }
    
    private static void readAndSend(QueueSend qs) throws IOException, JMSException
    {
    String line="Test Message Body with counter = ";
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    boolean readFlag=true;
    System.out.println("ntStart Sending Messages (Enter QUIT to Stop):n");
    while(readFlag)
    {
    System.out.print("<Msg_Sender> ");
    String msg=br.readLine();
    if(msg.equals("QUIT") || msg.equals("quit"))
    {
    qs.send(msg);
    System.exit(0);
    }
    qs.send(msg);
    System.out.println();
    }
    br.close();
    }
    
    private static InitialContext getInitialContext(String url) throws NamingException
    {
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
    env.put(Context.PROVIDER_URL, url);
    return new InitialContext(env);
    }
    }
    
  3. In QueueReceive.java copy the below program
    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.jnp.interfaces.NamingContextFactory";
    //*************** Connection Factory JNDI name *************************
    public final static String JMS_FACTORY="/ConnectionFactory";
    //*************** Queue JNDI name *************************
    public final static String QUEUE="/TestQ";
    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&lt;Msg_Receiver&gt; "+ 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
    {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
    qcon = qconFactory.createQueueConnection();
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    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).");
    // Wait until a "quit" message has been received.
    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);
    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/AS6/jboss-as   <---- 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/client/jbossall-client.jar:$JBOSS_HOME/client/jboss-javaee.jar:$JBOSS_HOME/common/lib/jnpserver.jar:$JBOSS_HOME/client/jboss-logging-spi.jar:$JBOSS_HOME/lib/jboss-javaee.jar:$JBOSS_HOME/common/lib/servlet-api.jar:$JBOSS_HOME/common/lib/log4j.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 jnp://localhost:1099
     

    Prompt-2

    java QueueReceive jnp://localhost:1099
     

    Note:
    With the “java QueueSend” and “java QueueReceive” command you have to give the<Protocol>://<IP-address>:<Port number>of the managed servers in different prompts.

  9. Once this is been done try to send some messages in the Prompt-1 which can be revived on Prompt-2.

NOTE:

– Here we are be creating a Queue with MySQL as the database, however you can use any supported database with this article as the steps would be similar.


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