Java Tutorial - Java Scipt : Message-Driven Beans

Java Tutorial - Java Scipt :

Message-Driven Beans

We will now cover the steps to create an MDB for use with JBossMQ. Believe it or not, MDBs are one of the simplest J2EE components to write and deploy. The example does assume some knowledge of JMS, which is covered in Chapter 9. This is an MDB we like that works with queues. We’ll be creating what we call an interceptor component. Let’s say you have an existing component that communicates with a queue Q1. Essentially, we will create an MDB that is registered to listen on Q2, and change the mapping for the client to have its messages routed to Q2 instead. Then, with the MDB, we can inspect the messages and pass them on to Q1. This is useful for debugging JMS environments without disrupting existing components.
Here’s the code for InterceptorMessageBean.java:
import javax.ejb.*;
import javax.jms.*;
import javax.naming.*;
public class InterceptorMessageBean
implements MessageDrivenBean, MessageListener
{
protected MessageDrivenContext m_context = null;
protected Queue m_queue = null;
protected QueueConnection m_connection = null;
protected QueueSession m_session = null;
public void setMessageDrivenContext( MessageDrivenContext context )
throws EJBException {
m_context = context;
}
/**
* Create the message-driven bean.
**/
public void ejbCreate() throws CreateException {
try {
// --- Allocate JMS resources. ---
InitialContext context = new InitialContext();
QueueConnectionFactory factory = (QueueConnectionFactory)
context.lookup( “XAConnectionFactory” );
m_queue = (Queue)
context.lookup( “java:comp/env/jms/destinationQueue” );
m_connection = factory.createQueueConnection();
}
catch( Exception e ) {
throw new CreateException( e.getMessage() );
}
}
public void ejbRemove() {
// --- Release cached JMS resources. ---
if( m_queue != null ) {
m_queue = null;
}
if( m_connection != null ) {
try {
m_connection.close();
}
catch( JMSException e ) {
e.printStackTrace();
}
m_connection = null;
}
}
public void onMessage( Message message ) {
QueueSession session = null;
System.out.println( “Interceptor got message “ + message );
try {
// --- Forward the message. ---
session = m_connection.createQueueSession( false, 0 );
QueueSender sender = session.createSender( m_queue );
sender.send( message );
System.out.println( “Message forwarded.” );
}
catch( Exception e ) {
e.printStackTrace();
}
finally {
try {
session.close();
}
catch( JMSException e ) {
e.printStackTrace();
}
}
}
}

We can compile this with the following command in Windows:

javac -classpath .;%JBOSS_HOME%\client\jbossj2ee.
jar;%JBOSS_HOME%\client\log4j.jar InterceptorMessageBean.java

And in Linux:

javac -classpath .:$JBOSS_HOME/client/jbossj2ee.
jar:$JBOSS_HOME/client/log4j.jar InterceptorMessageBean.java

Now, we’ll have to create the deployment descriptors for this MDB. There are two deployment descriptor files required for the EJB .jar file that we will be using for the InterceptorMessageBean: ejb-jar.xml and jboss.xml. The ejb-jar.xml file is a standard J2EE deployment descriptor file, and the jboss.xml deployment descriptor file holds the JBoss-specific settings. These should reside in a directory called META-INF under the base directory where the InterceptorMessageBean.class file resides.Here’s the listing for ejb-jar.xml:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE ejb-jar PUBLIC
“-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN”
“http://java.sun.com/dtd/ejb-jar_2_0.dtd”>
<ejb-jar >
<description><![CDATA[No Description.]]></description>
<display-name>Interceptor MDB</display-name>
<enterprise-beans>
<message-driven >
<description>
<![CDATA[Message Driven Bean Template]]>
</description>
<display-name>Interceptor MDB</display-name>
<ejb-name>InterceptorMessageBean</ejb-name>
<ejb-class>InterceptorMessageBean</ejb-class>
<transaction-type>Container</transaction-type>
<acknowledge-mode>Auto-acknowledge</acknowledge-mode>
<message-driven-destination>
<destination-type>javax.jms.Queue</destination-type>
<subscription-durability>NonDurable</subscription-durability>
</message-driven-destination>
<resource-ref >
<res-ref-name>jms/destinationQueue</res-ref-name>
<res-type>javax.jms.Queue</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref >
<res-ref-name>jms/testQueue2</res-ref-name>
<res-type>javax.jms.Queue</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</message-driven>
</enterprise-beans>
</ejb-jar>
And the listing for jboss.xml is:
<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE jboss PUBLIC
“-//JBoss//DTD JBOSS 3.0//EN”
“http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd”>
<jboss>
<unauthenticated-principal>nobody</unauthenticated-principal>
<enterprise-beans>
<message-driven>
<ejb-name>InterceptorMessageBean</ejb-name>
<destination-jndi-name>jms/testQueue2</destination-jndi-name>
<resource-ref>
<res-ref-name>jms/destinationQueue</res-ref-name>
<jndi-name>queue/testQueue</jndi-name>
</resource-ref>
<resource-ref>
<res-ref-name>jms/testQueue2</res-ref-name>
<jndi-name>queue/testQueue2</jndi-name>
</resource-ref>
</message-driven>
</enterprise-beans>
</jboss>

Now, let’s create our EJB jar file for deployment. We will use the jar command to do so:

jar cvf InterceptorMDB.jar InterceptorMessageBean.class META-INF\ejbjar.xml META-INF\jboss.xml
In Linux, use:

jar cvf InterceptorMDB.jar InterceptorMessageBean.class META-INF/ejbjar. xml META-INF/jboss.xml

To deploy the EJB jar file, just copy it into JBoss’s deploy directory, usually %JBOSS_HOME%\server\default\deploy. If JBoss is running, you should see a message along the lines of:
“Deployed package: file:C:/jboss- 3.0.4/server/default/deploy/InterceptorMDB.jar” That’s all there is to it! As you can see, message-driven beans are just a single class. The descriptors are minimal, and they are very powerful part of the enterprise architecture. Clean and simple! Just the way things should be!