Chapter 4. Message-Driven Beans 4.1. Message-Driven Beans Message-driven Beans (MDBs) provide an event driven model for application development. The methods of MDBs are not injected into or invoked from client code but are triggered by the receipt of messages from a messaging service such as a Jakarta Messaging server. The Jakarta EE specification requires that Jakarta Messaging is supported but other messaging systems can be supported as well. MDBs are a special kind of stateless session beans. They implement a method called onMessage(Message message) . This method is triggered when a Jakarta Messaging destination on which the MDB is listening receives a message. That is, MDBs are triggered by the receipt of messages from a Jakarta Messaging provider, unlike the stateless session beans where methods are usually called by Jakarta Enterprise Beans clients. MDB processes messages asynchronously. By default each MDB can have up to 16 sessions, where each session processes a message. There are no message order guarantees. In order to achieve message ordering, it is necessary to limit the session pool for the MDB to 1 . Example: Management CLI Commands to Set Session Pool to 1 : 4.2. Message-Driven Beans Controlled Delivery JBoss EAP provides three attributes that control active reception of messages on a specific MDB: Delivery Active Delivery Groups Clustered Singleton MDBs 4.2.1. Delivery Active The delivery active configuration of the message-driven beans (MDB) indicates whether the MDB is receiving messages or not. If an MDB is not receiving messages, then the messages will be saved in the queue or topic according to the topic or queue rules. You can configure the active attribute of the delivery-group using XML or annotations, and you can change its value after deployment using the management CLI. By default, the active attribute is activated and delivery of messages occurs as soon as the MDB is deployed. Configuring Delivery Active in the jboss-ejb3.xml File In the jboss-ejb3.xml file, set the value of active to false to indicate that the MDB will not be receiving messages as soon as it is deployed: <?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="urn:delivery-active:1.1" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <d:delivery> <ejb-name>HelloWorldQueueMDB</ejb-name> <d:active>false</d:active> </d:delivery> </assembly-descriptor> </jboss:ejb-jar> If you want to apply the active value to all MDBs in your application, you can use a wildcard * in place of the ejb-name . Configuring Delivery Active Using Annotations You can also use the org.jboss.ejb3.annotation.DeliveryActive annotation. For example: @MessageDriven(name = "HelloWorldMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/HELLOWORLDMDBQueue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) @DeliveryActive(false) public class HelloWorldMDB implements MessageListener { public void onMessage(Message rcvMessage) { // ... } } If you use Maven to build your project, make sure you add the following dependency to the pom.xml file of your project: <dependency> <groupId>org.jboss.ejb3</groupId> <artifactId>jboss-ejb3-ext-api</artifactId> <version>2.2.0.Final</version> </dependency> Configuring Delivery Active Using the Management CLI You can configure the active attribute of the delivery-group after deployment using the management CLI. These management operations dynamically change the value of the active attribute, enabling or disabling delivery for the MDB. This method of changing the delivery active value does not persist if you restart the server. At runtime, connect to the instance you want to manage, then enter the path of the MDB for which you want to manage the delivery. For example: Navigate to the instance you want to manage: To stop the delivery to the MDB: To start the delivery to the MDB: View the MDB Delivery Active Status You can view the current delivery active status of any MDB using the management console: Select the Runtime tab and select the appropriate server. Click EJB and select the child resource, for example HelloWorldQueueMDB . Result You see the status as Delivery Active: true or Delivery Active: false . 4.2.2. Delivery Groups Delivery groups provide a way to manage the delivery-active state for a group of MDBs. An MDB can belong to one or more delivery groups. Message delivery is enabled only when all the delivery groups that an MDB belongs to are active. For a clustered singleton MDB, message delivery is active only in the singleton node of the cluster and only if all the delivery groups associated with the MDB are active. You can add a delivery group to the ejb3 subsystem using either the XML configuration or the management CLI. Configuring Delivery Group in the jboss-ejb3.xml File <delivery> <ejb-name>MdbName<ejb-name> <delivery-group>passive</delivery-group> </delivery> On the server side, delivery-groups can be enabled by having their active attribute set to true , or disabled by having their active attribute set to false , as shown in the example below: <delivery-groups> <delivery-group name="group" active="true"/> </delivery-groups> Configuring Delivery Group Using the Management CLI The state of delivery-groups can be updated using the management CLI. For example: When you set the delivery active in the jboss-ejb3.xml file or using the annotation, it persists on server restart. However, when you use the management CLI to stop or start the delivery, it does not persist on server restart. Configuring Multiple Delivery Groups Using Annotations You can use the org.jboss.ejb3.annotation.DeliveryGroup annotation on each MDB class belonging to a group: @MessageDriven(name = "HelloWorldQueueMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/HELLOWORLDMDBQueue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) @DeliveryGroup("delivery-group-1") @DeliveryGroup("delivery-group-2") public class HelloWorldQueueMDB implements MessageListener { ... } 4.2.3. Clustered Singleton MDBs When an MDB is identified as a clustered singleton and is deployed in a cluster, only one node is active. This node can consume messages serially. When the server node fails, the active node from the clustered singleton MDBs starts consuming the messages. Identify an MDB as a Clustered Singleton You can use one of the following procedures to identify an MDB as a clustered singleton. Use the clustered-singleton XML element as shown in the example below: <?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="urn:clustering:1.1" xmlns:d="urn:delivery-active:1.2" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <c:clustering> <ejb-name>HelloWorldQueueMDB</ejb-name> <c:clustered-singleton>true</c:clustered-singleton> </c:clustering> <d:delivery> <ejb-name>*</ejb-name> <d:group>delivery-group-1</d:group> <d:group>delivery-group-2</d:group> </d:delivery> </assembly-descriptor> </jboss:ejb-jar> In your MDB class, use the @org.jboss.ejb3.annotation.ClusteredSingleton . This procedure requires no extra configuration at the server. You need to run the service in a clustered environment. Note You have to activate the delivery-group in the entire cluster, specifically, in all nodes of the cluster, because you do not know which node of the cluster is chosen to be the singleton master . If the server chooses a node to be singleton master , and that node does not have the required delivery-group activated, no node in the cluster receives the messages. The messaging-clustering-singleton quickstart, which ships with JBoss EAP, demonstrates the use of clustering with integrated Apache ActiveMQ Artemis. It uses the same source code as the helloworld-mdb quickstart, with a difference only in the configuration to run it as a clustered singleton. There are two Jakarta Messaging resources contained in this quickstart: A queue named HELLOWORLDMDBQueue bound in the Java Naming and Directory Interface as java:/queue/HELLOWORLDMDBQueue A topic named HELLOWORLDMDBTopic bound in the Java Naming and Directory Interface as java:/topic/HELLOWORLDMDBTopic Both contain a singleton configuration as specified in the jboss-ejb3.xml file: <c:clustering> <ejb-name>*</ejb-name> <c:clustered-singleton>true</c:clustered-singleton> </c:clustering> The wildcard asterisk * in the <ejb-name> element indicates that all the MDBs contained in the application will be clustered singleton. As a result, only one node in the cluster will have those MDBs active at a specific time. If this active node shuts down, another node in the cluster will become the active node with the MDBs, which then becomes the singleton provider. You can also find a configuration for the delivery group in the jboss-ejb3.xml file: <d:delivery> <ejb-name>HelloWorldTopicMDB</ejb-name> <d:group>my-mdb-delivery-group</d:group> </d:delivery> In this case, only one of the MDBs, HelloWorldTopicMDB , is associated with a delivery group. All the delivery groups used by an MDB must be configured in the ejb3 subsystem configuration. The delivery group can be enabled or disabled. If the delivery group is disabled in a cluster node, all the MDBs belonging to that delivery group become inactive in the respective cluster node. When using the delivery groups in a non-clustered environment, the MDB is active whenever the delivery group is enabled. If a delivery group is used in conjunction with the singleton provider, the MDB can be active in the singleton provider node only if that node has the delivery group enabled. Otherwise, the MDB will be inactive in that node, and all the other nodes of the cluster. See the README.html file included with this quickstart for detailed instructions about how to configure the server for messaging clustering and to review the code examples. For information on how to download and use the JBoss EAP quickstarts, see the Using the Quickstart Examples section in the JBoss EAP Getting Started Guide . 4.3. Create a Jakarta Messaging-based Message-Driven Bean in Red Hat CodeReady Studio This procedure shows how to add a Jakarta Messaging-based message-driven bean to a project in Red Hat CodeReady Studio. This procedure creates a Jakarta Enterprise Beans 3.x message-driven bean that uses annotations. Prerequisites You must have an existing project open in Red Hat CodeReady Studio. You must know the name and type of the Jakarta Messaging destination that the bean will be listening to. Support for Jakarta Messaging must be enabled in the JBoss EAP configuration to which this bean will be deployed. Add a Jakarta Messaging-based Message-driven Bean in Red Hat CodeReady Studio Open the Create EJB 3.x Message-Driven Bean wizard. Go to File New Other . Select EJB/Message-Driven Bean (EJB 3.x) and click the button. Figure 4.1. Create EJB 3.x Message-Driven Bean Wizard Specify class file destination details. There are three sets of details to specify for the bean class here: project, Java class, and message destination. Project: If multiple projects exist in the workspace, ensure that the correct one is selected in the Project menu. The folder where the source file for the new bean will be created is ejbModule under the selected project's directory. Only change this if you have a specific requirement. Java Class: The required fields are: Java package and Class name . It is not necessary to supply a superclass unless the business logic of your application requires it. Message Destination: These are the details you must supply for a Jakarta Messaging-based message-driven bean: Destination name , which is the queue or topic name that contains the messages that the bean will respond to. By default the JMS checkbox is selected. Do not change this. Set Destination type to Queue or Topic as required. Click the button. Enter message-driven bean specific information. The default values here are suitable for a Jakarta Messaging-based message-driven bean using container-managed transactions. Change the Transaction type to Bean if the Bean will use Bean-managed transactions. Change the Bean name if a different bean name than the class name is required. The JMS Message Listener interface will already be listed. You do not need to add or remove any interfaces unless they are specific to your application's business logic. Leave the checkboxes for creating method stubs selected. Click the Finish button. Result The message-driven bean is created with stub methods for the default constructor and the onMessage() method. A Red Hat CodeReady Studio editor window opens with the corresponding file. 4.4. Specifying a Resource Adapter in jboss-ejb3.xml for an MDB In the jboss-ejb3.xml deployment descriptor you can specify a resource adapter for an MDB to use. To specify a resource adapter in jboss-ejb3.xml for an MDB, use the following example. Example: jboss-ejb3.xml Configuration for an MDB Resource Adapter <jboss xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:jee="http://java.sun.com/xml/ns/javaee" xmlns:mdb="urn:resource-adapter-binding"> <jee:assembly-descriptor> <mdb:resource-adapter-binding> <jee:ejb-name>MyMDB</jee:ejb-name> <mdb:resource-adapter-name>MyResourceAdapter.rar</mdb:resource-adapter-name> </mdb:resource-adapter-binding> </jee:assembly-descriptor> </jboss> For a resource adapter located in an EAR, you must use the following syntax for <mdb:resource-adapter-name> : For a resource adapter that is in another EAR: <mdb:resource-adapter-name>OtherDeployment.ear#MyResourceAdapter.rar</mdb:resource-adapter-name> For a resource adapter that is in the same EAR as the MDB, you can omit the EAR name: <mdb:resource-adapter-name>#MyResourceAdapter.rar</mdb:resource-adapter-name> 4.5. Using Resource Definition Annotations in MDBs Deployed to a Cluster If you use the @JMSConnectionFactoryDefinition and @JMSDestinationDefinition annotations to create a connection factory and destination for message-driven beans, be aware that the objects are only created on the server where the MDB is deployed. They are not created on all nodes in a cluster unless the MDB is also deployed to all nodes in the cluster. Because objects configured by these annotations are only created on the server where the MDB is deployed, this affects remote Jakarta Connectors topologies where an MDB reads messages from a remote server and then sends them to a remote server. 4.6. Enable Jakarta Enterprise Beans and MDB Property Substitution in an Application Red Hat JBoss Enterprise Application Platform allows you to enable property substitution in Jakarta Enterprise Beans and MDBs using the @ActivationConfigProperty and @Resource annotations. Property substitution requires the following configuration and code changes. You must enable property substitution in the JBoss EAP server configuration file. You must define the system properties in the server configuration file or pass them as arguments when you start the JBoss EAP server. You must modify the application code to use the substitution variables. The following examples demonstrate how to modify the helloworld-mdb quickstart that ships with JBoss EAP to use property substitution. See the helloworld-mdb-propertysubstitution quickstart for the completed working example. 4.6.1. Configure the Server to Enable Property Substitution To enable property substitution in the JBoss EAP server, you must set the annotation-property-replacement attribute in the ee subsystem of the server configuration to true . Back up the server configuration file. The helloworld-mdb-propertysubstitution quickstart example requires the full profile for a standalone server, so this is the EAP_HOME /standalone/configuration/standalone-full.xml file. If you are running your server in a managed domain, this is the EAP_HOME /domain/configuration/domain.xml file. Navigate to the JBoss EAP install directory and start the server with the full profile. Note For Windows Server, use the EAP_HOME \bin\standalone.bat script. Launch the management CLI. Note For Windows Server, use the EAP_HOME \bin\jboss-cli.bat script. Type the following command to enable annotation property substitution. You should see the following result. Review the changes to the JBoss EAP server configuration file. The ee subsystem should now contain the following XML. Example ee Subsystem Configuration <subsystem xmlns="urn:jboss:domain:ee:4.0"> ... <annotation-property-replacement>true</annotation-property-replacement> ... </subsystem> 4.6.2. Define the System Properties You can specify the system properties in the server configuration file or you can pass them as command line arguments when you start the JBoss EAP server. System properties defined in the server configuration file take precedence over those passed on the command line when you start the server. 4.6.2.1. Define the System Properties in the Server Configuration Launch the management CLI. Use the following command syntax to configure a system property in the JBoss EAP server. Syntax to Add a System Property The following system properties are configured for the helloworld-mdb-propertysubstitution quickstart. Example Commands to Add System Properties Review the changes to the JBoss EAP server configuration file. The following system properties should now appear in the after the <extensions> . Example System Properties Configuration <system-properties> <property name="property.helloworldmdb.queue" value="java:/queue/HELLOWORLDMDBPropQueue"/> <property name="property.helloworldmdb.topic" value="java:/topic/HELLOWORLDMDBPropTopic"/> <property name="property.connection.factory" value="java:/ConnectionFactory"/> </system-properties> 4.6.2.2. Pass the System Properties as Arguments on Server Start If you prefer, you can instead pass the arguments on the command line when you start the JBoss EAP server in the form of -D PROPERTY_NAME = PROPERTY_VALUE . The following is an example of how to pass the arguments for the system properties defined in the section. Example Server Start Command Passing System Properties 4.6.3. Modify the Application Code to Use the System Property Substitutions Replace the hard-coded @ActivationConfigProperty and @Resource annotation values with substitutions for the newly defined system properties. The following are examples of how to change the helloworld-mdb quickstart to use the newly defined system property substitutions. Change the @ActivationConfigProperty destination property value in the HelloWorldQueueMDB class to use the substitution for the system property. The @MessageDriven annotation should now look like this: HelloWorldQueueMDB Code Example @MessageDriven(name = "HelloWorldQueueMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "USD{property.helloworldmdb.queue}"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) Change the @ActivationConfigProperty destination property value in the HelloWorldTopicMDB class to use the substitution for the system property. The @MessageDriven annotation should now look like this: HelloWorldTopicMDB Code Example @MessageDriven(name = "HelloWorldQTopicMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "USD{property.helloworldmdb.topic}"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) Change the @Resource annotations in the HelloWorldMDBServletClient class to use the system property substitutions. The code should now look like this: HelloWorldMDBServletClient Code Example /** * Definition of the two Jakarta Messaging Service destinations used by the quickstart * (one queue and one topic). */ @JMSDestinationDefinitions( value = { @JMSDestinationDefinition( name = "java:/USD{property.helloworldmdb.queue}", interfaceName = "javax.jms.Queue", destinationName = "HelloWorldMDBQueue" ), @JMSDestinationDefinition( name = "java:/USD{property.helloworldmdb.topic}", interfaceName = "javax.jms.Topic", destinationName = "HelloWorldMDBTopic" ) }) /** * <p> * A simple servlet 3 as client that sends several messages to a queue or a topic. * </p> * * <p> * The servlet is registered and mapped to /HelloWorldMDBServletClient using the {@linkplain WebServlet * @HttpServlet}. * </p> * * @author Serge Pagop (spagop@redhat.com) * */ @WebServlet("/HelloWorldMDBServletClient") public class HelloWorldMDBServletClient extends HttpServlet { private static final long serialVersionUID = -8314035702649252239L; private static final int MSG_COUNT = 5; @Inject private JMSContext context; @Resource(lookup = "USD{property.helloworldmdb.queue}") private Queue queue; @Resource(lookup = "USD{property.helloworldmdb.topic}") private Topic topic; <!-- Remainder of code can be found in the `helloworld-mdb-propertysubstitution` quickstart. --> Modify the activemq-jms.xml file to use the system property substitution values. Example .activemq-jms.xml File <?xml version="1.0" encoding="UTF-8"?> <messaging-deployment xmlns="urn:jboss:messaging-activemq-deployment:1.0"> <server> <jms-destinations> <jms-queue name="HELLOWORLDMDBQueue"> <entry name="USD{property.helloworldmdb.queue}"/> </jms-queue> <jms-topic name="HELLOWORLDMDBTopic"> <entry name="USD{property.helloworldmdb.topic}"/> </jms-topic> </jms-destinations> </server> </messaging-deployment> Deploy the application. The application now uses the values specified by the system properties for the @Resource and @ActivationConfigProperty property values. 4.7. Activation Configuration Properties 4.7.1. Configuring MDBs Using Annotations You can configure activation properties by using the @MessageDriven element and sub-elements which correspond to the @ActivationConfigProperty annotation. @ActivationConfigProperty is an array of activation configuration properties for MDBs. The @ActivationConfigProperty annotation specification is as follows: @Target(value={}) @Retention(value=RUNTIME) public @interface ActivationConfigProperty { String propertyName(); String propertyValue(); } Example showing @ActivationConfigProperty @MessageDriven(name="MyMDBName", activationConfig = { @ActivationConfigProperty(propertyName="destinationLookup",propertyValue="queueA"), @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), }) 4.7.2. Configuring MDBs Using a Deployment Descriptor The <message-driven> element in the ejb-jar.xml defines the bean as an MDB. The <activation-config> and elements contain the MDB configuration via the activation-config-property elements. Example ejb-jar.xml <?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1"> <enterprise-beans> <message-driven> <ejb-name>MyMDBName</ejb-name> <ejb-class>org.jboss.tutorial.mdb_deployment_descriptor.bean.MyMDBName</ejb-class> <activation-config> <activation-config-property> <activation-config-property-name>destinationLookup</activation-config-property-name> <activation-config-property-value>queueA</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-property> <activation-config-property-name>acknowledgeMode</activation-config-property-name> <activation-config-property-value>Auto-acknowledge</activation-config-property-value> </activation-config-property> </activation-config> </message-driven> <enterprise-beans> </jboss:ejb-jar> Table 4.1. Activation Configuration Properties Defined by Jakarta Messaging Service Specifications Name Description destinationLookup The Java Naming and Directory Interface name of the queue or topic. This is a mandatory value. connectionFactoryLookup The lookup name of an administratively defined javax.jms.ConnectionFactory , javax.jms.QueueConnectionFactory or javax.jms.TopicConnectionFactory object that will be used to connect to the Jakarta Messaging provider from which the endpoint would receive messages. If not defined explicitly, pooled connection factory with name activemq-ra is used. destinationType The type of destination valid values are javax.jms.Queue or javax.jms.Topic . This is a mandatory value. messageSelector The value for a messageSelector property is a string which is used to select a subset of the available messages. Its syntax is based on a subset of the SQL 92 conditional expression syntax and is described in detail in Jakarta Messaging specification. Specifying a value for the messageSelector property on the ActivationSpec JavaBean is optional. acknowledgeMode The type of acknowledgement when not using transacted Jakarta Messaging. Valid values are Auto-acknowledge or Dups-ok-acknowledge . This is not a mandatory value. The default value is Auto-acknowledge . clientID The client ID of the connection. This is not a mandatory value. subscriptionDurability Whether topic subscriptions are durable. Valid values are Durable or NonDurable . This is not a mandatory value. The default value is NonDurable . subscriptionName The subscription name of the topic subscription. This is not a mandatory value. Table 4.2. Activation Configuration Properties Defined by JBoss EAP Name Description destination Using this property with useJNDI=true has the same meaning as destinationLookup . Using it with useJNDI=false , the destination is not looked up, but it is instantiated. You can use this property instead of destinationLookup . This is not a mandatory value. shareSubscriptions Whether the connection is configured to share subscriptions. The default value is False . user The user for the Jakarta Messaging connection. This is not a mandatory value. password The password for the Jakarta Messaging connection. This is not a mandatory value. maxSession The maximum number of concurrent sessions to use. This is not a mandatory value. The default value is 15 . transactionTimeout The transaction timeout for the session in milliseconds. This is not a mandatory value. If not specified or 0, the property is ignored and the transactionTimeout is not overridden and the default transactionTimeout defined in the Transaction Manager is used. useJNDI Whether or not use Java Naming and Directory Interface to look up the destination. The default value is True . jndiParams The Java Naming and Directory Interface parameters to use in the connection. Parameters are defined as name=value pairs separated by ; localTx Use local transaction instead of XA. The default value is False . setupAttempts Number of attempts to setup a Jakarta Messaging connection. It is possible that the MDB is deployed before the Jakarta Messaging resources are available. In that case, the resource adapter will try to set up several times until the resources are available. This applies only to inbound connections. The default value is -1 . setupInterval Interval in milliseconds between consecutive attempts to setup a Jakarta Messaging connection. This applies only to inbound connections. The default value is 2000 . rebalanceConnections Whether rebalancing of inbound connections is enabled or not. This parameter allows for rebalancing of all inbound connections when the underlying cluster topology changes. There is no rebalancing for outbound connections. The default value is False . deserializationWhiteList A comma-separated list of entries for the white list, which is the list of trusted classes and packages. This property is used by the Jakarta Messaging resource adapter to allow objects in the list to be deserialized. For more information, see Controlling Jakarta Messaging ObjectMessage Deserialization in Configuring Messaging for JBoss EAP. deserializationBlackList A comma-separated list of entries for the black list, which is the list of untrusted classes and packages. This property is used by the Jakarta Messaging resource adapter to prevent objects in the list from being deserialized. For more information, see Controlling Jakarta Messaging ObjectMessage Deserialization in Configuring Messaging for JBoss EAP. 4.7.3. Some Example Use Cases for Configuring MDBs Use case for an MDB receiving a message For a basic scenario when MDB receives a message, see the helloworld-mdb quickstart that is shipped with JBoss EAP. Use case for an MDB sending a message After processing the message you may need to inform other business systems or reply to the message. In this case, you can send the message from MDB as shown in the snippet below: package org.jboss.as.quickstarts.mdb; import javax.annotation.Resource; import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.inject.Inject; import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.Queue; @MessageDriven(name = "MyMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queue/MyMDBRequest"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) public class MyMDB implements MessageListener { @Inject private JMSContext jmsContext; @Resource(lookup = "java:/queue/ResponseDefault") private Queue defaultDestination; /** * @see MessageListener#onMessage(Message) */ public void onMessage(Message rcvMessage) { try { Message response = jmsContext.createTextMessage("Response for message " + rcvMessage.getJMSMessageID()); if (rcvMessage.getJMSReplyTo() != null) { jmsContext.createProducer().send(rcvMessage.getJMSReplyTo(), response); } else { jmsContext.createProducer().send(defaultDestination, response); } } catch (JMSException e) { throw new RuntimeException(e); } } } In the example above, after the MDB receives the message, it replies to either the destination specified in JMSReplyTo or the destination which is bound to the Java Naming and Directory Interface name java:/queue/ResponseDefault . Use case for an MDB configuring rebalancing of inbound connection @MessageDriven(name="MyMDBName", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queueA"), @ActivationConfigProperty(propertyName = "rebalanceConnections", propertyValue = "true") } )

