EJB 2.1: Message Linking

Message linking is a new feature to EJB 2.1 that allows the messages being sent by any enterprise bean to be routed to a specific message-driven bean in the same deployment. By using message linking, you can orchestrate a flow of messages between components in the same application. For example, in the beginning of this chapter, the TravelAgent EJB from Chapter 11 was re-implemented so that it sent a JMS message with the ticket information to a Topic destination. Here’s a different implementation of the TravelAgent EJB’s bookPassage( ) method, this time using an ObjectMessage type:

public TicketDO bookPassage(CreditCardDO card, double price)
    throws IncompleteConversationalState {
                   
    if (customer == null || cruise == null || cabin == null) {
        throw new IncompleteConversationalState( );
    }
    try {
        ReservationHomeLocal resHome = (ReservationHomeLocal)
            jndiContext.lookup("java:comp/env/ejb/ReservationHomeLocal");
        ReservationLocal reservation =
            resHome.create(customer, cruise, cabin, price, new Date( ));
        Object ref = jndiContext.lookup
            ("java:comp/env/ejb/ProcessPaymentHomeRemote");
        ProcessPaymentHomeRemote ppHome = (ProcessPaymentHomeRemote)
            PortableRemoteObject.narrow(ref, ProcessPaymentHomeRemote.class);
        ProcessPaymentRemote process = ppHome.create( );
        process.byCredit(customer, card, price);

        TicketDO ticket = new TicketDO(customer,cruise,cabin,price);


        TopicConnectionFactory factory = (TopicConnectionFactory)
               jndiContext.lookup("java:comp/env/jms/TopicFactory");
               Topic topic = (Topic)
               jndiContext.lookup("java:comp/env/jms/TicketTopic");
               TopicConnection connect = factory.createTopicConnection( );
               TopicSession session = connect.createTopicSession(true,0);
               TopicPublisher publisher = session.createPublisher(topic);

               ObjectMessage objectMsg = session.createObjectMessage( );
               objectMsg.setObject(ticket);
               publisher.publish(objectMsg);
               connect.close( );

        return ticket;
    } catch(Exception e) {
        throw new EJBException(e);
    }
}

When we discussed this method earlier in the chapter, we never really mentioned where the ticket message was being sent. It could go to the reservation agent or some other department of Titan Cruises. However, message linking makes sure that the message goes directly to a message-driven bean that we deploy.

For example, we might deploy a message driven bean, the TicketDistributor EJB, that is responsible for distributing ticket information to several different targets such as legacy databases, partner organizations, marketing, etc. Figure 12-5 shows how the TicketDistributor EJB (an MDB) works with the TravelAgent EJB to distribute ticket information to several different targets.

Message flow with message linking

Figure 12-5. Message flow with message linking

The TicketDistributor distributes the ticket information to a variety of disparate targets, including a separate relational database using JDBC, a legacy system (e.g., IMS, CICS, etc.) using a J2EE Connector, and email using JavaMail. The TravelAgent EJB could have handled this type of distribution directly, but defining a separate MDB to do distribution provides more flexibility and better performance.

The TicketDistributor MDB is more flexible because the routing for the message can be changed without modifying the TravelAgent EJB. The TravelAgent EJB always sends messages to the same JMS topic; it’s the responsibility of the TicketDistributor to distribute the ticket information to other sources. The TicketDistributor also improves performance, because the TicketAgent doesn’t have to wait on the various targets (a separate database, legacy system, and email) to accept and process the message before finishing the reservation. The TicketAgent just sends the ticket information and forgets about it. It’s the responsibility of the TicketDistribution MDB to distribute the ticket information to the appropriate parities. In addition, the TravelAgent EJB doesn’t have to coordinate a distributed transaction across different resources, which can create significant bottlenecks and affect throughput.

In order to link the outgoing messages sent by the TravelAgent EJB with the incoming messages consumed and processed by the TicketDistribution MDB, we need to define <message-destination-link> elements in the deployment descriptor. The <message-destination-link> element is defined by the <message-destination-ref> element of the TravelAgent EJB. The TicketDistributor EJB also declares the <message-destination-link> element. Both elements reference the same logical destination declared in the assembly descriptor:

