JBoss AS 7: sending JMS messages across Java EE components

In this short tutorial we will give a tip about sending messages between Java EE components such as Servlet/EJB and MDBs.

 

JMS objects like connection, session, consumer and producer were designed to be re-used. In most implementations connection and session are pretty heavyweight to setup and consumer usually requires a network round trip to set up. Producer is often more lightweight, although there is often some overhead in creating it.

 

The simplest way to code a Java EE JMS client is by adding injections of JMS resources such as:

public class SomeServlet extends HttpServlet {

@Resource(mappedName = "queue/testQueue")
private Queue queueExample;

@Resource(mappedName = "java:/ConnectionFactory")
private ConnectionFactory cf;

    public void sendMessage() {

            connection = cf.createConnection();
            . . . .
        }
}


There is a potential pitfall in this approach, since we will need to create a new connection each time we send a JMS message. Even if the JMS client is located on the same JVM as the MDB consumer, it can lead to some overhead in your JMS applications, especially if you are sending lots of messages and you expect good performances.
The best practice is to use the pooled connection factory instead of java:/ConnectionFactory. This factory is defined within the messaging subsystem:
<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>


The pooled connection factory is special in that it leverages the outbound adapter of the HornetQ JCA Resource Adapter therefore providing superior performance compared with the standard JMS Connection factory.  It is by default available to local clients although it can be configured to work with a remote server.

 

 As the name suggests, resources acquired from it will be automatically enlisted any on-going JTA transaction.  If you want to send a message from an EJB using CMT then this is likely the connection factory you want to use so the send operation will be atomically committed along with the rest of the EJB's transaction operations.

 

You can configure your application to use the pooled connection factoryby replacing the java:/ConnectionFactory with:

@Resource(mappedName = "java:/JmsXA")

Finally, you can use the CLI interface to configure the min and max size of the pooled connection factory:


/subsystem=messaging/hornetq-server=default/pooled-connection-factory=hornetq-ra/:write-attribute(name=min-pool-size,value=10)
/subsystem=messaging/hornetq-server=default/pooled-connection-factory=hornetq-ra/:write-attribute(name=max-pool-size,value=50)

References: https://docs.jboss.org/author/display/AS72/Messaging+configuration


Advertisement