Commands:
/subsystem=ejb3/strict-max-bean-instance-pool=mdb-strict-max-pool:write-attribute(name=derive-size,value=undefined) /subsystem=ejb3/strict-max-bean-instance-pool=mdb-strict-max-pool:write-attribute(name=max-pool-size,value=1) reload
<?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="urn:delivery-active:1.1" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <d:delivery> <ejb-name>HelloWorldQueueMDB</ejb-name> <d:active>false</d:active> </d:delivery> </assembly-descriptor> </jboss:ejb-jar>
@MessageDriven(name = "HelloWorldMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/HELLOWORLDMDBQueue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) @DeliveryActive(false) public class HelloWorldMDB implements MessageListener { public void onMessage(Message rcvMessage) { // } }
<dependency> <groupId>org.jboss.ejb3</groupId> <artifactId>jboss-ejb3-ext-api</artifactId> <version>2.2.0.Final</version> </dependency>
cd deployment=helloworld-mdb.war/subsystem=ejb3/message-driven-bean=HelloWorldQueueMDB
:stop-delivery
:start-delivery
<delivery> <ejb-name>MdbName<ejb-name> <delivery-group>passive</delivery-group> </delivery>
<delivery-groups> <delivery-group name="group" active="true"/> </delivery-groups>
/subsystem=ejb3/mdb-delivery-group=group:add /subsystem=ejb3/mdb-delivery-group=group:remove /subsystem=ejb3/mdb-delivery-group=group:write-attribute(name=active,value=true)
@MessageDriven(name = "HelloWorldQueueMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/HELLOWORLDMDBQueue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) @DeliveryGroup("delivery-group-1") @DeliveryGroup("delivery-group-2") public class HelloWorldQueueMDB implements MessageListener { }
<?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="urn:clustering:1.1" xmlns:d="urn:delivery-active:1.2" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <c:clustering> <ejb-name>HelloWorldQueueMDB</ejb-name> <c:clustered-singleton>true</c:clustered-singleton> </c:clustering> <d:delivery> <ejb-name>*</ejb-name> <d:group>delivery-group-1</d:group> <d:group>delivery-group-2</d:group> </d:delivery> </assembly-descriptor> </jboss:ejb-jar>
<c:clustering> <ejb-name>*</ejb-name> <c:clustered-singleton>true</c:clustered-singleton> </c:clustering>
<d:delivery> <ejb-name>HelloWorldTopicMDB</ejb-name> <d:group>my-mdb-delivery-group</d:group> </d:delivery>
<jboss xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:jee="http://java.sun.com/xml/ns/javaee" xmlns:mdb="urn:resource-adapter-binding"> <jee:assembly-descriptor> <mdb:resource-adapter-binding> <jee:ejb-name>MyMDB</jee:ejb-name> <mdb:resource-adapter-name>MyResourceAdapter.rar</mdb:resource-adapter-name> </mdb:resource-adapter-binding> </jee:assembly-descriptor> </jboss>
<mdb:resource-adapter-name>OtherDeployment.ear#MyResourceAdapter.rar</mdb:resource-adapter-name>
<mdb:resource-adapter-name>#MyResourceAdapter.rar</mdb:resource-adapter-name>
EAP_HOME /bin/standalone.sh -c standalone-full.xml
EAP_HOME /bin/jboss-cli.sh --connect
/subsystem=ee:write-attribute(name=annotation-property-replacement,value=true)
{"outcome" => "success"}
<subsystem xmlns="urn:jboss:domain:ee:4.0"> <annotation-property-replacement>true</annotation-property-replacement> </subsystem>
/system-property= PROPERTY_NAME :add(value= PROPERTY_VALUE )
/system-property=property.helloworldmdb.queue:add(value=java:/queue/HELLOWORLDMDBPropQueue) /system-property=property.helloworldmdb.topic:add(value=java:/topic/HELLOWORLDMDBPropTopic) /system-property=property.connection.factory:add(value=java:/ConnectionFactory)
<system-properties> <property name="property.helloworldmdb.queue" value="java:/queue/HELLOWORLDMDBPropQueue"/> <property name="property.helloworldmdb.topic" value="java:/topic/HELLOWORLDMDBPropTopic"/> <property name="property.connection.factory" value="java:/ConnectionFactory"/> </system-properties>
EAP_HOME /bin/standalone.sh -c standalone-full.xml -Dproperty.helloworldmdb.queue=java:/queue/HELLOWORLDMDBPropQueue -Dproperty.helloworldmdb.topic=java:/topic/HELLOWORLDMDBPropTopic -Dproperty.connection.factory=java:/ConnectionFactory
@MessageDriven(name = "HelloWorldQueueMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "USD{property.helloworldmdb.queue}"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
@MessageDriven(name = "HelloWorldQTopicMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "USD{property.helloworldmdb.topic}"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
/** * Definition of the two Jakarta Messaging Service destinations used by the quickstart * (one queue and one topic). */ @JMSDestinationDefinitions( value = { @JMSDestinationDefinition( name = "java:/USD{property.helloworldmdb.queue}", interfaceName = "javax.jms.Queue", destinationName = "HelloWorldMDBQueue" ), @JMSDestinationDefinition( name = "java:/USD{property.helloworldmdb.topic}", interfaceName = "javax.jms.Topic", destinationName = "HelloWorldMDBTopic" ) }) /** * <p> * A simple servlet 3 as client that sends several messages to a queue or a topic. * </p> * * <p> * The servlet is registered and mapped to /HelloWorldMDBServletClient using the {@linkplain WebServlet * @HttpServlet}. * </p> * * @author Serge Pagop (spagop@redhat.com) * */ @WebServlet("/HelloWorldMDBServletClient") public class HelloWorldMDBServletClient extends HttpServlet { private static final long serialVersionUID = -8314035702649252239L; private static final int MSG_COUNT = 5; @Inject private JMSContext context; @Resource(lookup = "USD{property.helloworldmdb.queue}") private Queue queue; @Resource(lookup = "USD{property.helloworldmdb.topic}") private Topic topic; <!-- Remainder of code can be found in the `helloworld-mdb-propertysubstitution` quickstart. -->
<?xml version="1.0" encoding="UTF-8"?> <messaging-deployment xmlns="urn:jboss:messaging-activemq-deployment:1.0"> <server> <jms-destinations> <jms-queue name="HELLOWORLDMDBQueue"> <entry name="USD{property.helloworldmdb.queue}"/> </jms-queue> <jms-topic name="HELLOWORLDMDBTopic"> <entry name="USD{property.helloworldmdb.topic}"/> </jms-topic> </jms-destinations> </server> </messaging-deployment>
@Target(value={}) @Retention(value=RUNTIME) public @interface ActivationConfigProperty { String propertyName(); String propertyValue(); }
@MessageDriven(name="MyMDBName", activationConfig = { @ActivationConfigProperty(propertyName="destinationLookup",propertyValue="queueA"), @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), })
<?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1"> <enterprise-beans> <message-driven> <ejb-name>MyMDBName</ejb-name> <ejb-class>org.jboss.tutorial.mdb_deployment_descriptor.bean.MyMDBName</ejb-class> <activation-config> <activation-config-property> <activation-config-property-name>destinationLookup</activation-config-property-name> <activation-config-property-value>queueA</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-property> <activation-config-property-name>acknowledgeMode</activation-config-property-name> <activation-config-property-value>Auto-acknowledge</activation-config-property-value> </activation-config-property> </activation-config> </message-driven> <enterprise-beans> </jboss:ejb-jar>
package org.jboss.as.quickstarts.mdb; import javax.annotation.Resource; import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.inject.Inject; import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.Queue; @MessageDriven(name = "MyMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queue/MyMDBRequest"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) public class MyMDB implements MessageListener { @Inject private JMSContext jmsContext; @Resource(lookup = "java:/queue/ResponseDefault") private Queue defaultDestination; /** * @see MessageListener#onMessage(Message) */ public void onMessage(Message rcvMessage) { try { Message response = jmsContext.createTextMessage("Response for message " + rcvMessage.getJMSMessageID()); if (rcvMessage.getJMSReplyTo() != null) { jmsContext.createProducer().send(rcvMessage.getJMSReplyTo(), response); } else { jmsContext.createProducer().send(defaultDestination, response); } } catch (JMSException e) { throw new RuntimeException(e); } } }
@MessageDriven(name="MyMDBName", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queueA"), @ActivationConfigProperty(propertyName = "rebalanceConnections", propertyValue = "true") } )