Integration Server JMS over AMQP with RabbitMQ using RabbitMQ Native JMS Client library

Overview

RabbitMQ provides a native JMS client library, which can be used for JMS over AMQP with Integration Server.
https://www.rabbitmq.com/jms-client.html

See the following article for RabbitMQ setup and configuration.

As of today, the native client support AMQP 0-9-1.

To validate the AMQP protocol version, go to RabbitMQ admin console>Connections , check Protocol .

To validate the virtual host connection points, go to RabbitMQ admin console > Connections , check Virtual host.

Ensure that the RabbitMQ node is enabled with the rabbitmq-jms-topic-exchange plugin.

Note: If the JMS trigger in webMethods Integration Server fails with the “JMS Trigger <Trigger_Name> failed preprocessing: java.lang.NumberFormatException: Null is not a valid int” exception, provide a JMS message priority value while sending the JMS message.

Note: In some versions, if “Message TTL” is configured on the RabbitMQ queue, the trigger in Integration Server receives the messages from that queue only if the queue in RabbitMQ is bound to the “amq.direct” exchange.

JNDI binding

Define JNDI bindings
Create a binding file for RabbitMQ
	Define the connection URI 
		The format would be something like 
		amqp://[user]:[password]@[host]:[post]/ (for default virtual host)
		amqp://[user]:[password]@[host]:[post]/[virtual host name] (for specific virtual host)
		
		So we need to define a vhost section and a uri section for this 
		
	           #uri (with default vhost, no vhost definition required)
			ConnectionFactory/RefAddr/9/Content=amqp://guest:guest@localhost:5672/
			ConnectionFactory/RefAddr/9/Type=uri
			ConnectionFactory/RefAddr/9/Encoding=String
			
		#uri (with vhost democonnect)
			ConnectionFactory/RefAddr/9/Content=amqp://guest:guest@localhost:5672/democonnect
			ConnectionFactory/RefAddr/9/Type=uri
			ConnectionFactory/RefAddr/9/Encoding=String	
			
		#vhost (democonnect)
			ConnectionFactory/RefAddr/4/Content=democonnect
			ConnectionFactory/RefAddr/4/Type=vhost
			ConnectionFactory/RefAddr/4/Encoding=String	
			
	Define Connection Factory Object 
		#Connection Factory Object (lookup name ConnectionFactory)
			ConnectionFactory/ClassName=javax.jms.ConnectionFactory
			ConnectionFactory/FactoryName=com.rabbitmq.jms.admin.RMQObjectFactory
			ConnectionFactory/RefAddr/0/Content=jms/ConnectionFactory
			ConnectionFactory/RefAddr/0/Type=name
			ConnectionFactory/RefAddr/0/Encoding=String
			ConnectionFactory/RefAddr/1/Content=javax.jms.ConnectionFactory
			ConnectionFactory/RefAddr/1/Type=type
			ConnectionFactory/RefAddr/1/Encoding=String
			ConnectionFactory/RefAddr/2/Content=com.rabbitmq.jms.admin.RMQObjectFactory
			ConnectionFactory/RefAddr/2/Type=factory
			ConnectionFactory/RefAddr/2/Encoding=String	
			
	Define destination (Queue lookup name testQueue1)
		# testQueue1 Queue
                        testQueue1/ClassName=javax.jms.Queue
                        testQueue1/FactoryName=com.rabbitmq.jms.admin.RMQObjectFactory
                        testQueue1/RefAddr/0/Content=jms/Queue
                        testQueue1/RefAddr/0/Type=name
                        testQueue1/RefAddr/0/Encoding=String
                        testQueue1/RefAddr/1/Content=javax.jms.Queue
                        testQueue1/RefAddr/1/Type=type
                        testQueue1/RefAddr/1/Encoding=String
                        testQueue1/RefAddr/2/Content=com.rabbitmq.jms.admin.RMQObjectFactory
                        testQueue1/RefAddr/2/Type=factory
                        testQueue1/RefAddr/2/Encoding=String
                        testQueue1/RefAddr/3/Content=testQueue1
                        testQueue1/RefAddr/3/Type=destinationName
                        testQueue1/RefAddr/3/Encoding=String
                        testQueue1/RefAddr/4/Content=true
                        testQueue1/RefAddr/4/Type=amqp
                        testQueue1/RefAddr/4/Encoding=String
                        testQueue1/RefAddr/5/Content=testqueue1exchange
                        testQueue1/RefAddr/5/Type=amqpExchangeName
                        testQueue1/RefAddr/5/Encoding=String
                        testQueue1/RefAddr/6/Content=testQueue1
                        testQueue1/RefAddr/6/Type=amqpRoutingKey
                        testQueue1/RefAddr/6/Encoding=String
                        testQueue1/RefAddr/7/Content=testQueue1
                        testQueue1/RefAddr/7/Type=amqpQueueName
                        testQueue1/RefAddr/7/Encoding=String
			
	Define host/port (host: localhost, port: 5672) 
		#Host 
			ConnectionFactory/RefAddr/3/Content=localhost
			ConnectionFactory/RefAddr/3/Type=host
			ConnectionFactory/RefAddr/3/Encoding=String
			
		#Port
			ConnectionFactory/RefAddr/7/Content=5672
			ConnectionFactory/RefAddr/7/Type=port
			ConnectionFactory/RefAddr/7/Encoding=String

	Define Credentials (username/password)
		#Username (guest)
			ConnectionFactory/RefAddr/5/Content=guest
			ConnectionFactory/RefAddr/5/Type=username
			ConnectionFactory/RefAddr/5/Encoding=String

		#Password (guest)
			ConnectionFactory/RefAddr/6/Content=guest
			ConnectionFactory/RefAddr/6/Type=password
			ConnectionFactory/RefAddr/6/Encoding=String

