Oracle9iAS Containers for J2EE Enterprise JavaBeans Developer's Guide and Reference Release 2 (9.0.2) Part Number A95881-01 |
|
A Message-Driven Bean (MDB) is a JMS message listener that can reliably consume messages from a queue or a durable subscription. The advantage of using an MDB instead of a JMS message listener is because you can use the asynchronous nature of a JMS listener with the advantages that the EJB container does the following for you:
QueueReceiver
or TopicSubscriber
is created by the container.
QueueReceiver
or TopicSubscriber
and its factory at deployment time.
An MDB is an easy method for creating a JMS message listener.
This chapter discusses the tasks involved in creating an MDB in OC4J and demonstrates simple MDB development with a basic configuration and deployment. Download the MessageLogger
MDB example (messagelogger.ear
) from the OC4J sample code page on the OTN site.
To create an MDB, you perform the following steps:
javax.ejb.MessageDrivenBean
and javax.jms.MessageListener
interfaces, which includes the following:
Destination
type (queue or topic) in the OC4J JMS XML file--jms.xml
.
Destination
type to the MDB in the OC4J-specific deployment descriptor--orion-ejb-jar.xml
.
data-sources.xml
.
application.xml
file, create an EAR file, and install the EJB in OC4J.
The following sections demonstrates a simple MDB.
Most MDBs receive messages from a queue or a topic, then invoke an entity bean to process the request contained within the message.
The following example is a MessageLogger
MDB prints the message it receives, and invokes an entity bean, LogMessage
, to process the message.
As an MDB, it is responsible for the following:
javax.ejb.MessageDrivenBean
and javax.jms.MessageListener
interfaces
public
(not final
or abstract
)
setMessageDrivenContext
, ejbCreate
, onMessage
, and ejbRemove
.
package com.evermind.logger; import javax.ejb.*; import javax.jms.*; import javax.naming.*; import java.util.*; public class MessageLogger implements MessageDrivenBean { private MessageDrivenContext messageContext; public void ejbCreate() { /* no implementation is necessary for this MDB */ /* An MDB does not carry state for an individual client. However, you can retrieve state for use across many calls for multiple clients - state such as an entity bean reference or a database connection. If so, retrieve these within the ejbCreate and remove them in the ejbRemove method. */ } public void ejbRemove() { /* no implementation is necessary for this MDB*/ } public void onMessage(Message message) { /* The whole point for this message logger MDB is to receive and print messages. It is not complicated, but it shows how MDBs are set up to receive JMS messages from queues and topics. */ /*print the message*/ System.out.println("Received message: " + message); try { /* retrieve the initial context for the lookup */ Context ic = new InitialContext(); /*invoke the LogMessage entity bean to process the message*/ /* retrieve the home interface of the LogMessage bean*/ /* making sure to narrow the returned object to LogMessageHome*/ LogMessageHome home = (LogMessageHome)
javax.rmi.PortableRemoteObject.narrow(
ic.lookup("java:comp/env/logMessages"),
LogMessageHome.class); /* Retrieve the remote interface and instantiate the bean through the home.create method. The LogMessage create method requires three parameters: the time of the message, the subject of the message, and the actual message */ home.create(
new Date(message.getLongProperty("time")),
message.getStringProperty("subject"),
message.getStringProperty("message")); } catch(Exception e) { throw new EJBException(e); } } public void setMessageDrivenContext(MessageDrivenContext context) { /* As with all EJBs, you must set the context in order to be able to use it at another time within the MDB methods. */ this.messageContext = context; } }
You need to create both of the MDB deployment descriptors and the JMS Destination
configuration.
jms.xml
file.
ejb-jar.xml
) specifies whether a queue or a topic is used.
Destination
to associate with the MDB--The container understands which JMS Destination
to associate the MDB by the definition in the OC4J-specific deployment descriptor (orion-ejb-jar.xml
).
Within the EJB deployment descriptor, define the MDB name, class, JNDI reference, and JMS Destination
type (queue or topic) in the <message-driven>
element. If a queue is specified, you must also define whether it is durable or not.
The following is the deployment descriptor for the entire EJB application. It includes the deployment information for both the MessageLogger
MDB and the LogMessage
entity bean. The MessageLogger
MDB invokes the LogMessage
entity bean.
The MessageLogger
MDB is defined in the <message-driven>
element, as follows:
<ejb-name>
element
<ejb-class>
element
Destination
type is a Topic
that is specified in the <message-driven-destination><jms-destination-type>
element
<ejb-ref>
element
<?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd"> <ejb-jar> <enterprise-beans><message-driven>
<ejb-name>com.evermind.logger.MessageLogger</ejb-name>
<ejb-class>com.evermind.logger.MessageLogger</ejb-class>
<message-driven-destination>
<jms-destination-type>javax.jms.Topic</jms-destination-type>
</message-driven-destination>
<ejb-ref>
<ejb-ref-name>logMessages</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.evermind.logger.LogMessageHome</home>
<remote>com.evermind.logger.LogMessage</remote>
</ejb-ref>
</message-driven>
<entity> <ejb-name>com.evermind.logger.LogMessage</ejb-name> <home>com.evermind.logger.LogMessageHome</home> <remote>com.evermind.logger.LogMessage</remote> <ejb-class>com.evermind.logger.LogMessageEJB</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>java.lang.Long</prim-key-class> <reentrant>False</reentrant> <cmp-field><field-name>id</field-name></cmp-field> <cmp-field><field-name>time</field-name></cmp-field> <cmp-field><field-name>subject</field-name></cmp-field> <cmp-field><field-name>message</field-name></cmp-field> <cmp-field><field-name>category</field-name></cmp-field> <primkey-field>id</primkey-field> <ejb-ref> <ejb-ref-name>counter</ejb-ref-name> <ejb-ref-type>Entity</ejb-ref-type> <home>com.evermind.ejb.CounterHome</home> <remote>com.evermind.ejb.Counter</remote> </ejb-ref> </entity> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>com.evermind.logger.LogMessage</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Supports</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar>
Once you have configured the MDB and the JMS Destination
type, you must inform the container which JMS Destination
to associate with the MDB. You could have several topics and queues defined in your jms.xml
file. For information on defining these JMS Destination
types in jms.xml
, see the JMS chapter in Oracle9iAS Containers for J2EE Services Guide.
In order to identify the Destination
that is to be associated with the MDB, you map the Destination
location and connection factory to the MDB through the <message-driven-deployment>
element in the orion-ejb-jar.xml
file.
The following is the orion-ejb-jar.xml
deployment descriptor for the MessageLogger
example. It maps a JMS Topic
to the MessageLogger
MDB, providing the following:
<ejb-name>
in the EJB deployment descriptor, is specified in the name attribute.
Destination
, as defined in the jms.xml
file, is specified in the destination-location
attribute.
Destination
Connection
Factory
, as defined in the jms.xml
file, is specified in the connection-factory-location
attribute.
Once all of these are specified in the <message-driven-deployment>
element, the container knows how to map the MDB to the correct JMS Destination
.
<enterprise-beans><message-driven-deployment
name="com.evermind.logger.MessageLogger"
destination-location="jms/theTopic"
connection-factory-location="jms/theTopicConnectionFactory">
<ejb-ref-mapping name="logMessages" />
</message-driven-deployment>
... </enterprise-beans>
Configure the topic or queue that the client sends all messages to that are destined for the MDB. The name, location, and connection factory for either Destination
type must be specified.
The following JMS configuration specifies a topic (theTopic
) that is used by the MessageLogger
example:
<?xml version="1.0"?> <!DOCTYPE jms-server PUBLIC "Orion JMS server" "http://www.orionserver.com/dtds/ jms-server.dtd"> <jms-server port="9127"> <topic name="jms/theTopic" location="jms/theTopic"> <description>Employee topic</description> </topic> <topic-connection-factory location="jms/theTopicConnectionFactory"
username="admin" password="welcome" /> <!-- path to the log-file where JMS-events/errors are stored --> <log> <file path="../log/jms.log" /> </log> </jms-server>
If you use a database in your application, you should configure the DataSource
for that database. Full details for DataSource
configuration is provided in the Oracle9iAS Containers for J2EE Services Guide.
The database that the MessageLogger
example uses is configured in the data-sources.xml
file, as follows:
<data-source class="com.evermind.sql.DriverManagerDataSource" name="OracleDS" location="jdbc/OracleCoreDS" xa-location="jdbc/xa/OracleXADS" ejb-location="jdbc/OracleDS" connection-driver="oracle.jdbc.driver.OracleDriver" username="scott" password="tiger" url="jdbc:oracle:thin:@mysun:8852:orcl" inactivity-timeout="30" />
Archive your EJB into a JAR file. You deploy the MDB the same way as the session bean, which is detailed in "Prepare the EJB Application for Assembly" and "Deploy the Enterprise Application to OC4J".
The client sends a message to the MDB through a JMS Destination
. The MDB is associated with the JMS Destination
by the container. The following is a JNDI lookup of the JMS Destination
for the MessageLogger
MDB.
Context ic - new InitialContext(); Queue msgQueue = (javax.jms.Queue) ic.lookup("java:comp/env/jms/msgQueue");
For example, the following JSP sends a message to the MessageLogger MDB Topic:
<%@ page import="javax.jms.*, javax.naming.*, java.util.*" %> <% TopicConnectionFactory connectionFactory = (TopicConnectionFactory)new InitialContext().lookup ("java:comp/env/jms/theTopicConnectionFactory"); TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); TopicSession topicSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); topicSession.start(); Topic topic = (Topic)new InitialContext().lookup("java:comp/env/jms/theTopic"); TopicPublisher publisher = topicSession.createPublisher(topic); Message message = topicSession.createMessage(); message.setJMSType("logMessage"); message.setLongProperty("time", System.currentTimeMillis()); message.setStringProperty("subject", request.getParameter("subject")); message.setStringProperty("message", request.getParameter("message")); publisher.publish(message); publisher.close(); topicSession.close(); connection.close(); %> Message sent!
|
Copyright © 2002 Oracle Corporation. All Rights Reserved. |
|