<ejb-jar ...>

  <enterprise-beans>
    ...
    <session>
        <ejb-name>TravelAgentBean</ejb-name>
        ...
        <resource-ref>
            <res-ref-name>jms/TopicFactory</res-ref-name>
            <res-type>javax.jms.TopicConnectionFactory</res-type>
            <res-auth>Container</res-auth>
        </resource-ref>
        <message-destination-ref>
            <message-destination-ref-name>
                   jms/TicketTopic
            </message-destination-ref-name>
            <message-destination-type>javax.jms.Topic</message-destination-type>
            <message-destination-usage>Produces</message-destination-usage>
            <message-destination-link>
                 Distributor
               </message-destination-link>
        </message-destination-ref>
        ...
    </session>
    <message-driven>
        <ejb-name>TicketDistributorEJB</ejb-name>
        <ejb-class>
            com.titan.distributor.TicketDistributorBean
        </ejb-class>
        <messaging-type>javax.jms.MessageListener</messaging-type>
        <transaction-type>Bean</transaction-type> 
        <message-destination-type>
            javax.jms.Topic
        </message-destination-type>  
        <message-destination-link>
               Distributor
               </message-destination-link>
        ...
    </message-driven>
    ...
  </enterprise-beans>
  <assembly-descriptor>
    ...
    <message-destination>
               <message-destination-name>Distributor</message-destination-name>
               </message-destination>
    ...  
  </assembly-descriptor>
</ejb-jar>

As you know, a <message-destination-ref> element declares the destination to which an enterprise beans sends or receives messages. When the <message-destination-ref> includes a <message-destination-link> element, it means that message senders and receivers will be sharing a logical destination described in the assembly-descriptor. In the example above, the TravelAgent EJB’s <message-destination-ref> declares a <message-destination-link> , which points to the <message-destination> element in the <assembly-descriptor> that has the name Distributor. The <message-destination-link> defined by the TicketDistributor MDB points to the same <message-destination> element. This means the messages sent by the TravelAgent EJB to the Distributor message destination will go to the TicketDistributor MDB.

Message-driven beans always consume messages from the destination defined by the <message-destination-link> element defined directly under the <message-bean> element. However, they can also produce messages that are sent to a logical message destination if they use the message API described by their own <message-destination-ref> element. The following listing shows that the TicketDistributor consumes messages from the Distributor destination, but also uses the JMS to send messages to a completely different destination, called Partner:

<ejb-jar ...>

  <enterprise-beans>
      ...
       <message-driven>
      <ejb-name>TicketDistributorEJB</ejb-name>
      <ejb-class>
          com.titan.distributor.TicketDistributorBean
      </ejb-class>
      <messaging-type>javax.jms.MessageListener</messaging-type>
      <transaction-type>Bean</transaction-type> 
      <message-destination-type>
        javax.jms.Topic
      </message-destination-type>  
      <message-destination-link>
               Distributor
               </message-destination-link>
        ...
      <message-destination-ref>
          <message-destination-ref-name>
                jms/PartnerCompany
          </message-destination-ref-name>
          <message-destination-type>javax.jms.Topic</message-destination-type>
          <message-destination-usage>Produces</message-destination-usage>
          <message-destination-link>
               Partner
               </message-destination-link>
        </message-destination-ref>
        ...
    </message-driven>
     ...
  </enterprise-beans>
  <assembly-descriptor>
    ...
    <message-destination>
               <message-destination-name>Distributor</message-destination-name>
               </message-destination>
               <message-destination>
               <message-destination-name>Partner</message-destination-name>
               </message-destination>    
    ...  
  </assembly-descriptor>
</ejb-jar>

At deployment time, each of the <message-destination> elements are mapped to a real messaging destination in the target environment. In most cases, this will be a JMS topic or queue, but it could be a destination of some other type of messaging system.

The J2EE application server doesn’t have to route the messages through an actual destination. It can asynchronously send them from the sender to the receiver; in this case, from the TravelAgent EJB to the TicketDistributor MDB. However, if the application server handles message delivery itself, rather than going through a messaging provider, it must follow the semantics of the messaging system. For JMS, transactions, persistence, durability, security, and acknowledgments should be handled correctly whether the message is sent directly from one component to another, or via a JMS provider.

Although any enterprise bean can consume (receive) messages from a logical destination as well as produce (send) messages, only MDBs should consume messages. The reasons for this limitation were discussed earlier in this chapter (see “Entity and Session Beans Should Not Receive Messages”).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.78.237