Note: If you use a virtual host, create an exchange in that virtual host and bind it to the queue. In the JNDI bindings example, “testqueue1exchange” is the exchange created on “democonnect”. “testQueue1” is the queue bound to “testqueue1exchange”.

Sample .bindings file content

.bindings

#Connection Factory Object
ConnectionFactory/ClassName=javax.jms.ConnectionFactory
ConnectionFactory/FactoryName=com.rabbitmq.jms.admin.RMQObjectFactory
ConnectionFactory/RefAddr/0/Content=jms/ConnectionFactory
ConnectionFactory/RefAddr/0/Type=name
ConnectionFactory/RefAddr/0/Encoding=String
ConnectionFactory/RefAddr/1/Content=javax.jms.ConnectionFactory
ConnectionFactory/RefAddr/1/Type=type
ConnectionFactory/RefAddr/1/Encoding=String
ConnectionFactory/RefAddr/2/Content=com.rabbitmq.jms.admin.RMQObjectFactory
ConnectionFactory/RefAddr/2/Type=factory
ConnectionFactory/RefAddr/2/Encoding=String

Change this line accordingly if the broker is not at localhost

ConnectionFactory/RefAddr/3/Content=localhost
ConnectionFactory/RefAddr/3/Type=host
ConnectionFactory/RefAddr/3/Encoding=String

#vhost
ConnectionFactory/RefAddr/4/Content=democonnect
ConnectionFactory/RefAddr/4/Type=vhost
ConnectionFactory/RefAddr/4/Encoding=String

#uname
ConnectionFactory/RefAddr/5/Content=guest
ConnectionFactory/RefAddr/5/Type=username
ConnectionFactory/RefAddr/5/Encoding=String

password
ConnectionFactory/RefAddr/6/Content=guest
ConnectionFactory/RefAddr/6/Type=password
ConnectionFactory/RefAddr/6/Encoding=String

#Port
ConnectionFactory/RefAddr/7/Content=5672
ConnectionFactory/RefAddr/7/Type=port
ConnectionFactory/RefAddr/7/Encoding=String

SSL
ConnectionFactory/RefAddr/8/Content=false
ConnectionFactory/RefAddr/8/Type=ssl
ConnectionFactory/RefAddr/8/Encoding=String

#uri
ConnectionFactory/RefAddr/9/Content=amqp://guest:guest@localhost:5672/democonnect
ConnectionFactory/RefAddr/9/Type=uri
ConnectionFactory/RefAddr/9/Encoding=String

testQueue1 Queue

testQueue1/ClassName=javax.jms.Queue
testQueue1/FactoryName=com.rabbitmq.jms.admin.RMQObjectFactory
testQueue1/RefAddr/0/Content=jms/Queue
testQueue1/RefAddr/0/Type=name
testQueue1/RefAddr/0/Encoding=String
testQueue1/RefAddr/1/Content=javax.jms.Queue
testQueue1/RefAddr/1/Type=type
testQueue1/RefAddr/1/Encoding=String
testQueue1/RefAddr/2/Content=com.rabbitmq.jms.admin.RMQObjectFactory
testQueue1/RefAddr/2/Type=factory
testQueue1/RefAddr/2/Encoding=String
testQueue1/RefAddr/3/Content=testQueue1
testQueue1/RefAddr/3/Type=destinationName
testQueue1/RefAddr/3/Encoding=String
testQueue1/RefAddr/4/Content=true
testQueue1/RefAddr/4/Type=amqp
testQueue1/RefAddr/4/Encoding=String
testQueue1/RefAddr/5/Content=testqueue1exchange
testQueue1/RefAddr/5/Type=amqpExchangeName
testQueue1/RefAddr/5/Encoding=String
testQueue1/RefAddr/6/Content=testQueue1
testQueue1/RefAddr/6/Type=amqpRoutingKey
testQueue1/RefAddr/6/Encoding=String
testQueue1/RefAddr/7/Content=testQueue1
testQueue1/RefAddr/7/Type=amqpQueueName
testQueue1/RefAddr/7/Encoding=String

Note: Download the required RabbitMQ JMS client library and put the jars in Integration Server lib/jars directory

Integration Server Settings > Messaging > JNDI Settings

Predefined JNDI Templates → file system

Initial Context Factory → com.sun.jndi.fscontext.RefFSContextFactory

Provider URL → Directory location of the .binding file

Settings > Messaging > JMS Settings

Demo

demo2

4 Likes

Thanks @Prasanta_Malik .

Good read. Nice article! :slightly_smiling_face:

Did it work for you? It did not under 10.11

Could you explain bit more about your query please.

Thanks

Thank you for your reply.

We have tried to connect to RabbitMQ following the instructions in but nothing worked.

We followed even the exact name, binding, jar files, but still it did not work. Has it worked for you?

https://tech.forums.softwareag.com/t/integration-server-support-for-amqp-with-providers-azure-service-bus-and-rabbitmq/254392/2

1 Like

Yes this was tested successfully. What exactly you are trying? using the native library of rabbitMQ or over AMQP using qpid libraries? You could provide all details with the error, I will try to have a look.

Thanks

2 Likes

Thank you, for your email.

Thank you.

We tried to create the JNDI Provider Connection and JMS connection based on your suggestions. I was able to create and test JNDI Provider Connection successfully(Screen shot below)

Bindings file attached.

First I tried with rabbitmq-jms-3.1.0.jar but it failed with Error –

com.wm.app.b2b.server.jms.JMSSubsystemException: [ISS.0134.9016] Error creating connection factory: java.lang.UnsupportedClassVersionError: com/rabbitmq/jms/admin/RMQObjectFactory has been compiled by a more recent version of the Java Runtime (class file version 55.0),

so, I lowered the version to rabbitmq-jms-1.5.0.jar but now got below error. Screen shot provided.

I attached the jar file and binding file which I used. Please provide you feedback.

None worked.

Shall we try QPID libraries instead?

(Attachment .bindings is missing)

1 Like

I added bindings text below because the forum rejected it as an attachment.

Hi,
Using IS 10.15 on Linux and having : Cannot instantiate class: com.sun.jndi.fscontext.RefFSContextFactory.
So basically it doesn’t work.
Another general remark with all those articles related to webMethods: there is already kind of a dependency nightmare with the product and we’re never told what jars we need to install to make things work. In my case this is what costs me most of my time, like hours, while once you figure that out, following this article shouldn’t take more than 5 minutes

I managed to make it work.
Here are the jars that are absolutely required for a 10.15 installation:

  • fscontext-4.6-b01.jar
  • javax.jms-API-2.0.jar
  • amqp-client-5.21.0.jar
  • rabbitmq-jms-2.9.0.jar

Since IS 10.15 is still running on Java 11, it is important to use version 2.9.0 of rabbitmq-jms as it is the latest release still depending on javax.jms, earlier versions depending on jakarta.jms.
I’m a bit surprised that the fscontext jar is required, I would have expected it to be bundled with the IS, same regarding javax.jms, but whatever, once you figure that out, everything works fine, but you need to follow really carefully the video at the bottom, more specifically the exchange that must be of “fanout” type.
That’s not easy with a video in gif format though :confused: