Contents
What is JMS?
Many modern enterprise applications are built from separate software components that reside in a distributed or multi-tiered environment on several Java Virtual Machines. These disparate component need to communicate with each other and this is called messaging. JMS is one of the messaging APIs.
The JMS API provides messaging that is,
- Loosely coupled - The sender and receiver might have no information each other or the mechanisms used to process messages.
- Asynchronous - Receivers do not request messages. Messages can be delivered as they arrive. The sender does not wait for reply.
- Reliable - A message is sent and received once and only once.
What are the main components of a JMS architecture?
The following table lists the main components:
JMS Provider | This is the messaging system that implements the JMS API interfaces and provides certain control features. |
JMS Clients | System components or programs that send or receive messages. |
Messaging Domains | JMS supports both the point-to-point and publish/subscribe message domains. |
Messages | These are the objects used to communicate between JMS clients. |
Queues | Used to hold messages in the point-to-point domain. |
Topics | Used to hold messages in the publish/subscribe domain. |
Connection | A client’s active connection to the JMS provider |
Session | One or more sessions can be created for each connection. Used to create senders and receivers and administer transactions. |
What is point-to-point message passing?
With point-to-point, the sender and receiver agree on a message destination, also known as a queue. The sender leaves the message and the receiver picks it up at any time thereafter. The message remains in the queue until the receiver removes it.
What is publish/subscribe message passing?
With the publish/subscribe model, the sender, now called a publisher, again sends messages to an agreed destination. The destination is known as a topic by convention, and this time there might be many receivers that are called subscribers. Messages are immediately delivered to all current subscribers, and deleted when all the subscribers have received the message.
How to configure the ESB Profile of WSO2 Enterprise Integrator to behave as a message consumer?
Refer to section The ESB Profile of WSO2 Enterprise Integrator as a JMS Consumer.
How to configure the ESB Profile of WSO2 Enterprise Integrator to behave as a message producer?
Refer to section The ESB Profile of WSO2 Enterprise Integrator as a JMS Producer.
How to use content-based routing with the JMS transport?
There are possibly two ways to achieve this.
Accept the message from a JMS queue using a JMS proxy, and use the existing mediators to route the message based on the content. For example, Filter Mediator.
Use JMS message selector. The selector expression should be specified using the
transport.jms.MessageSelector
parameter in the JMS transport.
How to cache JMS objects with the JMS transport?
For better performance, it is important to cache JMS objects such as JMS connections, sessions, producers and consumers. Whe the JMS transport is configured in the ESB Profileof WSO2 Enterprise Integrator, it has the ability to cache JMS objects.
You can use the transport.jms.CacheLevel
parameter to configure the required cache level. It can be configured either as a proxy service parameter (when acting as a consumer), or as a parameter in the connection factory definition under the JMS transport sender section in the <EI_HOME>/conf/axis2/axis2.xml
file.
The parameter can have the following values:
Value | Description |
---|---|
auto | Uses an appropriate caching level depending on the transaction strategy. auto is the default value. |
none | No JMS object will be cached. |
connection | MS connections objects will be cached. |
session | JMS session and connection objects will be cached. |
consumer | JMS connections, sessions and consumers objects will be cached. |
producer | JMS connections, sessions and producer objects will be cached. |
How to configure JMS as a reliable transport with acknowledgments?
The following values can be used.
Duplicates Allowed | Consumer applications specify this acknowledgement mode using DUPS_OK_ACKNOWLEDGE constant defined in the Session interface. Using this mode, the session acknowledges messages lazily, which provides faster message processing times although some duplicate messages might be delivered multiple times if JMS fails. Recommended only for applications that are tolerant to message duplicates. |
Auto acknowledge | This is the default acknowledgement mode, which is specified using the AUTO_ACKNOWLEDGE constant defined in the Session interface. For each message, the session automatically acknowledges that a client has received a message in either of the following instances:
If a JMS provider or the message consumer crashes while it is processing a message, the message will either be re-delivered or lost when using the automatic acknowledgement mode. |
Client acknowledge | Consumer applications specify this acknowledgement mode using the CLIENT_ACKNOWLEDGE constant defined in the Session interface. It gives consumer more control over when messages are acknowledged. A consumer can group a number of messages, and then invoke the acknowledge method of the message to instruct the JMS provider that the message and all other messages received until this point have been consumed. When a consumer uses client acknowledge, it can use the recover method of the session to revert back to its last checkpoint. This causes the session to re-deliver all messages that have not yet been acknowledged by the consumer. If a client crashes and later re-connects to its queue or topic, the session will effectively be recovered and the consumer will receive all unacknowledged messages. |
Transactional Acknowledge | A transacted session is a related group of consumed and produced messages that are treated as a single work unit. A transaction can be either committed or rolled back. When the session's commit method is called, the consumed messages are acknowledged, and the associated produced messages are sent. When a session's rollback method is called, the produced messages are destroyed, and the consumed messages are recovered. As soon as either the commit or rollback method is called, the current transaction ends and a new transaction is immediately started. For example, if an application moves messages from one destination to another, it should use a transacted session to ensure that the message is either successfully transferred, or not transferred at all. In this case, the commit method should be called after each message. |
How to archive clustering with JMS?
Refer to section Clustering with JMS.
How to use JMS transactions?
Refer to section JMS Transactions.
How to respond the client after sending a SOAP request to the JMS queue?
This can be achieved with the following configuration. R eplace the following line according to your end point URI: <address uri=" http://localhost:9000/services/SimpleStockQuoteService "/>.
<definitions xmlns="http://ws.apache.org/ns/synapse"> <registry provider="org.wso2.carbon.mediation.registry.WSO2Registry"> <parameter name="cachableDuration">15000</parameter> </registry> <proxy name="StockQuoteProxy" transports="http" startOnLoad="true" trace="disable"> <description/> <target> <inSequence> <property name="OUT_ONLY" value="true"/> <clone> <target> <endpoint> <address uri="http://localhost:9000/services/SimpleStockQuoteService"/> </endpoint> </target> <target sequence="test"/> </clone> </inSequence> <outSequence> <send/> </outSequence> </target> </proxy> <sequence name="test"> <payloadFactory> <format> <ns:a xmlns:ns="http://services.samples"> <ns:b>Accepted</ns:b> </ns:a> </format> </payloadFactory> <property name="HTTP_SC" value="202" scope="axis2"/> <header name="To" action="remove"/> <property name="RESPONSE" value="true"/> <send/> </sequence> <sequence name="fault"> <log level="full"> <property name="MESSAGE" value="Executing default 'fault' sequence"/> <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/> <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/> </log> <drop/> </sequence> <sequence name="main"> <in> <log level="full"/> <filter source="get-property('To')" regex="http://localhost:9000.*"> <send/> </filter> </in> <out> <send/> </out> <description>The main sequence for the message mediation</description> </sequence> </definitions>
Does WSO2 EI implement JMS queues with disk persistence?
If the broker supports JMS message persistence, WSO2 EI can read/write from a persistence message queue.
How does WSO2 EI manage message recalling when the destination queue cannot be reached?
You can define message stores to handle failed messages.
How to prevent message loss due to unavailability of a data source?
If you have sent messages through JMS endpoint to an unavailable data services server, messages will get queued at the JMS broker. When you start the data services server soon after, the JMS queue will be consumed by the server. But, there can be a message loss due to the unavailability of the data source if it is configured as a Carbon Data Source.
You can avoid this message loss by setting the following parameters in the data service configuration.
1. Click on the data service in the service list, and navigate to service description page.
2. Add the following parameters to the data service. If WSO2 EI's management console UI is used to add them, y ou can add the name first and then enter the values after saving.
<parameter name="transport.jms.SessionAcknowledgement" locked="false">CLIENT_ACKNOWLEDGE</parameter> <parameter name="transport.jms.CacheLevel" locked="false">none</parameter>
This will ensure that no messages will be lost even if the data source is not available at the initialization. You might notice exceptions in the log but the inserts will be done to the database accordingly.
How can you access and modify JMS headers from within a proxy service?
You can set custom values for JMS headers from within a proxy service using the Property mediator as follows:
<property name="JMS_PRIORITY" value="2" scope="transport"/> <property name="JMS_COORELATION_ID" value="1234567" scope="transport"/> <property name="JMS_MESSAGE_ID" value="CustomMessageID" scope="transport"/>
You can then retrieve these values using get-property
function (e.g., get-property('transport','JMS_PRIORITY')
).
Ability to modify JMS headers depends on the JMS provider, where there may be limitations in modifying some headers when using certain providers. In such cases, even if the header values are set within the proxy service, they would not get modified as expected.