Thursday 31 October 2013

JMS Connection Factories Explained

What ConnectionFactory should I use in my application ?

I thought it would be good to explain a bit about connection factories before I go on explaining JMS 2.0. The connection factories are one of the two administrative objects offered by JMS API. Both JMS 1.1 and 2.0 support the generic ConnectionFactory. The connection factories support concurrent use just like the Destination administrative object. There are domain specific connection factories in JMS 1.1 spec and they remain unchanged in 2.0. I personally discourage the use of domain specific connection factories just as it was said in the spec. The WildFly application server provides four connectionfactory instances on its default JMS provider, HornetQ's configuration :

<jms-connection-factories>
   <connection-factory name="InVmConnectionFactory">
      <connectors>
         <connector-ref connector-name="in-vm"/>
      </connectors>
      <entries>
         <entry name="java:jboss/DefaultJMSConnectionFactory"/>
         <entry name="java:/ConnectionFactory"/>
      </entries>
   </connection-factory>
   <connection-factory name="ServletConnectionFactory">
      <connectors>
         <connector-ref connector-name="servlet"/>
      </connectors>
      <entries>
         <entry name="java:jboss/exported/jms/ServletConnectionFactory"/>
      </entries>
   </connection-factory>
   <connection-factory name="RemoteConnectionFactory">
      <connectors>
         <connector-ref connector-name="netty"/>
      </connectors>
      <entries>
         <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
      </entries>
     <confirmation-window-size>100</confirmation-window-size>
   </connection-factory>
   <pooled-connection-factory name="hornetq-ra">
      <transaction mode="xa"/>
      <connectors>
         <connector-ref connector-name="in-vm"/>
      </connectors>
      <entries>
         <entry name="java:/JmsXA"/>
      </entries>
   </pooled-connection-factory>
</jms-connection-factories>

The connection factory instances differentiate by their characteristics. I would rather explain in terms of transport layer and on application type to aid what instance to be used in a client application. 

Remote JMS clients :
I would recommend the factory bound at jms/RemoteConnectionFactory or jms/ServletConnectionFactory for remote JMS clients. The latter uses servlet transport over the configured http port where as the former uses netty on port 5445. The http bound connection factory resolves the need of opening a port on the firewall.

Clients inside the same container :
The clients who reside the in the same container should obtain connections from the JCA based connection factory; from the factory bound at java:/JmsXA. It is considered an anti-pattern to obtain connections other than the factory bound at java:/JmsXA . When you obtain connections from this factory, you're indeed obtaining connections from the ManagedConnectionPool (MCP).

When you obtain connections from the factory bound at java:/JmsXA, it's not only just a method call but the connection objects support two phase commit protocol. Hence, they can be enlisted in a global transaction. Further you're obtaining connections from JCA's MCP,  with the container managed security. 

However there's a limitation imposed by the JEE 7 specification, under the section 6:7. It does not permit EJB/Web applications to have more than a single active session from a connection obtained from the MCP. This restriction does not encourage JMS clients to use a JVM based connection factory inside the container, which is meant for legacy JMS applications. Instead, the users must make sure to reuse JMS objects efficiently since JMS objects are reusable.

The purpose of using a JMS resource adapter is compromised and nullified when JMS clients obtain connections from anywhere other than the managed connection pool; when they JMS clients are inside the same container. It is a bad practice use any connection factory than the JCA based factory.

The JMS ConnectionFactory and Connection objects can be concurrently accessed and reusable. The plain JMS clients must make sure to cache and reuse connection objects instead of obtaining a connection at each message send. Although session objects are reusable, I would not encourage them to be shared across threads, to assure thread safety. Further, it might have an adverse impact on transacted sessions. However, you don't have to cache JMS resources inside the container, the container does this for you when you obtain connections from the MCP.

No comments:

Post a Comment