| Oracle® Fusion Middleware Programming Message-Driven Beans for Oracle WebLogic Server 11g Release 1 (10.3.5) Part Number E15493-04 |
|
|
View PDF |
The following topics provide information on how to program and implement EJB 3.0 compliant MDBs:
To implement EJB 3.0 compliant MDBs, follow the steps described in "Overview of the EJB 3.0 Development Process" in Programming WebLogic Enterprise JavaBeans, Version 3.0 for Oracle WebLogic Server.
To program EJB 3.0 compliant MDBs, follow the steps described in "Programming the Bean File: Typical Steps" in Programming WebLogic Enterprise JavaBeans, Version 3.0 for Oracle WebLogic Server.
You must use the @javax.ejb.MessageDriven annotation to declare the EJB type as message-driven. You can specify the following optional attributes:
messageListenerInterface—Specifies the message listener interface, if you haven't explicitly implemented it or if the bean implements additional interfaces.
Note:
The bean class must implement, directly or indirectly, the message listener interface required by the messaging type that it supports or the methods of the message listener interface. In the case of JMS, this is thejavax.jms.MessageListener interface.activationConfig—Specifies an array of activation configuration properties that configure the bean in its operational environment.
Activation configuration properties are name-value pairs that are passed to the MDB container when an MDB is deployed. The properties can be declared in either an ejb-jar.xml deployment descriptor or by using the @ActivationConfigProperty annotation on the MDB bean class. An example using the @ActivationConfigProperty annotation is shown in Example 7-1. An example using the ejb-jar.xml deployment descriptor is shown in Example 7-2.
Example 7-1 Example @ActivationConfigProperty Code
. . .
@ActivationConfigProperties(
{
@ActivationConfigProperty(
name="connectionFactoryJndiName", value="JNDINameOfMDBSourceCF"
),
@ActivationConfigProperty(
name="initialContextFactory", value="weblogic.jndi.WLInitialContextFactory"
)
}
)
. . .
To set activation configuration properties in the ejb-jar.xml descriptor, use the activation-config-property element in the message-driven stanza, as shown in Example 7-2.
Example 7-2 Activation Configuration Properties Set in ejb-jar.xml
<message-driven>
. . .
<activation-config>
<activation-config-property>
<activation-config-property-name>destinationJNDIName</activation-config-property-name>
<activation-config-property-value>myQueue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
<activation-config-property>
</activation-config>
. . .
</message-driven>
<message-driven>
. . .
<activation-config>
<activation-config-property>
<activation-config-property-name>destinationJNDIName</activation-config-property-name>
<activation-config-property-value>myQueue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
<activation-config-property>
</activation-config>
. . .
</message-driven>
Because activation configuration properties can be set in an ejb.jar deployment descriptor or by using activationConfigProperty annotation properties, conflicts may result if the same name is used in both places. Conflicts may also result from using same-named properties from pre-3.0 versions of EJB or from proprietary WebLogic Server EJB annotations. Such conflicts are resolved following the following priority order, in sequence from high to low is
Properties set in the weblogic-ejb-jar.xml deployment descriptor
Proprietary WebLogic Server 10.0 (and later) annotations
activation-config-property properties set in the ejb-jar.xml deployment descriptor
activationConfigProperty annotation properties
For example, if the same property exists in the weblogic-ejb-jar.xml descriptor and the ejb-jar.xml descriptor, the one in weblogic-ejb-jar.xml has the higher priority and overrides the one in ejb-jar.xml value. Or, if the same property is set in both an ejb-jar.xml descriptor element and in an activationConfigProperty annotation, the descriptor element takes precedence and the annotation is ignored.
For more information about activation configuration properties, see "javax.ejb.ActivationConfigProperty" in Programming WebLogic Enterprise JavaBeans, Version 3.0 for Oracle WebLogic Server. Also see Table 11-1, which summarizes the activation configuration properties supported by WebLogic Server.
For detailed information on developing MDBs to support the messaging modes as described in MDBs and Messaging Models, see Programming and Configuring MDBs: Details.
Example 7-3 shows a WebLogic MDB that uses a subscription to a WebLogic JMS queue (from WebLogic Server 10.3.4 or later), transactionally processes the messages, and forwards the messages to a target destination.
The MDB connects using JMS connection factory MyCF to receive from queue MyQueue. It forwards the messages to MyTargetDest using a connection generated from connection factory MyTargetCF.
Resource reference pooling note: The MDB uses a resource reference to access MyTargetCF. The resource reference automatically enables JMS producer pooling, as described in "Enhanced Support for Using WebLogic JMS with EJBs and Servlets" in Programming JMS for Oracle WebLogic Server.
For a similar sample using topics instead of queues, see Example 10-1, "Sample MDB Using Distributed Topics".
Example 7-3 Sample MDB Using Distributed Queues
package test;
import javax.annotation.Resources;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.jms.*;
@MessageDriven(
name = "MyMDB",
activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "connectionFactoryJndiName",
propertyValue = "MyCF"), // External JNDI Name
@ActivationConfigProperty(propertyName = "destinationJndiName",
propertyValue = "MyQueue") // Ext. JNDI Name
}
)
@Resources ({
@Resource(name="targetCFRef",
mappedName="MyTargetCF", // External JNDI name
type=javax.jms.ConnectionFactory.class),
@Resource(name="targetDestRef",
mappedName="MyTargetDest", // External JNDI name
type=javax.jms.Destination.class)
})
public class MyMDB implements MessageListener {
// inject a reference to the MDB context
@Resource
private MessageDrivenContext mdctx;
// cache targetCF and targetDest for re-use (performance)
private ConnectionFactory targetCF;
private Destination targetDest;
@TransactionAttribute(value = TransactionAttributeType.REQUIRED)
public void onMessage(Message message) {
System.out.println("My MDB got message: " + message);
// Forward the message to "MyTargetDest" using "MyTargetCF"
Connection jmsConnection = null;
try {
if (targetCF == null)
targetCF = (javax.jms.ConnectionFactory)mdctx.lookup("targetCFRef");
if (targetDest == null)
targetDest = (javax.jms.Destination)mdctx.lookup("targetDestRef");
jmsConnection = targetCF.createConnection();
Session s = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer mp = s.createProducer(null);
mp.send(targetDest, message);
} catch (JMSException e) {
System.out.println("Forcing rollback due to exception " + e);
e.printStackTrace();
mdctx.setRollbackOnly();
} finally {
// Closing a connection automatically returns the connection and
// its session plus producer to the resource reference pool.
try { if (jmsConnection != null) jmsConnection.close(); }
catch (JMSException ignored) {};
}
// emulate 1 second of "think" time
try { Thread.currentThread().sleep(1000); }
catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // Restore the interrupted status
}
}
}