JMS Connection
This method is deprecated. Please use the new method instead.
This is an explanation on how to connect Lobster_data to a JMS system by using the Message Service. Note: JMS messages are not to be confused with the internal data/message type Message in Lobster_data. The principle is similar, but the latter is an internal and proprietary message format.
We will describe the connection to Apache ActiveMQ, but any JMS conform system can be connected accordingly.

Important note: You have to set class com.ebd.hub.services.message.JMSMessageService instead of class com.ebd.hub.services.message.MessageService in the configuration files ./etc/factory.xml and ./etc/message.xml.
First of all, the fundamental connection to the JMS system has to be configured in the file ./etc/message.xml. Please copy the JAR files of your JMS provider to folder ./extlib (in our case activemq-all-5.10.0.jar). For each JMS queue, respectively topic, you have to insert an entry in file ./etc/message.xml. In our example here, we receive JMS messages from JMS queue JMSReceiveQueue and send messages to JMS queue JMSSendQueue. Only byte and text messages are supported.
Before you start, make sure you have a local Apache ActiveMQ Server with the above-mentioned queues running (see http://activemq.apache.org/) and have manually created two test messages in queue JMSReceiveQueue. This tutorial used ActiveMQ 5.10.0 Release.
Receive JMS Messages
In general, incoming JMS byte or text messages have to be converted into Lobster_data-compliant messages. These converted messages then have to be fed to a profile with an input agent of type Message. We need an entry to declare the general consumer/subscriber JMS2DW.
<!-- jms2message bridge/support -->
<
Call
name
=
"setJMSManager"
><
Arg
>
<
New
class
=
"com.ebd.hub.services.message.jms.JMSManager"
>
<
Arg
>
<
New
class
=
"com.ebd.hub.services.message.jms.JMSMapper"
>
<!-- Feed JMS data to Lobster_data. This can be repeated arbitrarily many times for additional queues or topics -->
<
Call
name
=
"addJMSMap"
>
<
Arg
>
<
New
class
=
"com.ebd.hub.services.message.jms.JMSMap"
>
<!-- Map JMS (initial) context/queue to message service context/queue -->
<
Arg
>ConnectionFactory</
Arg
>
<
Arg
>JMSReceiveQueue</
Arg
>
<!-- This is the connection to JMS2DW, see above in 'addConsumerQueue' -->
<
Arg
>jms</
Arg
>
<
Arg
>in</
Arg
>
<!-- If 'false', a JMS queue is used. If 'true', a JMS topic is used -->
<
Arg
type
=
"boolean"
>false</
Arg
>
</
New
>
</
Arg
>
</
Call
>
<!-- Feed data to JMS. See next chapter. Does not have any effect here.-->
<
Call
name
=
"addMessageMap"
>
<
Arg
>
<
New
class
=
"com.ebd.hub.services.message.jms.JMSMap"
>
<!-- Map JMS (initial) context/queue to message service context/queue -->
<
Arg
>ConnectionFactory</
Arg
>
<
Arg
>JMSSendQueue</
Arg
>
<!-- This is the connection to DW2JMS. See next chapter -->
<
Arg
>DW2jms</
Arg
>
<
Arg
>DW2out</
Arg
>
<!-- If 'false', a JMS queue is used. If 'true', a JMS topic is used -->
<
Arg
type
=
"boolean"
>false</
Arg
>
</
New
>
</
Arg
>
</
Call
>
</
New
>
</
Arg
>
<!-- General settings for the connection to the JMS system -->
<!-- With 'addJNDIProperty' every property (key, value) can be passed to the ConnectionFactory -->
<
Call
name
=
"addJNDIProperty"
>
<
Arg
>java.naming.factory.initial</
Arg
>
<
Arg
>org.apache.activemq.jndi.ActiveMQInitialContextFactory</
Arg
>
</
Call
>
<
Call
name
=
"addJNDIProperty"
>
<
Arg
>java.naming.provider.url</
Arg
>
<
Arg
>
tcp://localhost:61616
</
Arg
>
</
Call
>
<!-- If set to true, JMS header properties are added as well -->
<
Set
name
=
"addJmsPropertiesOfMessage"
>true</
Set
>
</
New
>
</
Arg
>
</
Call
>
<
Call
name
=
"addConsumerQueue"
>
<
Arg
>
<
New
class
=
"com.ebd.hub.services.message.ConsumerQueue"
>
<
Arg
>jms</
Arg
>
<
Arg
>in</
Arg
>
<!-- Class and method that shall be called -->
<
Call
name
=
"addConsumer"
>
<
Arg
>com.ebd.hub.datawizard.plugin.JMS2DW</
Arg
>
<
Arg
>consume</
Arg
>
</
Call
>
</
New
>
</
Arg
>
</
Call
>
Now we only need to create the configuration file ./conf/jms2dw.properties. This file has to contain an entry <context>.<queue>=<profile name> to make sure the correct profile is addressed. JMS header properties are passed on to the profile in variables MSG_CALL_<name of the property in capital letters> if parameter addJmsPropertiesOfMessage is set to true.
Example:
jms.in=ProfileA
Summary
The configurations in files message.xml and ./conf/jms2dw.properties make sure that the data received in JMS queue JMSReceiveQueue is internally fed to context jms and queue in and sent to profile ProfileA as Lobster_data message. Profile ProfileA reacts as if any other profile had sent a message. The messages always have the type persistent and have a maximum lifetime of 24 hours.
Receiving Profile

Create a profile with an Input Agent of type Message as shown in the screenshot above and make sure it is active. At the latest at a restart of the Integration Server, the profile will fetch all the messages in queue JMSReceiveQueue.
Connection Errors
If your test messages are still on the ActiveMQ Server, the reason could be a connection error. Please check the file ./logsservices/error.log. In the case of an error, you might find a section like the following. You would get an error like this if the Apache ActiveMQ Server was not running at all, for example.
14:27:42 SYSTEM:MESSAGE:JMSLISTENER Exception in listener for dynamicQueues/JMSReceiveQueue, restarting in 60s
javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused: connect
at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:35)
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:283)
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:227)
at org.apache.activemq.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:175)
at com.ebd.hub.services.message.jms.JMSListener.init(JMSListener.java:140)
at com.ebd.hub.services.message.jms.JMSListener.run(JMSListener.java:73)
Caused by: java.net.ConnectException: Connection refused: connect
Here is another possible error.
javax.naming.NameNotFoundException: JMSReceiveQueue
at org.apache.activemq.jndi.ReadOnlyContext.lookup(ReadOnlyContext.java:225)
at javax.naming.InitialContext.lookup(InitialContext.java:411)
at com.ebd.hub.services.message.jms.JMSListener.handleQueue(JMSListener.java:166)
at com.ebd.hub.services.message.jms.JMSListener.init(JMSListener.java:158)
at com.ebd.hub.services.message.jms.JMSListener.run(JMSListener.java:73)
Important note: We will use this error to mention, that with newer versions of ActiveMQ you might have to use the prefix dynamicQueues/ (respectively dynamicTopics/), e.g. dynamicQueues/JMSSendQueue and dynamicQueues/JMSReceiveQueue. Please adjust these names in the configuration file ./etc/message.xml. See 'dynamic contexts' in ActiveMQ for more details. If all the other configurations are correct, the profile should now be able to fetch the messages.
Successful Connection Establishment

