6.4 Using JMS and Connectors for Communication

We have seen how message-driven beans can be used to implement incoming communication from an enterprise application to EJB components. We now illustrate two approaches for outgoing communication from EJB applications to enterprise information systems. Both approaches focus on the communication between enterprise bean components and enterprise information systems. One approach emphasizes the use of JMS; the other uses the J2EE Connector technology. Application server products that support the J2EE (1.3 or 1.4) platform provide both JMS and J2EE Connector technologies.

6.4.1 Using JMS to Communicate with Messaging Systems

JMS provides APIs that allow an enterprise bean component to send and receive messages that flow through enterprise messaging systems. We have already seen how a message-driven bean, such as PayrollMDB can be used to receive JMS messages from a messaging system. Here, we explain how an enterprise bean sends JMS messages to an enterprise messaging system message queue.

Recall from Chapter 4 the communication requirements for the Benefits Enrollment application, especially the need to keep Star Enterprise's payroll database updated with payroll changes. In a loosely coupled model, the Benefits Enrollment application needs to send payroll-update notifications to the PayrollQueue reliable queue in Star Enterprise. To accomplish this, the Benefits Enrollment application uses a DeductionUpdateBeanJMS command bean. The EnrollmentEJB stateful session bean component of the application invokes this command bean. Code Example 6.3 shows the complete code for the DeductionUpdateBeanJMS command bean:

