Message-Driven Beans

Consider an EJB scenario. EJBs are designed to be used in a synchronous environment. To include the facility of asynchronous messaging in the enterprise bean scenario, message-driven beans were introduced in the EJB2.0 specification. The functions of message-driven beans are a combination of the EJB and JMS functionalities. The obvious question that would arise is, what's so special about message-driven beans? Why shouldn't you use a pure JMS application, in case you need an asynchronous functionality? Well, to develop a sturdy, full-scale JMS application, you have to handle transactions, security, scalability, fault tolerance, concurrent message processing, and object life cycle. This is a pretty daunting task. However, all these are inbuilt into the EJB server, which makes your development much simpler and allows you to concentrate on your business functionality rather than the technology.

As is clear from the previous paragraph, message-driven beans are managed by the vendor server's EJB container. A message-driven bean is always a message recipient. Similarly, in the WebLogic Server's sender-recipient model, a message-driven bean is analogous to a message recipient.

The WebLogic Server creates listeners to these queues at deployment time. Because these message-driven beans are container managed, the WebLogic Server automatically manages the removal and creation of message-driven beans so as to process other incoming messages.

Using the onMessage() method in your message-driven bean, you can obtain the obtain messages from a destination. This is done with the support of deployment descriptor files. The details of this are explained a little further in the life cycle description of a message-driven bean. You do not write a remote or home interface for message-driven beans because message-driven beans follow the asynchronous model, and both these interfaces are strictly synchronous by definition.

A message-driven bean connects to the JMS server using the "run-as" principle. The run-as element, set in the deployment descriptor file ejb-jar.xml, is used by the bean as an identity to interact with the JMS. The default value for this element is guest. The destination type (queue or topic) is also specified in the deployment descriptor in the destination-type element.

In message-driven beans, permission to receive must be set in order to connect to either a remote destination or a destination in the same domain. To set the "receive" permission, an ACL (access control list) must be used. As explained in the earlier days, an ACL is a list of users or a group that has permission to access specific resources. The "receive" permission has to be granted to the ACL in the domain in which the message-driven bean is executed.

Although the functionality of message-driven beans makes them look very similar to the JMS destination's message consumer, there are many differences between the two:

  • Because the WebLogic Server manages a message-driven bean totally, multiple instances of the message-driven bean created by the WebLogic Server enable asynchronous processing of multiple transaction requests.

  • Message-driven EJBs have some very convenient security features and automatic transaction management.

  • Message-driven beans are not tied to any other API. JMS consumers, on the other hand, are tied to session pools.

  • Message-driven beans are allocated server space only on server startup, hence they judiciously utilize the WebLogic Server space. JMS consumers, on the other hand, are like normal Java classes, whose instances can be obtained as and when required by using the corresponding session JMS API.

  • A message-driven bean cannot be associated with more than one queue or topic. A receiving application in JMS, however, can be associated with more than one destination.

  • Unlike all other EJBs, a message-driven bean does not have remote and home interfaces and cannot be accessed directly. Only the WebLogic Server has access to the message-driven bean, and hence only the server can create a message-driven bean and pass the JMS messages to it.

Life Cycle of a Message-Driven Bean

When a message reaches the destination queue or topic, the WebLogic Server first obtains a new bean instance. The max-beans-in-free-pool parameter is used to obtain a new bean instance. If no instance is available because the maxbeans element value is equal to the max-beans-in-free-pool value (that is, because all the free beans in the pool have been taken up), the WebLogic Server waits until an instance is freed. If it gets a bean instance immediately, that instance is used.

If the max-beans-in-free-pool element value is not equal to the maxbeans element value and no instances of the bean are available in the free pool, the WebLogic Server creates a new instance by calling the ejbCreate() method.

The MessageDrivenContext of the bean is then set using the setMessageDrivenContext() method, associating this instance with a container context. The bean can use the getRollBackOnly(), setRollBackOnly(), and getUserTransaction() methods of the container context. The former two can be used only for container-managed transactions, while the last can be used for bean-managed transactions. The getCallerPrincipal() method and isCallerInRole() method should not be called by an instance of a message-driven bean.

When the destination associated with the bean receives a message, the WebLogic Server calls the bean's onMessage() method and executes the business functionality implemented in this method.

Example Message-Driven Bean

