Lab 6: Message Driven Bean

In this lab, you will write a message-driven bean that accepts a PurchaseOrder serialized object. The bean will extract a portion of the object's data and log it to a file.

You will then write a JMS client that creates the PurchaseOrder object and sends it as a message via JMS to the message-driven bean.

Objectives:

Part 1: Configuring JMS Artifacts

Steps:

  1. Ask your instructor for the following information:

    TomEE Installation directory: ________________________________________

    If your computer has the standard lab setup on a computer running a version of Windows before Windows Vista, this directory will be:

    TomEE Installation Directory:   c:\java\apache-tomee-plus-1.7.1
               

    If your computer is running Windows Vista, Windows 7 or later, the directory will be:

    TomEE Installation directory:  c:\Users\username\java\apache-tomee-plus-1.7.1               
                

  2. Start Eclipse if it's not running, then stop the TomEE server if it's running.

  3. To make it easier to configure TomEE, you will import the TomEE configuration file into Eclipse. Follow these steps:

    1. In the Project Explorer (NOT the Servers tab at the bottom of the Eclipse window), find the Servers folder and expand it to see the TomEE server.

    2. Right-click on the TomEE server and choose Import to start the wizard.

    3. On the next page, expand the General category and select File System, then press Next.

    4. On the next page, for the From directory, browse to {TomEE Installation Directory}/conf.

      In the file list, select tomee.xml, then press Finish.

      You should see the tomee.xml file in the Servers folder in the Project Explorer.

  4. A JMS application needs to define a JMS connection factory and a JMS destination: a topic or a queue. Follow these steps to define the JMS artifacts:

    1. Open the tomee.xml file into the editor, and at the bottom of the editor, press the Source tab.

    2. Enter the following, immediately above the tomee close tag at the bottom.

      <Resource id="FooQueue" type="javax.jms.Queue"/>
      <Resource id="BarTopic" type="javax.jms.Topic"/>
                 
                 

    3. Save and close the tomee.xml file.

    4. At the bottom of the Eclipse window, in the Servers tab (NOT in the Project Explorer), right-click on the server and choose Publish to ensure that Eclipse publishes the configuration to the server.

    5. Start the server. Ensure that there are no errors in the Console, then search the Console for FooQueue to ensure that the JMS queue was defined correctly.

Part 2: Developing the EJB

Steps:

  1. As in earlier labs, create an Dynamic Web Project project named Lab06Web. Be sure to select the option to create a Web deployment descriptor.

  2. Right-click on the project and choose New - Class and create a class named PurchaseOrder in the purchaseorder package, implementing the java.io.Serializable interface. The new class doesn't need a main method. Complete the class:

    1. Define the following fields:

      private int poNumber;
      private Date poDate;
      private double amount;               
                     

      Use Source - Organize Imports to import java.util.Date.

    2. Use Source - Generate Getters and Setters to create get/set methods for all of the fields.

  3. Next, you will create the MDB. Follow these steps:

    1. Right-click on the project and choose New - Other - EJB - EJB3 Message Driven Bean to start the wizard.

    2. On the first wizard page, for the Java package, enter purchaseorder.

      For the Class name, enter ReceivePurchaseOrderBean, then press Finish.

      Eclipse creates the implementation class and opens it into the editor. Note that Eclipse wrote an empty implementation for the onMessage method -- you will complete it in a moment.

  4. Above the class definition, note that Eclipse wrote an annotation configuring the message-driven EJB. Unfortunately, the generated annotation is not completely correct for TomEE. In particular, TomEE requires two nested @ActivationConfigProperty annotations, one that defines the destination type and another that defines the destination name. Edit the generated text so that it looks like:

    @MessageDriven(activationConfig =
    {
      @ActivationConfigProperty(
            propertyName="destinationType", 
            propertyValue="javax.jms.Queue"),
      @ActivationConfigProperty(
            propertyName="destination", 
            propertyValue="FooQueue")
    })           
               
               

    Note that destination property's value matches the name of the queue you defined on TomEE in an earlier step.

  5. Your next job is to complete the onMessage method so that it extracts the PurchaseOrder serialized object from the message and writes the purchase-order number and purchase-order date to a log file. Here are some hints:

    Highlight all of the lines of code within the onMessage method and choose Source - Surround with Try/catch Block so that Eclipse writes simple exception handling code.

    Use Source - Organize Imports so that Eclipse writes the required import statements.

Part 3: Servlet Client

In this part, you will write a servlet that acts as a JMS client, sending a PurchaseOrder object in a message to your message-driven EJB.

Steps:

  1. Right-click on the project and create a new servlet named SendPurchaseOrder in the servlets package. The new servlet should override only the doGet method.

  2. Complete the new servlet:

    1. First, define fields using dependency injection that reference the JNDI resources:

      @Resource(mappedName="MyJmsConnectionFactory")
      private QueueConnectionFactory factory;               
      
      @Resource(mappedName="FooQueue")
      private Queue myQueue;
                     

      Note that these names match the JMS artifacts you created in an earlier step.

      Use Source - Organize Imports to import the correct types.

    2. In the doGet method, intialize the content type and retrieve a PrintWriter:

      response.setContentType("text/html");
      PrintWriter out = response.getWriter();               
                     

    3. Create a connection and start it, outputting an informative HTML message:

      out.println ( "<p>Creating connection...</p>" );
      QueueConnection connection = factory.createQueueConnection();
      connection.start();               
                     

    4. Create a JMS session:

      out.println ( "<p>Establishing a session...</p>" );
      QueueSession session = null;
      session = connection.createQueueSession (
              false, Session.AUTO_ACKNOWLEDGE );                
                     

    5. Create the JMS message:

      out.println ( "<p>Creating the message...</p>" );
      PurchaseOrder po = new PurchaseOrder();
      po.setPoNumber ( 1345 );
      po.setPoDate ( new java.util.Date() );
      ObjectMessage msg = session.createObjectMessage ( po );                
                    

    6. Send the message:

      out.println ( "<p>Sending the message...</p>" );
      QueueSender sender = session.createSender( myQueue );
      sender.send ( msg ); 
                    

    7. Close the connection:

      out.println ( "<p>All done, cleaning up...</p>" );
      connection.close();               
                     
                     

    8. Highlight all of the lines within the doGet method and choose Source - Surround With - Try/catch Block, then use Source - Organize Imports to bring in types from the javax.jms package.

  3. To test, right-click on SendPurchaseOrderServlet.java and choose Run As - Run on Server. You should see a Web page with your informative messages.

    To examine the results, use Windows Explorer to browse to the directory where your MDB created the log file. Then open the log file. Do you see the PO number and date?