Introduction
This simple JMS application has you submit a form which sends a message to a JBoss queue. A Message-Driven Bean (MDB) will be listening on that queue destination and receives the mssage and processes it.
The Setup
Download the source Download the source above and unzip it into your project directory of choice. For eclipse users the source comes with an eclipse project so you can just import that project file and be good to go. To build using ant, type 'ant all' or if you want to build and deploy to jboss type 'ant deploy' to build and deploy the ear to JBoss.

Java5 The Java5 JDK needs to be set as your environment. JAVA_HOME env variable needs to be defined pointing to yth the JDK home directory.

JBoss 4.x - Download JBoss 4.x here http://labs.jboss.com/portal/jbossas/download. Since you'll be probably be coding with the EJB 3.0 spec soon enough, set up JBoss4.x using the installer as described on the download page. After JBoss is installed declare a JBOSS_HOME environment variable pointing to the JBoss root directory.

Running the example If you've built the project usingg ant (ant deploy), the ear will be deployed to jboss and you simply go to your jboss home dir/bin and start jboss with run.sh (Nix flavors) or run.bat (Windows). If you want to just see the app run you can download the ear above and put the ear into your jboss/default/deploy directory. Once jboss is started, go the following url: http://localhost:8080/rr-jms

A Note About XDoclet
XDoclet reduces the amount of annoying code you have to write when dealing with EJB 2.1. I didn't use XDoclet here since I wanted to show all the steps you'd have go through to work with EJBs when not using XDoclet. EJB3 is also greatly simplified with the use of annotations. (MDBs are a type of EJB.)
web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
	version="2.4">
	<display-name>rr-email-jms example</display-name>

	<servlet>
		<servlet-name>AppServlet</servlet-name>
		<servlet-class>net.learntechnology.jms.AppServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>AppServlet</servlet-name>
		<url-pattern>/StartLongProcess</url-pattern>
	</servlet-mapping>

	<resource-ref>
		<res-ref-name>jms/LongProcessQueue</res-ref-name>
		<res-type>javax.jms.Queue</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>
	
	<resource-ref>
		<res-ref-name>jms/AppQueueConnectionFactory</res-ref-name>
		<res-type>javax.jms.QueueConnectionFactory</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>

</web-app> 
jboss-web.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.4//EN"
 "http://www.jboss.org/j2ee/dtd/jboss-web_4_0.dtd">

<jboss-web>
	<resource-ref>
		<res-ref-name>jms/LongProcessQueue</res-ref-name>
		<jndi-name>queue/LongProcessQueue</jndi-name>
	</resource-ref>
	<resource-ref>
		<res-ref-name>jms/AppQueueConnectionFactory</res-ref-name>
		<jndi-name>java:/JmsXA</jndi-name>
	</resource-ref>
</jboss-web>

index.jsp form
<form name="appForm" action="StartLongProcess">
    Your name: lt;input type="text" name="name" size="40">
<br/>
<input type="submit" value="Kick-off The Long Process"/> </form>
AppServlet

public class AppServlet extends HttpServlet {
    private static final String QUEUE_CONNECTION_FACTORY = "java:comp/env/jms/AppQueueConnectionFactory";
    private static final String LONG_PROCESS_QUEUE = "java:comp/env/jms/LongProcessQueue";

    public void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
    	System.out.println("in doPost of AppServlet..");
    	String name = request.getParameter("name");
    	System.out.println("name: "+name );
    	ProcessDTO processDTO = new ProcessDTO();
    	processDTO.setName(name);
		JmsProducer.sendMessage(processDTO, QUEUE_CONNECTION_FACTORY, LONG_PROCESS_QUEUE);
		request.setAttribute("started",true);
		RequestDispatcher dispatcher =  getServletContext().getRequestDispatcher("/index.jsp");
        dispatcher.forward(request, response);
    }
}
JmsProducer

