The JCA Java Connector Architecture provides the most efficient way of thread pooling, resource pooling, transaction handling and consumption on JMS and other Resource Adapters. For example if you are consuming JMS messages, the JCA container provides the most efficient way of pooling the JMS sessions and connections, pooling threads and processing messages in parallel as well as transaction and exception handling.
The following are the steps to configure a Message Driven POJO in Spring with Jencks. There is the complete XML here
Configure the JCA Container
Just add the following to your Spring configuration file
<!-- lets use the default configuration of work manager and transaction manager-->
<property name="bootstrapContext">
<bean class="org.jencks.factory.BootstrapContextFactoryBean">
<property name="threadPoolSize" value="25"/>
</bean>
</property>
<!-- the JCA Resource Adapter -->
<property name="resourceAdapter">
<bean id="activeMQResourceAdapter" class="org.apache.activemq.ra.ActiveMQResourceAdapter">
<property name="serverUrl" value="tcp://localhost:51616"/>
</bean>
</property>
</bean>
Which will create the JCA container.
Notice that the bootstrapContext property is used to create the JCA BootstrapContext which includes the WorkManager (which is the JCA ThreadPool). This allows you to configure the thread pool size, transaction manager and so forth.
Notice that there is a work manager you can configure to set the thread pooling limits.
Also you can associate whichever JCA Resource Adapter you wish, such as to use another JMS provider. If you have a modern JMS like ActiveMQ it will come with its own optimised Resource Adapter. If your JMS provider does not have its own RA then consider using the GenericRA
Consuming inbound JMS messages
The following shows an example:
<bean id="echoBean" class="org.jencks.TestBean" singleton="true"/>
The activation specification is dependent on the JCA Resource Adapter being used. If you are using ActiveMQ as your resource adapter then here are all the various properties you can configure, giving you full control over every aspect of the JMS subscription, pooling and delivery mode.
The POJO which implements the JMS MessageListener interface is referenced via the ref property in the inbound connector. The echoBean in this example can be any POJO created by Spring. If you wish you can use a spring singleton, or can add your own Spring interceptors around it - though note that Jencks already takes care of security and transaction handling for you automatically.
If you are using XA transactions on inbound messages and want to support recovery (that is on start up any in-progress transactions are recovered) then you must specify an id or name in the Spring XML configuration for the inbound connector as shown above. Failing to do so with a transaction manager such as Geronimo's will result in an exception during recovery.
Configuring the concurrency of message processing
One of the main points of using JCA is to allow you to process inbound messages concurrently in a thread pool using a pool of JMS connections and sessions. There are 2 main configuration points you can use in Jencks
the thread pool size defines the maximum number of concurrent messages that can be processed in Jencks across any subscription in that JCAContainer.
for some ActivationSpec implementations you can further configure the subscription to define the concurrency model. For example in ActiveMQ you can specify the maxSessions and maxMessagesPerSessions properties to configure how many concurrent messages can be processed for that subscription.
Using both approaches you can define how many threads are used for all the subscriptions and also how many of those threads can be used up by each subscription. This means you can segment your subscriptions to ensure one subscription doesn't overload other subscriptions.
You can also create multiple JCAContainer instances to allow you to have completely separate thread pools for different kinds of subscriptions if you wish.
Avoiding coupling your code to the JMS API
If you would rather avoid using the JMS MessageListener interface altogether you could use Spring Remoting with Jencks using the Lingo library.
Lingo is an implementation of Spring Remoting which adds remoting onto any POJO model. Lingo then takes care of all of the JMS code on both the client side and server side for you; marshalling things into and out of JMS Messages for you.
See the Lingo JCA example
Using XA
To use XA for an inbound connection in the JCA container you'll need to specify a transaction manager to the inbound connector. Here's an example