XXXXXXXXXXX Put note about thread pool size: <thread.pool size="100"/>
Fabric3 supports both synchronous and asynchronous remote communications using a third-party JMS provider. The JMS profile provides integration with ActiveMQ in the form of an embedded broker extension, although the profile will work with any JMS-compliant messaging middleware.
The following features are supported:
- Non-blocking operations
- Request-reply operations
- Callbacks
- Local and global (XA) transacted one-way messaging with transparent resource enlistment and recovery
Using the JMS Binding
A JMS provider can be used as the transport for one-way and request-response operations. A minimal one-way configuration is shown below:
<component name="OneWayClient">
<implementation.java class="..."/>
<reference name="service">
<binding.jms>
<destination name="serviceQueue"/>
</binding.jms>
</reference>
</component>
<component name="OneWayService">
<implementation.java class="..."/>
<service>
<binding.jms>
<destination name="serviceQueue"/>
</binding.jms>
</reference>
</component>
The above configuration uses the "serviceQueue" queue to enqueue messages. The JMS queue may be configured externally using the JMS provider and bound to JNDI or setup using Fabric3 server configuration (more on this later).
Configuring request-response operations is also straightforward and involves specifying a separate queue, which will be used to send responses (for specifics on how messages are correlated, see the SCA JMS Binding Specification):
<component name="RequestResponseClient">
<implementation.java class="..."/>
<reference name="service">
<binding.jms>
<destination name="serviceQueue"/>
<response>
<destination name="responseQueue"/>
</response>
</binding.jms>
</reference>
</component>
<component name="RequestResponseService">
<implementation.java class="..."/>
<service>
<binding.jms>
<destination name="serviceQueue"/>
<response>
<destination name="responseQueue"/>
</response>
</binding.jms>
</service>
</component>
While JMS is an asynchronous model, it is important to note that the client component will block on request-response operations until a response is received. In some cases, this is the desired behavior. In other situations, such as long-running interactions, looser coupling is required where the client can continue processing without waiting for a response to be returned. Callbacks can be used to provide responses at some later point in time. Configuring callbacks involves specifying a callback queue:
<component name="CallbackClient">
<implementation.java class="..."/>
<reference name="service">
<binding.jms>
<destination name="serviceQueue"/>
</binding.jms>
<callback>
<binding.jms>
<destination name="callbackQueue"/>
</binding.jms>
</callback>
</reference>
</component>
<component name="CallbackService">
<implementation.java class="..."/>
<service>
<binding.jms>
<destination name="serviceQueue"/>
</binding.jms>
<callback>
<binding.jms>
<destination name="callbackQueue"/>
</binding.jms>
</callback>
</service>
</component>
When the CallbackClient invokes the CallbackService, the call will return immediately. At some later point in time, a reponse will be delivered asynchronously using the "callbackQueue" queue.
In the previous examples, queues where assumed to be externally configured using Fabric3 server settings or the JMS provider. The JMS binding can also be configured to create queues dynamically by using the @create attribute on the destination element and setting it to "ifnotexist" or "always". Similarly, the JMS connection factory can be configured directly on the binding using the connectionFactory element. See the SCA JMS Binding Specification for more detail on how to do this.
Wire Formats
The JMS binding supports multiple wire formats including object serialization, JMS message types, and JAXB serialization. If a parameter type is annotated with the JAXB @XmlRootElement annotation, parameters will be sent as XML using a JMS text message. Otherwise, the JMS binding will introspect the parameter types and select the most appropriate message type (e.g. object, bytes, etc).
Configuring Connection Factories
Often, it is useful to be able to configure a set of JMS connection factories that can be used for multiple services, particularly for connection pooling. This can be done by creating a <jms> entry in the runtime systemConfig.xml. It is important to note that this is currently only supported with the ActiveMQ provider. The following shows how to setup reusable connection factories
<config>
<jms>
<connection.factories>
<connection.factory name="xaFactory"
broker.url="vm://broker" type="xa"/>
</connection.factories>
</jms>
</config>
The type attribute indicates the connection factory type to create: XA, local, or pooled. The connection factories can then be used in binding configurations as illustrated below:
<component name="CallbackClient">
<implementation.java class="..."/>
<reference name="service">
<binding.jms>
<destination name="serviceQueue"/>
</binding.jms>
</reference>
</component>
Default XA and non-XA connection factories can also be setup in systemConfig.xml. If no connection factory is specified, either the XA or non-XA factory will be used depending on whether global or local transacted messaging is required for a particular operation. Below is an example of how to set up default ActiveMQ connection factories:
<config>
<jms>
<connection.factories>
<connection.factory name="xaDefault"
broker.url="vm://broker" type="xa"/>
<connection.factory name="default"
broker.url="vm://broker"/>
</connection.factories>
</jms>
</config>
Connection Factories and Destinations using JNDI
The JMS binding can be used with external third-party providers by binding connection factories and destinations into the Fabric3 runtime's JNDI context. The following demonstrates how to access a queue bound to the name "serviceQueue" in JNDI:
<component name="CallbackService">
<implementation.java class="..."/>
<service>
<binding.jms>
<destination name="serviceQueue" create="never"/>
</binding.jms>
</service>
</component>
XA Transactions
Fabric3 supports transparent enlistment of JMS sessions in XA transactions as well as local transactions (the default). To enable transactions use the @requires attribute with transactedOneWay.global or transactedOneWay.local on a binding configuration:
<composite ...
xmlns:sca=http://docs.oasis-open.org/ns/opencsa/sca/200903>
<component name="CallbackService">
<implementation.java class="..."/>
<service>
<binding.jms requires="sca:transactedOneWay.global">
<destination name="serviceQueue"/>
</binding.jms>
</service>
</component>
</composite>
Note the transaction timeout is set by default to 30 seconds. To change this, use the transaction.timeout attribute on the <jms> element in systemConfig.xml:
<config>
<jms transaction.timeout="60">
...
</jms>
</config>
Message Autoscaling
Fabric3 supports autoscaling where the number of message listeners for a service endpoint are dynamically resized based on workload. The following are the autoscaling attributes which can be configured per endpoint as attributes on binding.jms:
- idle.limit
- transaction.timout
- receive.timeout
- max.messages
- recovery.interval
- max.receivers
- min.receivers
Configuring ActiveMQ
The JMS profile by default uses an embedded ActiveMQ broker per runtime that offers basic configuration. For simple use cases, this will likely be sufficient. For more advanced use cases, seprate broker process may be required.
ActiveMQ network and transport connectors can be setup in systemConfig.xml as follows:
<config>
<jms>
<active.mq>
<networkConnectors>
<networkConnector uri="multicast://default"/>
</networkConnectors>
<transportConnectors>
<transportConnector name="openwire"
uri="tcp://localhost:61616"/>
</transportConnectors >
</active.mq>
</jms>
</config>
Binding.SCA
When used with ActiveMQ, the JMS binding extension is configured by default to be a provider of binding.sca. This means components can be wired without configuring transports or physical endpoint information – basically as if they were components locally wired. The JMS binding extension will manage queue setup and connections transparently.
Connection factories can be configured for use with binding.sca in systemConfig.xml in the following way:
<config>
<jms>
<connection.factories>
<connection.factory name="xaFactory"
broker.url="vm://broker" type="xa"/>
<connection.factory name="nonXaFactory"
broker.url="vm://broker" type="local"/>
</connection.factories>
<binding.sca xa.factory="xaFactory"
factory= "nonXaFactory"/>
</jms>
</config>
Add Comment