Code Example 6.3 DeductionUpdateBeanJMS Class
 public class DeductionUpdateBeanJMS implements            DeductionUpdateBean {     private Queue payrollQueue;     private QueueConnectionFactory factory;     private int emplNumber;     private double deduction;     public DeductionUpdateBeanJMS() {         try {             InitialContext ictx = new InitialContext();             payrollQueue = (Queue)ictx.lookup(                    "java:comp/env/jms/PayrollQueue");             factory = (QueueConnectionFactory)ictx.lookup(                    "java:comp/env/jms/QueueConnectionFactory");         } catch ( Exception ex ) {             throw new EJBException("Unable to get Payroll bean", ex);         }     }     public void setBenefitsDeduction(int emplNumber,                double deduction) {         this.emplNumber = emplNumber;         this.deduction = deduction;     }     public void execute() {         QueueConnection connection=null;         try {             // Create a connection             connection = factory.createQueueConnection();             // Create a transactional session             QueueSession session =                    connection.createQueueSession(true, 0);             // Create a sender             QueueSender sender = session.createSender(payrollQueue);             // Send the message             MapMessage message = session.createMapMessage();             message.setInt("Employee", emplNumber);             message.setDouble("PayrollDeduction", deduction);             sender.send(message);         } catch (Exception ex) {             throw new EJBException(ex);         } finally {             try {                 if( connection != null ) {                     connection.close();                 }             } catch(Exception e) {}         }     }     public void release() {     payrollQueue = null;         factory = null;     } } 

Note that the DeductionUpdateBeanJMS class implements the DeductionUpdateBean interface. EnrollmentEJB uses the DeductionUpdateBean command bean interface. Chapter 4 shows how EnrollmentEJB uses this command bean; DeductionUpdateBean directly invokes the Payroll session bean, thus providing a tightly coupled interaction between the Benefits Enrollment and payroll applications.

Here, we show how to accomplish the same interaction in a loosely coupled fashion. The DeductionUpdateBeanJMS class uses JMS to communicate with the PayrollMDB bean through PayrollQueue. Using the message queue provides a loosely coupled interaction between the Benefits Enrollment and payroll applications.

To initiate a connection to PayrollQueue, the command bean needs two JMS objects: one representing the JMS queue and the other representing a connection factory to a queue. In its constructor, DeductionUpdateBeanJMS uses JNDI to look up the JMS PayrollQueue queue object and the JMS QueueConnectionFactory object.

PayrollQueue and QueueConnectionFactory need to be declared in the JNDI environment of the sender bean, which in this case is EnrollmentEJB. This is done by including two reference elements in EnrollmentEJB's XML deployment descriptor. The PayrollQueue reference is declared using a message-destination-ref element. This element includes the JNDI name at which the bean looks up PayrollQueue and the PayrollQueue's expected Java type in this case, javax.jms.Queue. This element also declares that the message destination is used for sending or consuming messages in this example, for sending messages. The QueueConnectionFactory is declared using a resource-ref element, which again includes the JNDI name and expected Java type (javax.jms.QueueConnectionFactory).

The setBenefitsDeduction method stores the employee number and payroll-deduction amount. These two fields are later inserted into the JMS message before the message is sent.

DeductionUpdateBeanJMS's execute method does the actual work of connecting to the queue and sending the JMS message. This method first obtains a QueueConnection object from QueueConnectionFactory and then creates a QueueSession object, which represents a single-threaded interaction between the command bean and the JMS provider. Next, execute creates a QueueSender object, using the PayrollQueue queue, and then instantiates a MapMessage object for the message to be sent, filling it with the employee number and payroll-deduction information. Finally, the method uses the QueueSender object to send the message to PayrollQueue.

It is important to note that the message send operation is transactional in nature. This means that the message is not sent if the transaction in which the command bean is called should be rolled back because of an error. Making the message send operation transactional ensures that the payroll deduction is applied only if an employee's benefits enrollment procedure completes successfully.

In addition, the PayrollQueue object enforces security access control to ensure that only authorized users can send payroll-deduction messages to it. The EJB container and the JMS provider perform the security-related interactions with the PayrollQueue object at the time the JMS connection to PayrollQueue is created.

6.4.2 Setting Up Messaging Flow within Applications

Sometimes an EJB application contains message senders and message receivers, and it is necessary to link them together. This can be done using XML deployment descriptor elements in the application. This facility is necessary when an application requires asynchronous message-based communication between its parts. For example, if the EnrollmentEJB session bean and the PayrollMDB message-driven bean were packaged in the same J2EE application, we would need to make sure that messages sent by EnrollmentEJB were routed to PayrollMDB through PayrollQueue.

Senders and receivers can be linked using a destination object, which is a queue or a topic for JMS. First, declare this destination object using the message-destination deployment descriptor element, which contains the name of the destination (for example, PayrollQueue). Next, link the message destination reference from the sending EJB component to this message destination using a message-destination-link element in the sending EJB component's deployment descriptor. Finally, using a similar link element, link the receiving message-driven bean to the destination as a consumer of messages. This completes the routing of messages between sender and receiver in the same application.

6.4.3 Using Connectors to Communicate with Enterprise Information Systems

Enterprise beans can use the J2EE Connector technology to communicate to legacy applications. Here, we illustrate how communication using a connector, or resource adapter, might take place between an enterprise bean and a mainframe application.

In this scenario, Star Enterprise's Payroll System is a mainframe application consisting of a collection of CICS transaction processing (TP) programs. Prior to deploying the Benefits Enrollment application, Star Enterprise needed to give its nonmainframe applications access to payroll information. To accomplish this, Star Enterprise purchased a mainframe connectivity product from vendor Aardvark. With its product, Aardvark included a resource adapter enabling communication with the mainframe system. Because it complies with the requirements of the J2EE Connector architecture, the resource adapter can be plugged into any J2EE-compliant application server.

After it deployed Aardvark's mainframe connectivity product into its Payroll application server, Star Enterprise developed an implementation of the PayrollEJB stateless session bean that uses Aardvark's resource adapter to access the Payroll mainframe system. The resource adapter has two functions:

  1. It integrates with the EJB container, using the system-level contracts defined in the Connector architecture.

  2. It communicates with the Payroll System CICS TP programs on the mainframe.

Refer to the section Other Sources of Information on page xviii for more information on the J2EE Connector architecture. For the source code for the PayrollBean class, see PayrollBean Implementation Class Using Connectors, on page 410.

The implementation of the setBenefitsDeduction method in PayrollBean uses the Common Client Interface (CCI) APIs defined in the J2EE Connector architecture. The CCI APIs provide a standard way for enterprise beans and other J2EE components to access enterprise information systems. The setBenefitsDeduction method begins with setup work to establish a connection to the underlying database and to define the parameters for its execution. The method first obtains a Connection object to use for its communication with the mainframe application. The method uses this object to create an Interaction object, which it will subsequently use for a single interaction with the mainframe application.

The setBenefitsDeduction method next creates an InteractionSpecImpl object. The method passes to the InteractionSpecImpl object the name of the target TP mainframe program and the direction of the interaction. In our example, the SYNC_SEND verb indicates that arguments pass only to the mainframe. For the last setup step, the setBenefitsDeduction method creates a MappedRecord object and uses the put methods to set the values of input arguments to be sent to the target mainframe program.

Finally, setup is completed and the setBenefitsDeduction method invokes the execute method on the Interaction object. The execute method causes the resource adapter to send the input arguments to the SETPAYROLL_DEDUCTION program on the mainframe. "Under the covers," the EJB container and the mainframe resource adapter propagate the transaction from the PayrollBean instance to the mainframe TP program. The developer of PayrollBean did not have to write any transaction-related code to enable this propagation of the transaction.

The preceeding example provides a brief introduction to using the J2EE Connector technology for accessing enterprise information systems from an enterprise bean. For a more detailed discussion, refer to the book J2EE™ Connector Architecture and Enterprise Application Integration, by Rahul Sharma, Beth Stearns, and Tony Ng (Addison-Wesley, 2001).



Applying Enterprise Javabeans
Applying Enterprise JavaBeans(TM): Component-Based Development for the J2EE(TM) Platform
ISBN: 0201702673
EAN: 2147483647
Year: 2003
Pages: 110

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net