Listing 15.5 shows a sample code snippet for a message-driven bean called SampleMessageDrivenBean.

Listing 15.5 SampleMessageDrivenBean
 public class SampleMessageDrivenBean implements MessageDrivenBean,         MessageListener{    public void ejbCreate(){         System.out.println("EJB create called");    }    public void ejbRemove(){         System.out.println("EJB remove called");    }        public void onMessage(Message inMessage) {                     TextMessage msg = null;                      try {         if (inMessage instanceof TextMessage) {             msg = (TextMessage) inMessage;             System.out.println                 ("MESSAGE BEAN: Message received: "                 + msg.getText());         } else {             System.out.println                 ("Message of wrong type: "                 + inMessage.getClass().getName());         }       } catch (JMSException e) {         e.printStackTrace();         mdc.setRollbackOnly();       } catch (Throwable te) {         te.printStackTrace();    } } 

Listing 15.6 contains a sample snippet of the corresponding deployment descriptor file, ejb-jar.xml.

Listing 15.6 ejb-jar.xml
 <assembly-descriptor>        <container-transaction>               <method>                      <ejb-name>SampleMessageDrivenBean</ejb-name>                      <method-name>*</method-name>               </method>        <trans-attribute>NotSupported</trans-attribute>        </container-transaction> </assembly-descriptor> 

Listing 15.7 shows a sample snippet of the corresponding entries in the weblogic-ejb-jar.xml file.

Listing 15.7 weblogic-ejb-jar.xml
 <message-driven-descriptor>     <destination-jndi-name>...</destination-jndi-name>     <provider-url>WeblogicURL:Port</provider-url> </message-driven-descriptor> ... <stateless-session-descriptor>        <pool>               <max-beans-in-free-pool>500</max-beans-in-free-pool>               <initial-beans-in-free-pool>250</initial-beans-in-free-pool>        </pool> </stateless-session-descriptor> 

Message-Driven Bean Tips

Keep the following points in mind while developing your message-driven bean:

  • A message-driven bean should implement the javax.ejb.MessageDrivenBean and javax.jms.MessageListener interfaces.

  • Your bean class does not have a remote or home interface. Your bean implementation class will also implement the methods ejbCreate(), ejbRemove(), and onMessage().

  • Because you are not creating the message-driven bean, the ejbCreate() method must not have any parameters passed to it. Also, this constructor of message-driven beans must not be declared as abstract, final, or static. The return type must be void. This method need not compulsorily use a throws clause. However, if it does, it should throw an application exception or a RemoteException(). The container uses this method to create an instance of the bean on the free pool.

  • The ejbRemove() method is called by the container to remove instances of message-driven beans from the free pool. As in the ejbCreate() method, the ejbRemove() method cannot be declared as static or final, nor can it accept any parameters. Also, it cannot throw any application exceptions or a RemoteException().

  • The container calls onMessage() method when a message is received on the destination. You can put in business logic related to the message obtained from the destination in this method. This method takes a single parameter of javax.jms.Message type. Also, this method must not be declared as final or static. An onMessage() method also cannot throw any application exceptions or a RemoteException().

  • The message-driven bean class cannot define a finalize method, because the creation and destruction of beans is not in the jurisdiction of the bean provider.

  • A message-driven bean can be deployed when the WebLogic Server starts up or on a running WebLogic Server. Deployment at startup can be achieved by placing the deployable EAR or JAR file into the Web application directory. Deployment on a running server requires you to place the deployable archive file in the applications directory of your domain or to deploy the bean through the Administration Console.

  • For message-driven beans using bean-managed transactions, the receipt of a message that results in the container's calling the onMessage() method of the bean is always outside the scope of the transaction. In the case of a container-managed message-driven bean transaction, however, the WebLogic Server includes the receipt of the message as a part of the transaction only if the element transaction type is set to Required in the deployment descriptor ejb-jar.xml.

  • In the case of a container-managed message-driven bean, the message is automatically acknowledged when the transaction is committed. In bean-managed message-driven beans, the semantics of the acknowledgment can be configured in the acknowledge-mode element of the deployment descriptor ejb-jar.xml.



Sams Teach Yourself BEA WebLogic Server 7. 0 in 21 Days
Sams Teach Yourself BEA WebLogic Server 7.0 in 21 Days
ISBN: 0672324334
EAN: 2147483647
Year: 2002
Pages: 339

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