Skip to content

JMS with SonicMQ and JMSJCA

by Matthias Fraass on Januar 18th, 2010

The last example in this series will cover how to connect Glassfish v3 to a remote SonicMQ server. I’m using SonicMQ 7.6 so YMMV if you have a different version.

My first approach was to connect them via genericra, like I did with OpenMQ, seemed to work but looking closer I encountered a problem. As it seems to be a incompatibility between genericra and SonicMQ, I decided to look for other ways to connect them.
I found that JMSJCA is working fine and so I will show you how to configure it properly.

First, you have to install and configure SonicMQ. I’m relating partly to this fine tutorial. As I don’t know if that tutorial will last longer than my blog entry here, I will copy the relevant passages (I stripped them down a bit):

  1. Copy the following libraries from /Sonic/MQ7.0/lib/ to glassfish/domains/domain1/lib/
    • sonic_Client.jar
    • sonic_ASPI.jar
    • sonic_Crypto.jar
    • sonic_XA.jar
    • mfcontext.jar
  2. Start SonicMQ via
    > Sonic/MQ7.6/bin/startcontainer.bat
  3. now comes the strange part: you have to configure a destination named “inqueue” (altough it’s bidirectional, I just left the name ‘inqueue’ from the genericra tutorial. You can call it whatever you want)
    • Go to the folder /opt/Sonic/samples/Management/configApi/jsConfigBean and edit the CreateQueue.js script. Set the QUEUE_NAME variable to “inqueue”.
    • Execute ../../../jsRun.bat CreateQueue.js
    • The output of the command will be
       inqueue doesn't exist. Creating it.
      Queue: inqueue
      Type = AdministrativelyCreated
      Global = false
      Exclusive = false
      Max Size = 1000
      Save Threshold = 1536
      Queue: inqueue
      Type = AdministrativelyCreated
      Global = false
      Exclusive = false
      Max Size = 12345
      Save Threshold = 1536
    • create the bindings:
    • cd /opt/Sonic/samples/Management/jndiAPI/java
    • Execute ../../../Mgmt.bat
    • and execute
      > bind qcf inboundXAQCF ConnectionURLs=tcp://localhost:2506,DefaultUser=Administrator,DefaultPassword=Administrator
      JndiCLI Domain1 tcp://localhost:2506 Administrator Administrator
      > bind qcf outboundXAQCF ConnectionURLs=tcp://localhost:2506,DefaultUser=Administrator,DefaultPassword=Administrator
      > bind queue inqueue inqueue
      > bind queue outqueue outqueue
      > bind queue deadmsgqueue deadmsgqueue
    • You have to do the last step manually: open SonicMQ admin GUI (startmc.bat) and change the “Factory Type” of outboundXAQCF to XAQueueConnectionFactory
    • Check if everything went right:
      > list
      testxa: progress.message.jclient.QueueConnectionFactory
      inqueue: progress.message.jclient.Queue
      inboundXAQCF: progress.message.jclient.xa.XAQueueConnectionFactory

The SonicMQ is ready now.
The next step is to configure the resource adapter.
Now Download sun-jms-adapter.rar from the project’s website and put it into \temp\.
Start glassfish and execute these commands:

asadmin undeploy --cascade sun-jms-adapter
asadmin delete-resource-adapter-config sun-jms-adapter
asadmin delete-admin-object jms/queue
asadmin delete-connector-connection-pool --cascade outpool
asadmin delete-connector-resource jms/outboundXAQCF

asadmin create-resource-adapter-config sun-jms-adapter
asadmin deploy \temp\sun-jms-adapter.rar

asadmin create-connector-connection-pool --raname sun-jms-adapter --connectiondefinition javax.jms.QueueConnectionFactory --transactionsupport XATransaction --property ConnectionURL=jndi\://:Options=JMSJCA.sep\=,JMSJCA.UnifiedCF\=outboundXAQCF,JMSJCA.QueueCF\=outboundXAQCF,java.naming.factory.initial\=com.sonicsw.jndi.mfcontext.MFContextFactory,java.naming.provider.url\=tcp\://localhost\:2506,java.naming.security.principal\=Administrator,java.naming.security.credentials\=Administrator,com.sonicsw.jndi.mfcontext.domain\=Domain1 outpool

asadmin create-connector-resource --poolname outpool jms/outboundXAQCF
asadmin create-admin-object --raname sun-jms-adapter --restype javax.jms.Queue --property Name=outqueue jms/outqueue

Now we can create a RESTful web service to send messages to the SonicMQ:

@Stateless
@Path("/jms")
public class JMSRestfulWebService {
@Resource(mappedName = "jms/outboundXAQCF")
private ConnectionFactory sonicConnectionFactory;

@Resource(mappedName = "jms/outqueue")
private Queue sonicQueue;

@Path("sonic")
@GET
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public String putMessageSonic() throws NamingException, JMSException, NotSupportedException, SystemException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException
{
System.out.println("called putMessageAdapter->Sonic");
javax.jms.Connection  connection = null;
javax.jms.Session        session = null;
MessageProducer messageProducer = null;

String sessionID=new Date().toString();

connection = sonicConnectionFactory.createConnection();
session = connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
messageProducer = session.createProducer(sonicQueue);
TextMessage message = session.createTextMessage();
message.setText("Hello, sonic JMS! @" + sessionID);
messageProducer.send(message);

return "JMS remotely produced 1 message for sonic #";
}
}

