Handling transactions in JBoss ESB

User Rating: 0 / 5

Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 

jboss esbIn the first tutorial about JBoss ESB we have learnt the basics about the Service Bus and which are the basic components of it. In this tutorial we will learn how to use JTA Transactions within a set of ESB actions.

 


That most important lesson we have learnt is that all interactions between clients and services within JBossESB occur through the exchange of Messages. Message can be used to build loose coupled applications which are the basis to develop SOA applications.
If we have a look at the JBoss ESB configuration is mainly split into two pieces: 

 

Providers: This part of the model centrally defines all the message <bus> providers used by the message <listener>s, defined within the <services> section of the model.  

Services: This part of the model centrally defines all of the services under the control of a single instance of JBoss ESB.


For the purpose of learning about transactions, we will concentrate on the definition of Providers. An example of Provider is a jms-provider which listen for messages which are placed in a queue/topic:

 <jms-provider name="JBossMQ" connection-factory="ConnectionFactory">
  <jms-bus busid="quickstartGwChannel">
    <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_helloworld_Request_gw"
 />
 </jms-bus>
              
A more advanced example of jms provider is the <jms-jca-provider>. This provider can be used in place of the <jms-provider> to enable delivery of incoming messages using JCA inflow. This introduces a transacted flow to the action pipeline, and thereby encompasses actions within a JTA transaction.
 <jms-jca-provider name="JBossMessaging" connection-factory="XAConnectionFactory">
   <jms-bus busid="quickstartGwChannel">
     <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_helloworld_Request_gw" transacted="true" />
 </jms-bus>
 <activation-config>
   <property name="dLQMaxResent" value="1"/>
 </activation-config>
 </jms-jca-provider>
          
We will test this provider using an out-of-box action named EJBProcessor.          
The EJBProcessor action takes an input Message and uses the contents to invoke a Stateless Session Bean. (This action supports EJB2.x and EJB3.x).

So let's modify one of the distribution ESB examples to test a JTA Transaction.

Here's a simple Stateless EJB 3 with 2 actions. Tne first one performs a Database Insert and the other rollback the transaction depending on the content of the message received:
@Stateless
 
public class SimpleSLSB implements SimpleRemote
{
 String messageLog;
 DataSource dataSource = null;
 @Resource
 private SessionContext context;
  @Resource(mappedName = "OracleDS")
  public void setDataSource(DataSource dataSource) {
    this.dataSource = dataSource;
  }
 
  public void action1(final String message) {  

  Connection connection = null;
  PreparedStatement stmt = null;
  System.out.println("SimpleSLSB printMessage : " + message);
  try {
  connection = dataSource.getConnection();
  stmt = connection.prepareStatement("insert into dummytable values ('"+message+"',sysdate)");
  stmt.execute();         
  }

  catch (SQLException e) {
   System.out.println("Insert failed!");
   // TODO Auto-generated catch block
   e.printStackTrace();
  }  
  finally {
   try {
    stmt.close();
    connection.close();
 
   }
   catch (SQLException e) {
    // TODO Auto-generated catch block
     e.printStackTrace();
   } 
  }
 }
 
  public void action2(final String message) {    
  if (message.equals("rollback") {
   messageLog="Transaction rolled back";
   context.setRollbackOnly();
   throw new EJBException("Rolling back JTA Transaction"); 
  }
 
 }
  public String getMessage() {
   return messageLog;
  }
}

And this is the jboss-esb.xml configuration file:
<?xml version = "1.0" encoding = "UTF-8"?>
<jbossesb
 xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd"
 parameterReloadSecs="5">

 <providers>


 <jms-jca-provider name="JBossMessaging"
 connection-factory="XAConnectionFactory">
 <jms-bus busid="quickstartGwChannel">
 <jms-message-filter dest-type="QUEUE"
 dest-name="queue/quickstart_ejbprocessor_Request_gw" transacted="true" />
 </jms-bus>
 <jms-bus busid="quickstartEsbChannel">
 <jms-message-filter dest-type="QUEUE"
 dest-name="queue/quickstart_ejbprocessor_Request_esb" transacted="true" />
 </jms-bus>
 <activation-config>
 <!--
 The maximum number of times a message is redelivered before it is
 sent to the DLQ
 -->
 <property name="dLQMaxResent" value="1" />
 </activation-config>
 </jms-jca-provider>
 </providers>

 <services>
 <service category="EJBProcessor" name="SimpleService"
 description="Service that demonstrates calling EJBs">

 <listeners>
 <jms-listener name="JMS-Gateway" busidref="quickstartGwChannel"
 maxThreads="1" is-gateway="true" />
 <jms-listener name="helloWorld" busidref="quickstartEsbChannel"
 maxThreads="1" />
 </listeners>

 <actions mep="OneWay">

 <action name="EJBTestVoid" class="org.jboss.soa.esb.actions.EJBProcessor">
 <property name="ejb3" value="true" />
 <property name="method" value="action1" />
 <property name="jndi-name" value="SimpleSLSB/remote" />
 <property name="initial-context-factory" value="org.jnp.interfaces.NamingContextFactory" />
 <property name="provider-url" value="localhost:1099" />
 <property name="ejb-params">
 <arg0 type="java.lang.String">somedata</arg0>
 </property>
 </action>


 <action name="EJBTestVoid2" class="org.jboss.soa.esb.actions.EJBProcessor">
 <property name="ejb3" value="true" />
 <property name="method" value="action2" />
 <property name="jndi-name" value="SimpleSLSB/remote" />
 <property name="initial-context-factory" value="org.jnp.interfaces.NamingContextFactory" />
 <property name="provider-url" value="localhost:1099" />
 <property name="ejb-params">
 <arg0 type="java.lang.String">rollback</arg0>
 </property>
 </action>

 <action name="debug" class="org.jboss.soa.esb.actions.SystemPrintln">
 <property name="printfull" value="false" />
 <property name="message" value="Value from getMessage" />
 </action>

 <!-- The next action is for Continuous Integration testing -->
 <action name="testStore" class="org.jboss.soa.esb.actions.TestMessageStore" />

 </actions>
 </service>

 </services>

</jbossesb>

As you can see, there's a pipeline of two actions (action1 and action2) which are called sequentially.
If the action2 receives as parameter "rollback" the transaction will be rolledback. What does the trick is
the XAConnectionfactory, which enlists the actions in a JTA transaction:
 <jms-jca-provider name="JBossMessaging" connection-factory="XAConnectionFactory">
    
If you experiment switching to a non-xa Connection factory:
<jms-jca-provider name="JBossMessaging" connection-factory="ConnectionFactory">

you will see that the transaction is actually committed when action1 is executed.

Follow us on Twitter