If the connection was successful and the messages have been received by the profile, the web interface of the ActiveMQ server will show a view as shown in the screenshot above.
Send Data to a JMS Server
To be able to send Lobster_data messages to a JMS system, the file ./etc/message.xml has to contain a section addMessageMap (which you already have set in the previous chapter). Additionally, the configuration file ./etc/message.xml has to contain the following entries for two additional consumer queues.
<
Call
name
=
"addConsumerQueue"
>
<
Arg
>
<
New
class
=
"com.ebd.hub.services.message.ConsumerQueue"
>
<
Arg
>jms</
Arg
>
<
Arg
>out</
Arg
>
<!-- Class and method that shall be called -->
<
Call
name
=
"addConsumer"
>
<
Arg
>com.ebd.hub.datawizard.plugin.DW2JMS</
Arg
>
<
Arg
>consume</
Arg
>
</
Call
>
</
New
>
</
Arg
>
</
Call
>
<
Call
name
=
"addConsumerQueue"
>
<!-- make context and queue visible -->
<
Arg
>
<
New
class
=
"com.ebd.hub.services.message.ConsumerQueue"
>
<
Arg
>DW2jms</
Arg
>
<
Arg
>DW2out</
Arg
>
</
New
>
</
Arg
>
</
Call
>
Lobster_data messages with context jms and queue name out shall be sent to the JMS queue (or topic) JMSSendQueue. The type (string or byte) of the JMS messages can be set in the configuration file ./conf/dw2jms.properties. The syntax is <context>.<queue>.type=<type>. If the type string is used, you also have to set the encoding with the syntax <context>.<queue>.encoding=<encoding>. Alternatively, you can declare the variables JMS_MSG_TYPE and JMS_MSG_ENCODING and save your values there. If these variables are declared, the settings in the configuration file will be ignored. All declared variables with prefix JMS_ will be set as JMS header properties, however, without the prefix JMS_, i.e. variable JMS_Invoice_No will be set as JMS header property InvoiceNo.
Example
jms.out.type=string
jms.out.encoding=8859_1
Explanation of the process with reference to context jms and queue out
You create a profile in Lobster_data with a Response Route of type Message, content CSV, and file encoding 8859_1. Then you set the context name to jms and the queue name to out. Note: The profile name will be ignored, but since it is a mandatory field, you have to enter an arbitrary value.
First of all, the Lobster_data message will be received by the subscriber com.ebd.hub.datawizard.plugin.DW2JMS from context jms and queue out and converted to a string JMS message and sent to the Lobster_data context DW2jms and queue DW2out (same values with prefix DW2). This is where the entry addMessageMap comes into play and sends the JMS message to the JMS queue (or topic) JMSSendQueue.