Just open http://localhost:8080/yourcontext/jms/sonic with a web browser and you should see in the log file that a message was created. You can check the Queue in the SonicMQ Admin GUI (monitoring tab) for the number of messages in the Queue – it should increase.

So let’s consume these messages with a MessageDrivenBean!

Add this to a sun-ejb-jar.xml (create it, if it’s not there yet):

MySonicRemoteMessageDrivenBean

sun-jms-adapter

<!--  see http://wiki.open-esb.java.net/Wiki.jsp?page=JMSJCAReadme#section-JMSJCAReadme-SupportForJNDI -->
Options
JMSJCA.sep=,JMSJCA.QueueCF=outboundXAQCF,java.naming.factory.initial=com.sonicsw.jndi.mfcontext.MFContextFactory

ConnectionURL
jndi://jms/outqueue

And this is the MDB which receives the messages:

@MessageDriven(mappedName = "jms/outqueue",
activationConfig = {
@ActivationConfigProperty(propertyName = "ConnectionFactoryJndiName", propertyValue = "outboundXAQCF")
,@ActivationConfigProperty(propertyName = "Destination", propertyValue="outqueue")
}
)
public class MySonicRemoteMessageDrivenBean implements MessageListener {

@EJB
LoggingBeanLocal loggingBean;

public MySonicRemoteMessageDrivenBean() {
}

/**
* @see MessageListener#onMessage(Message)
*/

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void onMessage(Message message) {
try {
System.out.println("### MySonicRemoteMessageDrivenBean got message: " + ((TextMessage)message).getText() + " @" + System.currentTimeMillis());
} catch (JMSException e) {
e.printStackTrace();
}

}
}

It should receive the queued messages as soon as you deploy it.

This settles our three-part tutorial about different ways of using the JMS with glassfish. I hope you enjoyed it and it might help someone to figure out the strange ways of configuring genericra and JMSJCA.

From → Coding

6 Comments
  1. Nice writeup!

    Here some notes/tips/alternates…

    re 1) you might want to add
    * sonic_XMessage.jar to the list here (Sonic JMS message types like XMLMessage)
    * sonic_Selector.jar (if you use message selectors)
    * sonic_SSL.jar (if you use SSL)

    re 2) you are using the default management broker here. That is not recommended best practices. Rather, consider using a separate (and additional) broker for data traffic at a different port. Of course for simplicity of the tutorial this is just fine

    re 3) These steps will work, but you can equally do everything using the GUI (Sonic Management Console / SMC… MQ/bin/startmc.bat(sh) )

    creating the (physical) queue is done against the broker /Brokers/DomainManager under Queues.

    creating the JNDI entries is done in the JMS Administered Objects tool (see tools menu). Just create a new connection there. Click the Sonic store checkbox. Enter you url, user, password as above and then create your jndi destinations and connection factories

  2. Nice post! I’ve added a link to this post in the JMSJCA documentation.

  3. @Thomas: Thank you! But for simplicitie’s sake, I will leave the tutorial as it is.

    @Frank: Thanks, that makes me a bit proud :) .

  4. james permalink

    Hi,

    i tried ../../../jsRun.bat CreateQueue.js
    and it returns me, failed to connect, unable to find configuration for /Broker/Mgmt/_default

    how can i changed the above so that it connects to topics instead of queues?

    thanks

  5. james permalink

    Hi,

    when I tried to run, ../../../jsRun.bat CreateQueue.js

    an error occured.

    Failure: Configuration not found for /Brokers/MgmtBroker/_Default

    thanks.

  6. Pradeep permalink

    We are using SoincMQ 6.1.0 and client is connecting through remote machine.

    On the client side we have the required client jars. The client side consists of two parts, the sender and the reciever, the reciever sends a response back to the sender.

    We are using SonicMQ v6.1 for JMS request response message exchange. The scenario in the test application has a component sending request to SonicMQ on a queue. The component also creates the replyTo destination(queue) and sets this on the request message. There is another component which waits on the queue and replies on the replyTo queue. This response is received by the first component. The first component uses JCA Resource Adapter Managed Connection Factory for outbound communication.

    The issue that we are facing in our application is that, for first message exchange goes through fine. But from the second message exchange onwards, the consumer on the first component does not receive the reply message. If we look into the Sonic MQ queues (Sonic Management Console -> Manage -> Queues), there is no pending message on the reply queue. But once the first component closes the consumer on the queue, the response message shows up on the queue.

    Looking to understand this behaviour. Also want to understand as to under what circumstances does the message appear on the queue only after the consumer is closed.

    Lets us know if code snippets for the sender side is needed to understand things better.

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS