Oracle® Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide
10g Release 2 (10.1.2) Part No. B15505-01 |
|
![]() Previous |
![]() Next |
The MDB processes incoming asynchronous requests using Oracle JMS (Advanced Queuing), as follows:
Caution: MDBs only work with certain versions of the Oracle database. See the certification matrix in the JMS chapter of the Oracle Application Server Containers for J2EE Services Guide for more information. |
The MDB opens a JMS connection to the database using a data source with a username and password. The data source represents the Oracle JMS provider and uses a JDBC driver to facilitate the JMS connection.
The MDB opens a JMS session over the JMS connection.
Any message for the MDB is routed to the onMessage
method of the MDB.
At any time, the client can send a message to the Oracle JMS topic or queue on which MDBs are listening. The Oracle JMS topic or queue is located in the database.
Note: The entire MDB example is available on OTN from the OC4J sample code page athttp://www.oracle.com/technology/tech/java/oc4j/demos/ on the OTN Web site.
|
Figure 9-2 Demonstration of an MDB Interacting with an Oracle JMS Destination
The following sections demonstrate an MDB that uses Oracle JMS as the JMS provider.
Create the OC4J-Specific Deployment Descriptor to Use Oracle JMS
Note: A full description of how to use Oracle JMS provider is discussed in the JMS chapter in the Oracle Application Server Containers for J2EE Services Guide. Also, see the Oracle9i Application Developer's Guide - Advanced Queuing. |
You or your DBA must install Oracle JMS according to theOracle9i Application Developer's Guide—Advanced Queuing for Release 2 (9.2) and generic database manuals. Once you have installed and configured this JMS provider, you must apply additional configuration for each MDB. This includes the following:
You or your DBA should create an RDBMS user through which the MDB connects to the database. Grant this user appropriate access privileges to perform Oracle JMS operations. See "Create User and Assign Privileges".
You or your DBA should create the tables and queues to support the JMS Destination
objects. See "Create JMS Destination Objects".
Note: The following sections use SQL for creating queues, topics, their tables, and assigning privileges that is provided within the MDB demo on OTN from the OC4J sample code page athttp://www.oracle.com/technology/tech/java/oc4j/demos/ on the OTN Web site.
|
Create an RDBMS user through which the MDB connects to the database. Grant access privileges to this user to perform Oracle JMS operations. The privileges that you need depend on what functionality you are requesting. Refer to theOracle9i Application Developer's Guide—Advanced Queuing for Release 2 (9.2) for more information on privileges necessary for each type of function.
The following example creates jmsuser
, which must be created within its own schema, with privileges required for Oracle JMS operations. You must be a SYS
DBA
to execute these statements.
DROP USER jmsuser CASCADE ; GRANT connect, resource,AQ_ADMINISTRATOR_ROLE TO jmsuser IDENTIFIED BY jmsuser ; GRANT execute ON sys.dbms_aqadm TO jmsuser; GRANT execute ON sys.dbms_aq TO jmsuser; GRANT execute ON sys.dbms_aqin TO jmsuser; GRANT execute ON sys.dbms_aqjms TO jmsuser; connect jmsuser/jmsuser;
You may need to grant other privileges, such as two-phase commit or system administration privileges, based on what the user needs. See the JTA chapter in the Oracle Application Server Containers for J2EE Services Guide for the two-phase commit privileges.
Each JMS provider requires its own method for creating the JMS Destination
object. Refer to theOracle9i Application Developer's Guide—Advanced Queuing for Release 2 (9.2) for more information on the DBMS_AQADM
packages and Oracle JMS messages types. For our example, Oracle JMS requires the following methods:
Note: The SQL for creating the tables for the Oracle JMS example is included in the MDB example available on OTN from the OC4J sample code page athttp://www.oracle.com/technology/tech/java/oc4j/demos/ on the OTN Web site.
|
Create the tables that handle the JMS Destination
(queue or topic).
In Oracle JMS, both topics and queues use a queue table. The rpTestMdb
JMS example creates a single table: rpTestQTab
for a queue.
To create the queue table, execute the following SQL:
DBMS_AQADM.CREATE_QUEUE_TABLE( Queue_table => 'rpTestQTab', Queue_payload_type => 'SYS.AQ$_JMS_MESSAGE', sort_list => 'PRIORITY,ENQ_TIME', multiple_consumers => false, compatible => '8.1.5');
The multiple_consumers
parameter denotes whether there are multiple consumers or not; thus, is always false for a queue and true for a topic.
Create the JMS Destination
. If you are creating a topic, you must add each subscriber for the topic. The rpTestMdb
JMS example requires a single queue—rpTestQueue
.
The following creates a queue called rpTestQueue
within the queue table rpTestQTab
. After creation, the queue is started.
DBMS_AQADM.CREATE_QUEUE( Queue_name => 'rpTestQueue', Queue_table => 'rpTestQTab'); DBMS_AQADM.START_QUEUE( queue_name => 'rpTestQueue');
If you wanted to add a topic, then the following example shows how you can create a topic called rpTestTopic
within the topic table rpTestTTab
. After creation, two durable subscribers are added to the topic. Finally, the topic is started and a user is granted a privilege to it.
Note: Oracle AQ uses theDBMS_AQADM.CREATE_QUEUE method to create both queues and topics.
|
DBMS_AQADM.CREATE_QUEUE_TABLE( Queue_table => 'rpTestTTab', Queue_payload_type => 'SYS.AQ$_JMS_MESSAGE', multiple_consumers => true, compatible => '8.1.5'); DBMS_AQADM.CREATE_QUEUE( 'rpTestTopic', 'rpTestTTab'); DBMS_AQADM.ADD_SUBSCRIBER('rpTestTopic', sys.aq$_agent('MDSUB', null, null)); DBMS_AQADM.ADD_SUBSCRIBER('rpTestTopic', sys.aq$_agent('MDSUB2', null, null)); DBMS_AQADM.START_QUEUE('rpTestTopic');
Note: The names defined here must be the same names used to define the queue or topic in theorion-ejb-jar.xml file.
|
To use the Oracle JMS provider, you must configure the following in the OC4J XML files:
Configure a data source for the database where the Oracle JMS provider is installed. The JMS topics and queues use database tables and queues to facilitate messaging. The type of data source you use depends on the functionality you want.
For no transactions or single-phase transactions, you can use either an emulated or non-emulated data sources. For two-phase commit transaction support, you can use only a non-emulated data source.
Example 9-4 Emulated DataSource With Thin JDBC Driver
The following example contains an emulated data source that uses the thin JDBC driver. To support a two-phase commit transaction, use a non-emulated data source. For differences between emulated and non-emulated data sources, see the Data Source chapter in the Oracle Application Server Containers for J2EE Services Guide.
The example is displayed in the format of an XML definition; see the Oracle Application Server Containers for J2EE User's Guide for directions on adding a new data source to the configuration through the EM tool.
<data-source class="com.evermind.sql.DriverManagerDataSource" name="OracleDS" location="jdbc/emulatedOracleCoreDS" xa-location="jdbc/xa/emulatedOracleXADS" ejb-location="jdbc/emulatedDS" connection-driver="oracle.jdbc.driver.OracleDriver" username="jmsuser" password="jmsuser" url="jdbc:oracle:thin:@myhost.foo.com:1521:mydb" />
Customize this data source to match your environment. For example, substitute the host name, port, and SID of your database for mysun:1521:orcl
.
Note: Instead of providing the password in the clear, you can use password indirection. For details, see the Oracle Application Server Containers for J2EE Services Guide. |
Identify the JNDI name of the data source that is to be used as the Oracle JMS provider within the <resource-provider>
element.
If this is to be the JMS provider for all applications (global), configure the global application.xml
file.
If this is to be the JMS provider for a single application (local), configure the orion-application.xml
file of the application.
The following code sample shows how to configure the JMS provider using XML syntax for Oracle JMS.
class
attribute—The Oracle JMS provider is implemented by the oracle.jms.OjmsContext
class, which is configured in the class
attribute.
property
attribute—Identify the data source that is to be used as this JMS provider in the property
element. The topic or queue connects to this data source to access the tables and queues that facilitate the messaging.
The following example demonstrates that the data source identified by "jdbc/emulatedDS
" is to be used as the Oracle JMS provider. This JNDI name is identified in the ejb-location
element in Example 9-4. If this example used a non-emulated data source, then the name would be the same as in the location
element.
<resource-provider class="oracle.jms.OjmsContext" name="myProvider"> <description> OJMS/AQ </description> <property name="datasource" value="jdbc/emulatedDS"></property> </resource-provider>
The OC4J-specific deployment descriptor configures the following:
Specify the Destination
and connection factory JNDI locations to the MDB through the <message-driven-deployment>
element in the orion-ejb-jar.xml
file. See "Specify the Destination and Connection Factory" for full details.
Associate any logical names defined as resource references in the ejb-jar.xml
file to the correct queue or topic, which, for Oracle JMS, was defined in the database through SQL. You could have several topics and queues defined in database. See "Map Any Resource References to JNDI Names" for full details on mapping the resource references in the orion-ejb-jar.xml
file.
Since this example uses resource references in the ejb-jar.xml
file, the orion-ejb-jar.xml
file maps these logical names to the actual JNDI names of the connection factory and the JMS Destination
object, which are defined in the database. In this example, the MDB uses a queue that is defined in the database as rpTestQueue
. The queue connection factory is not defined in the database, so any name can be used. For consistency, the queue connection factory name is myQCF
.
Map the Destination
and connection factory JNDI locations 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 rpTestMdb
example. It maps a JMS Queue
to the rpTestMdb
MDB, providing the following:
MDB name, as defined in the <message-driven><ejb-name>
in the EJB deployment descriptor, is specified in the name
attribute.
JMS Destination
Connection
Factory
, as specified by the user, is specified in the connection-factory-location
attribute. The Oracle JMS syntax for the connection factory is "java:comp/resource
" + JMS provider name + "TopicConnectionFactories
" or "QueueConnectionFactories
" + a user defined name. The user-defined name can be anything and does not match any other configuration. The xxxConnectionFactories
details what type of factory is being defined. For this example, the JMS provider name is defined in the <resource-provider>
element in the application.xml
file as myProvider
.
For a queue connection factory: Since the JMS provider name is myProvider
and you decide to use a name of myQCF
, the connection factory name is "java:comp/resource/myProvider/QueueConnectionFactories/myQCF
".
For a topic connection factory: Since the JMS provider name is myProvider
and you decide to use a name of myTCF
, the connection factory name is "java:comp/resource/myProvider/TopicConnectionFactories/myTCF
".
The user defined names, as shown above by myQCF
and myTCF
, are not used for anything else in your logic. So, any name can be chosen.
JMS Destination
, as defined in the database, is specified in the destination-location
element. The Oracle JMS syntax for the Destination
is "java:comp/resource
" + JMS provider name + "Topics
" or "Queues
" + Destination
name. The Topic
or Queue
details what type of Destination
is being defined. The Destination
name is the actual queue or topic name defined in the database.
For this example, the JMS provider name is defined in the <resource-provider>
element in the application.xml
file as myProvider
. In the database, the topic name is rpTestQueue
.
For a queue: If the JMS provider name is myProvider
and the queue name is rpTestQueue
, then the JNDI name for the queue as "java:comp/resource/myProvider/Queues/rpTestQueue
."
For a topic: If the JMS provider name is myProvider
and the topic name is rpTestTopic
, then the JNDI name for the topic as "java:comp/resource/myProvider/Topics/rpTestTopic
."
If this was a topic, then a durable topic name, which is user-defined, is specified in the subscription-name
attribute.
Listener threads are an optional parameter and defined in the listener-threads
attribute. The listener threads are spawned off when MDBs are deployed and are used to listen for incoming JMS messages on the topic or queue. These threads concurrently consume JMS messages. The default is one thread. Topics always use only one thread; queues can use more than one.
Transaction timeout, as defined in the transaction-timeout
attribute, is an optional parameter. This attribute controls the transaction timeout interval (in seconds) for any container-managed transactional MDB. The default is one day or 86,400 seconds. If the transaction has not completed in this time frame, the transaction is rolled back and the message is redelivered back to the Destination
object.
The MDB transaction-timeout attribute applies only to CMT MDBs that use Oracle JMS as the JMS provider. This attribute setting has no effect on BMT MDBs or any MDBs that use OC4J JMS:
JMS behavior with Oracle Application Server—JMS attempts to redeliver the message (defaults to five attempts and is set on the DBMS_AQADM.CREATE_QUEUE
method when creating the queue in the database), after which the message is moved to the exception queue. You can browse messages in the exception queue using SQL*Plus. For more information on setting redelivery attempts and browsing the exception queue, refer to theOracle9i Application Developer's Guide—Advanced Queuing for Release 2 (9.2).
JMS behavior with OC4J—The transaction-timeout setting does not work for CMT MDBs that use OC4J JMS. The timeout is always one day and cannot be modified. When the timeout occurs, OC4J JMS redelivers the message indefinitely, until the delivery is successful. You cannot set a retry limit.
In addition, the global transaction-timeout attribute defined in the server.xml file does not have any effect on MDBs.
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
.
<message-driven-deployment name="testMdb" connection-factory-location= "java:comp/resource/myProvider/QueueConnectionFactories/myQCF" destination-location="java:comp/resource/myProvider/Queues/rpTestQueue" listener-threads="5">
If you wanted to specify a topic, you must also include the subscription name, as follows:
<enterprise-beans> <message-driven-deployment name="rpTestMdb" connection-factory-location= "java:comp/resource/myProvider/TopicConnectionFactories/myTCF" destination-location="java:comp/resource/cartojms1/Topics/rpTestTopic" subscription-name="MDBSUB" listener-threads=1 > ... </enterprise-beans>
Note: You cannot use logical names in these fields. You must specify the full JNDI syntax for both the connection factory and theDestination object.
|
When you define logical names as resource references for your connection factory and Destination
object, you have to map these to the actual JNDI names.
Map the resource reference for the queue connection factory in the <resource-ref-mapping>
element. In the rpTestMdb
example, the logical name for the connection factory is jms/myQueueConnectionFactory
. This must be mapped to the JNDI string of java:comp/resource/myProvider/QueueConnectionFactories/myQCF.
Map the resource reference for the Destination
object in the <resource-env-ref-mapping>
element. In the rpTestMdb
example, the logical name for the queue is jms/persistentQueue
. This is mapped to the JNDI string of java:comp/resource/myProvider/Queues/rpTestQueue
.
See "Specify the Destination and Connection Factory" for how the Oracle JMS JNDI syntax was derived.
<resource-ref-mapping name="jms/myQueueConnectionFactory" location="java:comp/resource/myProvider/QueueConnectionFactories/myQCF"/> <resource-env-ref-mapping name="jms/persistentQueue" location="java:comp/resource/myProvider/Queues/rpTestQueue" />
Example 9-5 The orion-ejb-jar.xml file for the rpTestMdb Example
The following lists the complete orion-ejb-jar.xml
file for the rpTestMdb
example. It includes both the definition of the Oracle JMS objects and the resource reference mappings.
<enterprise-beans> <message-driven-deployment name="testMdb" connection-factory-location= "java:comp/resource/myProvider/QueueConnectionFactories/myQCF" destination-location="java:comp/resource/myProvider/Queues/rpTestQueue" listener-threads="5"> <resource-ref-mapping name="jms/myQueueConnectionFactory" location="java:comp/resource/myProvider/QueueConnectionFactories/myQCF"/> <resource-env-ref-mapping name="jms/persistentQueue" location="java:comp/resource/myProvider/Queues/rpTestQueue" /> </message-driven-deployment> </enterprise-beans> <assembly-descriptor> <default-method-access> <security-role-mapping name="<default-ejb-caller-role>" impliesAll="true" /> </default-method-access> </assembly-descriptor>
Archive your MDB into a JAR file. You deploy the MDB in the same way as the session bean, which Prepare the EJB Application for Assembly and "Deploy the Enterprise Application to OC4J" describe.
Note: Instructions on how a client sends a JMS message to the MDB is discussed in "Client Access of MDB". |