Oracle® Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide
10g Release 2 (10.1.2) Part No. B15505-01 |
|
![]() Previous |
![]() Next |
The client sends a message to the MDB through a JMS Destination
. The client can retrieve the JMS Destination
and connection factory either through using its explicit name or by a logical name. The following sections describe both methods for retrieving the JNDI name.
Using a Logical Name When Client Accesses the MDB
Note: You may have to add the JNDI properties if the client is not co-located with the MDB. The examples provided in the following sections do not include setting the JNDI properties. See "Setting JNDI Properties" for instructions on setting these properties. |
Within your client, you can use the actual JNDI name to retrieve the JMS Destination
objects. Both OracleAS JMS and Oracle JMS have their own naming methodology, as explained in the following sections:
Accessing Oracle JMS Destination with Explicit JNDI Names
Note: Alternatively, you can specify all of the JNDI names for theDestination and JMS provider objects as resource references in your orion-ejb-jar.xml file. See "Using a Logical Name When Client Accesses the MDB" for more information.
|
The JNDI lookup for OracleAS JMS requires the OracleAS JMS Destination
and connection factory as defined by you within the jms.xml
file, prepended with "java:comp/env/
." See "JMS Destination Object Configuration" to see how the queue and topic for OracleAS JMS is configured.
Note: If you decide to use logical names instead, you would use the same JNDI syntax. Logical names are recommended, because they are portable. See "Using a Logical Name When Client Accesses the MDB" for more information. |
To lookup a queue in the JNDI lookup for the testResourceProvider
example using OracleAS JMS are as follows:
//Lookup the Queue queue = (Queue)jndiContext.lookup("java:comp/env/jms/Queue/rpTestQueue"); //Lookup the Queue Connection factory queueConnectionFactory = (QueueConnectionFactory) jndiContext.lookup("java:comp/env/jms/Queue/myQCF");
To lookup a topic, you would have slightly different strings, designating a topic rather than a queue, as follows:
//Lookup the Topic topic = (Topic)jndiContext.lookup("java:comp/env/jms/Topic/rpTestTopic"); //Lookup the Connection factory topicConnectionFactory = (TopicConnectionFactory) jndiContext.lookup("java:comp/env/jms/Topic/myTCF");
Note that the same names for the topic and the connection factory are used in the client's configuration, the jms.xml
, and the MDB deployment descriptors.
The JNDI lookup—when using Oracle JMS—requires the Oracle JMS Destination
and connection factory syntax, which is the same naming convention as described for the connection-factory-location
and destination-location
attributes in "Specify the Destination and Connection Factory".
Note: If you decide to use logical names instead, you would use the same JNDI syntax. See "Using a Logical Name When Client Accesses the MDB" for more information. |
In your JNDI lookup, the implementation would be as follows for both a queue and a topic (See Example 9-6 for the full example):
/* Retrieve an Oracle JMS Queue through JNDI */ queue = (Queue) ic.lookup("java:comp/resource/myProvider/Queues/rpTestQueue"); /*Retrieve the Oracle JMS Queue connection factory */ queueConnectionFactory = (QueueConnectionFactory) ic.lookup ("java:comp/resource/myProvider/QueueConnectionFactories/myQCF"); /* Retrieve an Oracle JMS Topic through JNDI */ topic = (Topic) ic.lookup("java:comp/resource/myProvider/Topics/rpTestTopic"); /*Retrieve the Oracle JMS Topic connection factory */ topicConnectionFactory = (TopicConnectionFactory) ic.lookup ("java:comp/resource/myProvider/TopicConnectionFactories/myTCF");
Whether or not the implementation uses logical names or the actual JNDI names, the client sends a JMS message to the MDB by doing the following:
Retrieve both the configured JMS Destination
and its connection factory using a JNDI lookup.
Create a connection from the connection factory. If you are receiving messages for a queue, then start the connection.
Create a session over the connection.
Providing the retrieved JMS Destination
, create a sender for a queue, or a publisher for a topic.
Create the message.
Send out the message using either the queue sender or the topic publisher.
Close the queue session. Close the connection for either JMS Destination
types.
Example 9-6 Servlet Client Sends Message to Queue
public final class testResourceProvider extends HttpServlet { private String resProvider = "myResProvider"; private HashMap msgMap = new HashMap(); Context ctx = new InitialContext(); public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { doPost(req, res); } public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { //Retrieve the name of the JMS provider from the request, which is // to be used in creating the JNDI string for retrieval String rp = req.getParameter ("provider"); if (rp != null) resProvider = rp; try { // 1a. Look up the Queue Connection Factory QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup ("java:comp/resource/" + resProvider + "/QueueConnectionFactories/myQCF"); // 1b. Lookup the Queue Queue queue = (Queue) ctx.lookup ("java:comp/resource/" + resProvider + "/Queues/rpTestQueue"); // 2 & 3. Retrieve a connection and a session on top of the connection // 2a. Create queue connection using the connection factory. QueueConnection qconn = qcf.createQueueConnection(); // 2a. We're receiving msgs, so start the connection. qconn.start(); // 3. create a session over the queue connection. QueueSession qsess = qconn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); // 4. Since this is for a queue, create a sender on top of the session. //This is used to send out the message over the queue. QueueSender snd = sess.createSender (q); drainQueue (sess, q); TextMessage msg = null; /* Send msgs to queue. */ for (int i = 0; i < 3; i++) { // 5. Create message msg = sess.createTextMessage(); msg.setText ("TestMessage:" + i); // set property of the recipient to be the MDB //and set the reply destination. msg.setStringProperty ("RECIPIENT", "MDB"); msg.setJMSReplyTo(q); //6. send the message using the sender. snd.send (msg); // You can store the messages IDs and sent-time in a map (msgMap), // so that when messages are received, you can verify if you // *only* received those messages that you were // expecting. See receiveFromMDB() method where msgMap gets used. msgMap.put (msg.getJMSMessageID(), new Long (msg.getJMSTimestamp())); } // receive a reply from the MDB. receiveFromMDB (sess, q); //7. Close sender, session, and connection for queue snd.close(); sess.close(); qconn.close(); } catch (Exception e) { System.err.println ("** TEST FAILED **"+ e.toString()); e.printStackTrace(); } finally { } } /* * Receive any msgs sent to us via the MDB */ private void receiveFromMDB (QueueSession sess, Queue q) throws Exception { //The MDB sends out a message (as a reply) to this client. The MDB sets // the receipient as CLIENT. Thus, we will only receive msgs that have // RECIPIENT set to 'CLIENT' QueueReceiver rcv = sess.createReceiver (q, "RECIPIENT = 'CLIENT'"); int nrcvd = 0; long trtimes = 0L; long tctimes = 0L; // First msg needs to come from MDB. May take a little while //Receiving Messages for (Message msg = rcv.receive (30000); msg != null; msg = rcv.receive (30000)) { nrcvd++; String rcp = msg.getStringProperty ("RECIPIENT"); // Verify if msg in message Map // We check the msgMap to see if this is the message that we are // expecting. String corrid = msg.getJMSCorrelationID(); if (msgMap.containsKey(corrid)) { msgMap.remove(corrid); } else { System.err.println ("** received unexpected message [" + corrid + "] **"); } } rcv.close(); } /* * Drain messages from queue */ private int drainQueue (QueueSession sess, Queue q) throws Exception { QueueReceiver rcv = sess.createReceiver (q); int nrcvd = 0; /* * First drain any old msgs from queue */ for (Message msg = rcv.receive(1000); msg != null; msg = rcv.receive(1000)) nrcvd++; rcv.close(); return nrcvd; } }
If you want to use a logical name in your client application code, then define the logical name in one of the following XML files:
A standalone Java client—in the application-client.xml
file
An EJB that acts as a client—the ejb-jar.xml
file
For JSPs and servlets that act as clients—the web.xml
file
Map the logical name to the actual name of the topic or queue name in the OC4J deployment descriptors.
You can create logical names for the connection factory and Destination
objects, as follows:
The connection factory is identified in the client's XML deployment descriptor file within a <resource-ref>
element.
The logical name that you want the connection factory to be identified as is defined in the <res-ref-name>
element.
The connection factory class type is defined in the <res-type>
element as either javax.jms.QueueConnectionFactory
or javax.jms.TopicConnectionFactory
.
The authentication responsibility (Container
or Bean
) is defined in the <res-auth>
element.
The sharing scope (Shareable
or Unshareable
) is defined in the <res-sharing-scope>
element.
The JMS Destination
—the topic or queue—is identified in a <resource-env-ref>
element.
The logical name that you want the topic or queue to be identified as is defined in the <resource-env-ref-name>
element.
The Destination
class type is defined in the <resource-env-ref-type>
element as either javax.jms.Queue
or javax.jms.Topic
.
The following shows an example of how to specify logical names for a topic.
<resource-ref> <res-ref-name>myTCF</res-ref-name> <res-type>javax.jms.TopicConnectionFactory</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> <resource-env-ref> <resource-env-ref-name>rpTestTopic</resource-env-ref-name> <resource-env-ref-type>javax.jms.Topic</resource-env-ref-type> </resource-env-ref>
Then, you map the logical names to actual names in the OC4J deployment descriptors. The actual names, or JNDI names, are different in OracleAS JMS than in Oracle JMS. However, the mapping is defined in one of the following files:
For a standalone Java client—the orion-application-client.xml
For an EJB acting as a client—the orion-ejb-jar.xml
For JSPs and servlets acting as a client—the orion-web.xml
file.
The logical names in the client's deployment descriptor are mapped as follows:
The logical name for the connection factory defined in the <resource-ref>
element is mapped to its JNDI name in the <resource-ref-mapping>
element.
The logical name for the JMS Destination
defined in the <resource-env-ref>
element is mapped to its JNDI name in the <resource-env-ref-mapping>
element.
See the following sections for how the mapping occurs for both OracleAS JMS and Oracle JMS:
The JNDI name for the OracleAS JMS Destination and connection factory is defined by you within the jms.xml
file. As shown in "JMS Destination Object Configuration", the JNDI names for the topic and the topic connection factory are as follows:
The JNDI name for the topic is "jms/Topic/rpTestTopic
."
The JNDI name for the topic connection factory is "jms/Topic/myTCF
."
Prepend both of these names with "java:comp/env/
" and you have the mapping in the orion-ejb-jar.xml
file as follows:
<resource-ref-mapping name="myTCF" location="java:comp/env/jms/Topic/myTCF"> </resource-ref-mapping> <resource-env-ref-mapping name="rpTestTopic" location="java:comp/env/jms/Topic/rpTestTopic"></resource-env-ref-mapping>
The JNDI naming for Oracle JMS Destination
and connection factory objects is the same name that was specified in the orion-ejb-jar.xml
file for the MDB as described in "Specify the Destination and Connection Factory".
The following example maps the logical names for the connection factory and topic to their actual JNDI names. Specifically, the topic defined logically as "rpTestTopic
" in the ejb-jar.xml
file is mapped to its JNDI name of "java:comp/resource/cartojms1/Topics/rpTestTopic
."
<resource-ref-mapping name="myTCF" location="java:comp/resource/myProvider/TopicConnectionFactories/myTCF"> </resource-ref-mapping> <resource-env-ref-mapping name="rpTestTopic" location="java:comp/resource/myProvider/Topics/rpTestTopic"></resource-env-ref-mapping>
Once the resources have been defined, the client sends a JMS message to the MDB by doing the following:
Retrieve both the configured JMS Destination
and its connection factory using a JNDI lookup.
Create a connection from the connection factory. If you are receiving messages for a queue, start the connection.
Create a session over the connection.
Providing the retrieved JMS Destination
, create a sender for a queue, or a publisher for a topic.
Create the message.
Send out the message using either the queue sender or the topic publisher.
Close the queue session. Close the connection for either JMS Destination
types.
Example 9-7 JSP Client Sends Message to a Topic
The method of sending a message over a topic is almost the same. Instead of creating a queue, you create a topic. Instead of creating a sender, you create subscribers.
The following JSP client code sends a message over a topic to the MessageBean
MDB. The code uses logical names, which should be mapped in the OC4J deployment descriptor.
<%@ page import="javax.jms.*, javax.naming.*, java.util.*" %> <% //1a. Lookup the MessageBean topic jndiContext = new InitialContext(); topic = (Topic)jndiContext.lookup("rpTestTopic"); //1b. Lookup the MessageBean Connection factory topicConnectionFactory = (TopicConnectionFactory) jndiContext.lookup("myTCF"); //2 & 3. Retrieve a connection and a session on top of the connection topicConnection = topicConnectionFactory.createTopicConnection(); topicSession = topicConnection.createTopicSession(true, Session.AUTO_ACKNOWLEDGE); //5. Create the publisher for any messages destined for the topic topicPublisher = topicSession.createPublisher(topic); //6. Send out the message for (int ii = 0; ii < numMsgs; ii++) { message = topicSession.createBytesMessage(); String sndstr = "1::This is message " + (ii + 1) + " " + item; byte[] msgdata = sndstr.getBytes(); message.writeBytes(msgdata); topicPublisher.publish(message); System.out.println("--->Sent message: " + sndstr); } //7. Close publisher, session, and connection for topic topicPublisher.close(); topicSession.close(); topicConnection.close(); %> Message sent!