public class JmsProducer {
    private JmsProducer() {}
    public static void sendMessage(Serializable payload, String connectionFactoryJndiName, 
        String destinationJndiName) throws JmsProducerException {
        try {
            ConnectionFactory connectionFactory = null;
            Connection connection = null;
            Session session = null;
            Destination destination = null;
            MessageProducer messageProducer = null;
            ObjectMessage message = null;
            System.out.println("In sendMessage of JmsProducter, 
                getting ConnectionFactory for jndi name: "+connectionFactoryJndiName );
            connectionFactory = ServiceLocator.getJmsConnectionFactory(
                                                     connectionFactoryJndiName);

            connection = connectionFactory.createConnection();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            destination = ServiceLocator.getJmsDestination(destinationJndiName);
            messageProducer = session.createProducer(destination);
            message = session.createObjectMessage(payload);
            messageProducer.send(message);
            System.out.println("Message sent to messageProducer");
            messageProducer.close();
            session.close();
            connection.close();
        } catch (JMSException je) {
            throw new JmsProducerException(je);
        } catch (ServiceLocatorException sle) {
            throw new JmsProducerException(sle);
        }
    }
}
ServiceLocator

public class ServiceLocator {
   private ServiceLocator() {}
     public static ConnectionFactory getJmsConnectionFactory(String jmsConnectionFactoryJndiName)
             throws ServiceLocatorException {
        ConnectionFactory jmsConnectionFactory = null;
        try {
            Context ctx = new InitialContext();
            jmsConnectionFactory = (ConnectionFactory) ctx.lookup(jmsConnectionFactoryJndiName);
        } catch (ClassCastException cce) {
            throw new ServiceLocatorException(cce);
        } catch (NamingException ne) {
            throw new ServiceLocatorException(ne);
        }
        return jmsConnectionFactory;
    }
    public static Destination getJmsDestination(String jmsDestinationJndiName) 
            throws ServiceLocatorException {
        Destination jmsDestination = null;
        try {
            Context ctx = new InitialContext();
            jmsDestination = (Destination) ctx.lookup(jmsDestinationJndiName);
        } catch (ClassCastException cce) {
            throw new ServiceLocatorException(cce);
        } catch (NamingException ne) {
            throw new ServiceLocatorException(ne);
        }
        return jmsDestination;
    }
}
rr-email-jms-destinations-service.xml

<server>
    <mbean code="org.jboss.mq.server.jmx.Queue"
           name="jboss.mq.destination:service=Queue,name=LongProcessQueue">
      <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
    </mbean>
</server>
application.xml

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                                 http://java.sun.com/xml/ns/j2ee/application_1_4.xsd"
             version="1.4">
    <display-name>rr-jms-allinone EAR</display-name>
    <module>
        <web>
            <web-uri>rr-jms-webapp.war</web-uri>
            <context-root>rr-jms</context-root>
        </web>
    </module>
    <module>
        <java>common.jar</java>
    </module>
    <module>
        <ejb>rr-jms-ejb.jar</ejb>
    </module>
</application>
LongProcessMessageBean

public class LongProcessMessageBean implements MessageDrivenBean, MessageListener {

    //...

    public void onMessage(Message message) {
    	String name = null; 
        try {
            if (message instanceof ObjectMessage) {
                ObjectMessage objMessage = (ObjectMessage) message;
                Object obj = objMessage.getObject();
                if (obj instanceof ProcessDTO) {
                	name = ((ProcessDTO)obj).getName();
			    	System.out.println("****************************************************");
			        System.out.println("LongProcessMessageBean.onMessage(): Received message. NAME: "+name);
			    	System.out.println("****************************************************");
			    	System.out.println("Now calling LongProcessService.doLongProcess");
                    ProcessResult result = LongProcessService.doLongProcess((ProcessDTO)obj);
                 } else {
                    System.err.println("Expecting ProcessDTO in Message");
                }
            } else {
                System.err.println("Expecting Object Message");
            }
            System.out.println("*******************************************");
            System.out.println("Leaving LongProcessMessageBean.onMessage(). NAME: "+name );
            System.out.println("*******************************************");
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}
ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd"
	version="2.1">

	<description>ejb-jar.xml for rr-jms-allinone</description>
	<display-name>ejb-jar.xml</display-name>

	<enterprise-beans>
      <message-driven >
         <description>Long Process Message MDB</description>
         <display-name>LongProcessMessageMDB</display-name>
         <ejb-name>LongProcessMessageBean</ejb-name>
         <ejb-class>net.learntechnology.ejb.LongProcessMessageBean</ejb-class>
         <messaging-type>javax.jms.MessageListener</messaging-type>
         <transaction-type>Container</transaction-type>
         <message-destination-type>javax.jms.Queue</message-destination-type>
         <activation-config>
           <activation-config-property>
             <activation-config-property-name>destinationType</activation-config-property-name>
             <activation-config-property-value>javax.jms.Queue</activation-config-property-value>
           </activation-config-property>
           <activation-config-property>
             <activation-config-property-name>acknowledgeMode</activation-config-property-name>
             <activation-config-property-value>Auto-acknowledge</activation-config-property-value>
           </activation-config-property>
           <activation-config-property>
             <activation-config-property-name>subscriptionDurability</activation-config-property-name>
             <activation-config-property-value>NonDurable</activation-config-property-value>
           </activation-config-property>
         </activation-config>
      </message-driven>
	</enterprise-beans>

	<assembly-descriptor>
	</assembly-descriptor>

</ejb-jar>
jboss.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 4.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd">
<jboss>
	<enterprise-beans>
      <message-driven>
         <ejb-name>LongProcessMessageBean</ejb-name>                       
         <destination-jndi-name>queue/LongProcessQueue</destination-jndi-name>
      </message-driven>
	</enterprise-beans>
	<assembly-descriptor></assembly-descriptor>
	<resource-managers></resource-managers>
</jboss>
Code and Lesson - Rick Reumann