Send a little text file as test message in a new profile ProfileB. Configure the Response Route of that profile as shown in the screenshot above.

The web interface of the ActiveMQ server should now show a view as shown in the screenshot above.
Mass Data Processing
If a large number of messages are to be processed via a queue, the queue can be switched to file processing. There is a patch available that allows an additional option in the queue definition. If you are interested, please contact our support staff.
<!-- jms2message bridge/support -->
<
Call
name
=
"setJMSManager"
><
Arg
>
<
New
class
=
"com.ebd.hub.services.message.jms.JMSManager"
>
<
Arg
>
<
New
class
=
"com.ebd.hub.services.message.jms.JMSMapper"
>
<!-- Pass data from JMS to Lobster_data; can be repeated as often as required (for additional queues/topics) -->
<
Call
name
=
"addJMSMap"
>
<
Arg
>
<
New
class
=
"com.ebd.hub.services.message.jms.JMSMap"
>
<!-- Map JMS context/queue to message service context/queue -->
<
Arg
>ConnectionFactory</
Arg
>
<
Arg
>JMSReceiveQueue</
Arg
>
<!-- This relates to JMS2DW, see 'addConsumerQueue' -->
<
Arg
>jms</
Arg
>
<
Arg
>in</
Arg
>
<!-- Next value=false: A JMS queue is used, if true: JMS topic -->
<
Arg
type
=
"boolean"
>false</
Arg
>
<
Arg
type
=
"boolean"
>true</
Arg
><!-- write payload to file -->
...
If this parameter is set to true, the messages are no longer processed via the internal message bus but are output as *.dat in the file system under folder ./jms/in/<queue name>. See the following screenshot.
Profile for Mass Data Processing
The files output there can then be processed with a profile with time-driven Input Agent with data source File.
1. Change the event-driven Input Agent of type Message to a time-driven Input Agent with data source File with
file pattern *.dat and
folder ./jms/in/<queue name>
Do not set option Activate parallel processing if the profiles are to process the data serially according to the FIFO principle.
Switch option Sort files by to File name.
2. Set the Interval for the time-driven Input Agent with data source File.
3. The option Profile may only run in one instance (strict serial processing) must not be set.
Write Delay
There is a JVM environment variable hub.jms.writeDelay that allows delaying the JMS processing. See also section System Properties of the Integration Server.
If the server performance is not sufficient to process the messages retrieved from the external system and the folder with the payload messages is full, this variable can be set or adjusted at runtime via the Admin Console.
System Variables
The system variables JMS_JMSCorrelationID, JMS_JMSPriority, JMS_JMSExpiration can be used to set the corresponding JMS headers JMSCorrelationID, JMSPriority (0-9) and JMSExpiration (timstamp in ms).