Sunday, March 27, 2016

Jboss EAP 6.x MDB FIFO Configuration

MDBs (Message Driven Beans) provide a perfect way to implement asynchronous requests processing in J2EE applications. Generally the sequence such messages get processed, is not very important for most applications. But there can be situations where we need to make sure that the request processing is strictly FIFO (First In First Out). JBoss EAP 6.x Message Driven Beans follows almost a FIFO path but unfortunately not always. When burst of messages come to the JMS (HornetQ) there is a chance that messages get pushed to MDB none sequentially. As per RedHat "The JBoss-EAP6's default JMS broker, HornetQ supports preserve message ordering complying JMS 1.1 specification. However this does not always guarantee the "strict order" and is the expected behaviour."
There are two ways to address this issue in EAP 6.4 (i.e. to make sure message pushing to MDBs is FIFO.)
Auto Group Feature
 <connection-factory name="RemoteConnectionFactory">  
      <connectors>  
          <connector-ref connector-name="netty"/>  
      </connectors   
      <entries>  
          <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>  
      </entries>  
         <auto-group>true</auto-group>  
 </connection-factory>

This is the easiest way to implement FIFO. Just set the auto-group entry to your connection factory. Please note RedHat official documentation has a typo and it says "autogroup" but correct setting is "auto-group". When you do this setting HornetQ JMS provider make sure that the messages pushed to MDBs are strictly FIFO. It is important to understand that only one instance of your MDB pool will be used, when you set auto-group. (This is obviously the way it should be. Otherwise if more than one instance of MDBs are passed with messages, even if MDB instance firing is FIFO, it is useless. Because there is no guarantee that first one will get finished before the second, since each runs in it's own thread.)
The problem with this auto-group feature is that the configuration is at Connection factory level. This means if you have more than one MDB and all are going to be strictly FIFO and as explained above, only one instance of the pool is going to be used. If your application requirement is to have one or few MDBs to be strictly FIFO and other MDBs to be just normal where messages get processed by a pool of instances, then auto-grouping is not the ideal solution. Best solution is to use a JMSXGroupID JMS property to set a group id at client application level (or in other words at message producer level)
JMS Property JMSXGroupID
 message.setStringProperty("JMSXGroupID", "Group-0");  
Please note this is not a Jboss level setting. It should be done at the JMS message producer level (eg. Application which send JMS messages to JBOSS). And you can set any string and no need to specifically use "Group-0". In this solution also only one instance of the MDB instance in the pool is going to get used. But other MDBs which doesn't get this special property set messages has no impact and they will work in the usual behavior with pool of instances. So this way you can have some of your MDBs following strict FIFO, and others work with pool of instances.

No comments: