The Generic JMS Adapter does not work with the Qpid JMS client out of the box. Please refer to the following KB article for more information: The Generic JMS Adapter does not work with the QPID JMS Provider
To workaround this issue, the use of JNDI and JMS Administered Objects is required. This KB article provides the steps to configure JNDI and JMS Administered Objects with the Qpid JMS provider.
The following steps have been tested with OpenEdge 12.2.12, Apache ActiveMQ 5.17.4 and Apache Qpid JMS 1.8.0 / 1.10.0 (javax.jms).
Configuration steps:
- Add a Qpid section in the %DLC%\properties\jmsProvider.properties file:
[QpidJNDI]
javax.jms.ConnectionFactory=org.apache.qpid.jms.jndi.JmsInitialContextFactory
javax.jms.QueueConnectionFactory=org.apache.qpid.jms.jndi.JmsInitialContextFactory
javax.jms.TopicConnectionFactory=org.apache.qpid.jms.jndi.JmsInitialContextFactory
- Download the latest Qpid JMS (javax.jms) libraries from https://qpid.apache.org/download.html .
- Create a new Java project in PDSOE which uses the JDK version which is supported by the OpenEdge release (e.g. JDK 11 for OpenEdge 12.2).
- Add progress.jar and the Qpid libraries to the Classpath:
Note: There is no need to create a module-info.java file when prompted.
- Create a new class named AdminObjectFinder in the jmsfromABL package (see attached sample AdminObjectFinder.java file for the content):
- Copy the <Apache Qpid location>\examples\src\main\resources\jndi.properties file to the 'src' folder in PDSOE. A sample is attached.
- Within the jndi.properties file inside of PDSOE, update the URL and the JNDI lookup name in the following line:
connectionfactory.myFactoryLookup = amqp://localhost:5672
- If the connection factory in the ABL code needs to be referenced using a different name (e.g. myConnectionFactory instead of myFactoryLookup), then change the line to for example:
connectionfactory.myConnectionFactory = amqp://localhost:5672
- The jndi.properties file also contains JNDI lookup names for queues and topics, but it is not required to use them. If needed, they can be defined as follows:
queue.myQueue = TestQ
topic.myTopic = TestT
Then the JNDI lookup name can be used when referencing a queue or topic in the ABL code, for example:
RUN sendToQueue IN jmssession("myQueue", messageH, ?, ?, ?).
- Build the project: Project menu -> Build Project
- Generate a JAR file with the jndi.properties and the AdminObjectFinder class:
Right-click on the project -> Export -> Java -> JAR file
- Include the JAR file that was just generated (e.g. AdminObjectFinder.jar) and all the Qpid JAR files in the classpath within %DLC%\properties\JavaTools.properties. Also specify the JMS Provider that was specified in jmsProvider.properties for the -DjmsProvider JVM parameter. For example:
[SonicMQ]
classpath=E:\Download\apache-qpid-jms-1.8.0\lib\AdminObjectFinder.jar,E:\Download\apache-qpid-jms-1.8.0\lib\qpid-jms-client-1.8.0.jar,E:\Download\apache-qpid-jms-1.8.0\lib\slf4j-api-1.7.36.jar,E:\Download\apache-qpid-jms-1.8.0\lib\jakarta.jms-api-2.0.3.jar,E:\Download\apache-qpid-jms-1.8.0\lib\proton-j-0.34.0.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-buffer-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-common-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-handler-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-resolver-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-transport-native-unix-common-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-codec-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-transport-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-transport-native-epoll-4.1.86.Final-linux-x86_64.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-transport-classes-epoll-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-transport-native-kqueue-4.1.86.Final-osx-x86_64.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-transport-classes-kqueue-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\netty-codec-http-4.1.86.Final.jar,E:\Download\apache-qpid-jms-1.8.0\lib\qpid-jms-discovery-1.8.0.jar,${DLC}/java/progress.jar
jvmargs=-DsonicMQExtensions=false -DjmsProvider=QpidJNDI
- Refer to the JNDI lookup name of the connection factory in the ABL code, for example:
BLOCK-LEVEL ON ERROR UNDO, THROW.
DEFINE VARIABLE jmssession AS HANDLE NO-UNDO.
DEFINE VARIABLE messageH AS HANDLE NO-UNDO.
/* Creates the session object. */
RUN jms/jmssession.p PERSISTENT SET jmssession ("-SMQConnect"). // ClientConnect
RUN setBrokerURL IN jmssession ("myConnectionFactory").
/* Set user credentials. */
RUN setUser IN jmssession ("admin").
RUN setPassword IN jmssession ("admin").
/* Connect to the broker. */
RUN beginSession IN jmssession .
MESSAGE "Session started" VIEW-AS ALERT-BOX INFORMATION TITLE "Info".
/* Create a text message */
RUN createTextMessage IN jmssession (OUTPUT messageH).
RUN setText IN messageH ("This is test message sent.").
MESSAGE "sending" VIEW-AS ALERT-BOX INFORMATION TITLE "Info".
/* Send the message to the "TestQ" queue by referencing the JNDI lookup name */
RUN sendToQueue IN jmssession ("myQueue", messageH, ?, ?, ?).
RUN deleteMessage IN messageH.
RUN deleteSession IN jmssession.
MESSAGE "Sent" VIEW-AS ALERT-BOX.
CATCH e AS Progress.Lang.Error :
MESSAGE e:GetMessage(1) SKIP
"Num messages:" e:NumMessages VIEW-AS ALERT-BOX ERROR TITLE "JMS Error".
END CATCH.
Details about stand alone Generic JMS Adapter:
- Install using PROGRESS_OE_12.8_WIN_64_JMSADAPTER or PROGRESS_OE_12.8_LNX_64_JMSADAPTER.tar depending on your platform
- Add a new Adapter section for Qpid.
Example: ( obs: set unique appserviceNameList and uuid )
[Adapter.qpid]
appserviceNameList=adapter.progress.jms.qpid
brokerLogFile=@{WorkPath}\qpid.broker.log
controllingNameServer=NS1
description=Qpid Adapter broker
portNumber=23620
srvrLogFile=@{WorkPath}\qpid.server.log
uuid=932.99.999.XXX:2ee77e:cf3bbe3d33:-8030
3. Start AdminServer and Nameserver NS1 from JMS Adapter installation folder.
4. Start JMS broker using bin\oemessaging.bat or bin/oemessaging.sh
Make sure to set the following environment variables before running oemessaging:
JMSProvider
SONICMQEXTENSIONS=false
JMSCLIENTJAR ( include an entry in JMSCLIENTJAR for jmsfromABL/AdminObjectFinder.class and jndi.properties )
5. If you have multiple JMS providers, add an Adapter section ubroker.properties for each new adapter. ( see 2 )
6. Validate the adapter brokers are registered with the nameserver NS1 using
nsman -name NS1 -query
In the ABL client code create a JMS session using the nameserver URL.
Example:
RUN jms/jmssession.p PERSISTENT SET jmssession ("-URL AppServer://localhost:5162/adapter.progress.jms.qpid").
-
/* for the broker name use the appserviceNameList from ubroker.properties */