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.

ServiceMix provides JCA versions of its components for easy deployment in our JCA Container.

Using JMS with JCA

The most efficient way of consuming JMS is through JCA. This lets the JCA container handle the pooling of the session and connections, providing a way to efficiently process messages in parallel, as well as dealing with transactions and exception handling.

The steps to use JMS over JCA with ServiceMix are as follows.

Configure the JCA Container

Just add the following to your Spring configuration file

<bean id="jencks" class="org.jencks.JCAContainer">

  <!-- 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"/>
      <property name="transactionManager" ref="transactionManager"/>
    </bean>
  </property>


  <!-- the JCA Resource Adapter -->
  <property name="resourceAdapter">
    <bean id="activeMQResourceAdapter" class="org.apache.activemq.ra.ActiveMQResourceAdapter">
      <property name="serverUrl" value="tcp://localhost:61626"/>
    </bean>
  </property>
</bean>

 

Which will create the JCA container. 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.

Configure the JMS with JCA component.

We have a JmsInUsingJCABinding which works nicely with our JCA container to provide a JBI component for consuming inbound JMS messages using JCA for all the session, connection and thread pooling as well as handling parallel processing of inbound messages and transaction handling.

<sm:activationSpec componentName="myJmsReceiver" service="foo:myJmsReceiver" destinationService="foo:receiver">
  <sm:component><bean class="org.apache.servicemix.components.jms.JmsInUsingJCABinding">

    <property name="jcaContainer" ref="jencks"/>

    <property name="activationSpec">
      <bean class="org.apache.activemq.ra.ActiveMQActivationSpec">
        <property name="destination" value="test.org.apache.servicemix.example.jca"/>
        <property name="destinationType" value="javax.jms.Topic"/>
      </bean>
    </property>
  </bean></sm:component>
</sm:activationSpec>

 

You will notice that its not very different from the regular JMS component; the main difference is the use of the J2EE activation spec object to register with the JCA container.

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.

Using XA

To use XA for an inbound connection in the JCA container you'll need to specify a transaction manager to the connector. Here's an example

<sm:activationSpec componentName="myJmsReceiver" service="foo:myJmsReceiver" destinationService="foo:receiver">
  <sm:component><bean class="org.apache.servicemix.components.jms.JmsInUsingJCABinding">

    <property name="jcaContainer" ref="jencks"/>

    <property name="activationSpec">
      <bean class="org.apache.activemq.ra.ActiveMQActivationSpec">
        <property name="destination" value="test.org.apache.servicemix.example.jca"/>
        <property name="destinationType" value="javax.jms.Topic"/>
      </bean>
    </property>

    <!-- use XA transactions -->
    <property name="transactionManager" ref="transactionManager"/>
    <property name="synchronous" value="true"/>
  </bean></sm:component>
</sm:activationSpec>

 

You also need to provide a transaction manager implementation to use. Here this exampe uses Geronimo's Transaction Manager.

<bean id="transactionManager" class="org.jencks.factory.TransactionManagerFactoryBean">
  <property name="transactionLogDir" value="target/txlog" />
</bean>