Developing a WebLogic JMS Application


All JMS clients need to access WebLogic's JNDI to gain access to a ConnectionFactory. When connecting to WebLogic, clients need to specify the vendor-specific InitialContextFactory . The following sample code (see Listing 15.1) demonstrates obtaining an InitialContextFactory using RMI over a proprietary WebLogic protocol called "t3" to access the JNDI server. It is worth noting that the RMI specification uses JRMP as the default transport protocol but enables vendors to replace it with their own protocolthe RMI API is left untouched. Clients may need to pass username and password for authentication by the JNDI server. The InitialContext constructor may throw javax.naming.NamingException .

Note

Creating an InitialContext applies to both producers and consumers in the PTP and Pub/Sub domains.


Listing 15.1 Creating a JNDI InitialContext Object
 // Create a JNDI InitialContext Properties props = new Properties() ; props.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); props.put( Context.PROVIDER_URL, "t3://localhost:7001"); // Clients may need to authenticate // props.put( Context.SECURITY_PRINCIPAL, "  username  "); // props.put( Context.SECURITY_CREDENTALS, "  password  "); InitialContext ic = new InitialContext(props); 

Point-to-Point Client

PTP and Pub/Sub clients are similar. They follow similar steps using different interfaces. PTP clients must acquire a QueueConnectionFactory and then use it to create a QueueConnection . The connection then serves as a session factory and creates a QueueSession .

PTP clients use the following code to acquire a connection factory, a connection, and a session:

 
[View full width]
 // Lookup a Connection Factory in JNDI QueueConnectionFactory qCF = (QueueConnectionFactory)ic.lookup("javax.jms graphics/ccc.gif .QueueConnectionFactory"); // Create a Connection QueueConnection qCon = qCF.createQueueConnection(); // Create a Session QueueSession qSession = qCon.createQueueSession(false,Session.AUTO_ACKNOWLEDGE); 

PTP producers need to look up a queue in JNDI. The JNDI name is designated when the queue is created in the WebLogic Administration Console:

 
 // Lookup the Queue Queue queue = (Queue)ic.lookup("book.jms.BookQueue"); 

A Point-to-Point Producer

After getting the queue, a producer needs to create a QueueSender to actually send messages. Clients use the session to create a sender bound to the queue:

 
 // Create a QueueSender bound to the Queue QueueSender qSender = qSession.createSender(queue); 

Next the client creates a message. In this example the client creates a TextMessage and initializes it with "Hello World!":

 
 // Create a TextMessage TextMessage mes = qSession.createTextMessage("Hello World!"); 

Finally the client starts the connection and sends the message five times. Then the client closes the connection.

 
 qCon.start() ; for (int i = 0; i<5; i++ ) { qSender.send(mes); } finally { try { qCon.close(); qSender.close(); qSession.close(); } catch (JMSException je) { System.out.println(je); } } 

Listing 15.2 provides the complete PTPProducer JMS application.

Listing 15.2 The PTPProducer JMS Application
 import javax.naming.*; import javax.jms.*; import java.util.*; public class PTPProducer { private final static String NAMING_FACTORY= "weblogic.jndi.WLInitialContextFactory"; private final static String QCON_FACTORY="javax.jms.QueueConnectionFactory"; private final static String MESSAGE_QUEUE="book.jms.BookQueue"; public static void main ( String[] argv ) throws NamingException, JMSException { QueueConnection qCon = null; QueueSender qSender = null; QueueSession qSession = null; try { // Create a JNDI initial context Properties props = new Properties() ; props.put( Context.INITIAL_CONTEXT_FACTORY, NAMING_FACTORY); props.put( Context.PROVIDER_URL, "t3://localhost:7001"); InitialContext ic = new InitialContext(props); // Look up a Connection Factory in JNDI QueueConnectionFactory qCF = (QueueConnectionFactory)ic.lookup(QCON_FACTORY); // Create a Connection qCon = qCF.createQueueConnection(); // Create a Session qSession = qCon.createQueueSession(false,Session.AUTO_ACKNOWLEDGE); // Lookup the Queue Queue queue = (Queue)ic.lookup(MESSAGE_QUEUE); // Create a QueueSender bound to the Queue qSender = qSession.createSender(queue); // Create a TextMessage TextMessage mes = qSession.createTextMessage("Hello World!"); // Start the Queue, send the message qCon.start() for (int i = 0; i<5; i++ ) { qSender.send(mes); System.out.println("Sending Hello World - " + i + " to the JMS Queue"); } } catch ( NamingException e ) { System.out.println(e); } finally { //Release all JMS resources try { qCon.close(); qSender.close(); qSession.close(); } catch (JMSException je) { System.out.println(je); } } } } 

A Point-to-Point Consumer

PTP consumers share the basic steps with PTP producers. The differences begin after acquiring a queue. A PTP consumer must get a QueueReceiver to interact with the queue as follows :

 
 // Create a QueueReceiver bound to the Queue QueueReceiver qReceiver = qSession.createReceiver(queue); 

The PTP consumer uses a blocking read in an endless loop to receive messages from the queue. Listing 15.3 provides the entire PTPConsumer JMS application.

Listing 15.3 The PTPConsumer JMS Application
 import javax.naming.*; import javax.jms.*; import java.util.*; public class PTPConsumer { private final static String NAMING_FACTORY= "weblogic.jndi.WLInitialContextFactory"; private final static String QCON_FACTORY="javax.jms.QueueConnectionFactory"; private final static String MESSAGE_QUEUE="book.jms.BookQueue"; public static void main ( String[] argv ){ try { // Create a JNDI initial context Properties props = new Properties() ; props.put( Context.INITIAL_CONTEXT_FACTORY, NAMING_FACTORY); props.put( Context.PROVIDER_URL, "t3://localhost:7001"); InitialContext ic = new InitialContext(props); // Look up a Connection Factory in JNDI QueueConnectionFactory qCF = (QueueConnectionFactory)ic.lookup(QCON_FACTORY); // Create a Connection QueueConnection qCon = qCF.createQueueConnection(); // Create a Session QueueSession qSession = qCon.createQueueSession(false,Session.AUTO_ACKNOWLEDGE); // Look up the Queue Queue queue = (Queue)ic.lookup(MESSAGE_QUEUE); // Create a QueueReceiver bound to the Queue QueueReceiver qReceiver = qSession.createReceiver(queue); // Start the Queue, send, and close qCon.start() ; TextMessage msg; while( true ) { msg = (TextMessage)qReceiver.receive(); System.out.println(msg.getText()) ; } } catch ( NamingException e1 ) { System.out.println(e1); } catch ( JMSException e2 ) { System.out.println(e2); } } } 

To run the PTPProducer and PTPConsumer JMS applications, follow these steps:

  1. Compile respective java files using the javac utility.

  2. Start WebLogic Server and ensure you have a JMS server configured with a JMS Queue identified through the JNDI name "book.jms.BookQueue".

    Note

    The examples use the default WebLogic ConnectionFactory so no other WebLogic Server configuration is required to run the examples.

  3. Start a command shell for each of the JMS applications, PTPProducer and PTPConsumer, and also set the appropriate Java environments in each shell session.

  4. Launch the PTPProducer and PTPConsumer JMS Application through the following commands in their respective command shell sessions:

       
      java PTPProducer java PTPConsumer  

Figure 15.21 shows the PTPProducer sending messages and the PTPConsumer receiving messages.

Figure 15.21. Running the PTPProducer and PTPConsumer applications.

graphics/15fig21.gif

A Point-to-Point Client with an Asynchronous Listener

JMS Clients are not limited to blocking receive calls. Clients may create and register listeners to listen asynchronously for JMS messages. These listeners are classes that implement javax.jms.MessageListener . This interface has only one method, public void onMessage(Message msg) . Using a message listener requires a JMS consumer to first register as a listener for a specific destination with WebLogic JMS. After a message is delivered to this destination, WebLogic JMS calls the attached listener and passes the message to its onMessage() method, which is then processed by the consumer to that destination.

The following code sample shows how a listener implements MessageListener , which is a local class:

 
 // Start the Queue qCon.start() ; class Listener implements MessageListener { public void onMessage( Message msg ) { try { System.out.println(((TextMessage)msg).getText()) ; } catch (JMSException ex) { System.out.println(ex); } } } qReceiver.setMessageListener(new Listener()) ; while(true); 

Listing 15.4 shows the PTPConsumerAsync JMS application with a complete implementation of the asynchronous listener.

Listing 15.4 The PTPConsumerAsync Application
 import javax.naming.*; import javax.jms.*; import java.util.*; public class PTPConsumerAsync { private final static String NAMING_FACTORY= "weblogic.jndi.WLInitialContextFactory"; private final static String QCON_FACTORY="javax.jms.QueueConnectionFactory"; private final static String MESSAGE_QUEUE="book.jms.BookQueue"; public static void main ( String[] argv ){ try { // Create a JNDI initial context Properties props = new Properties() ; props.put( Context.INITIAL_CONTEXT_FACTORY, NAMING_FACTORY); props.put( Context.PROVIDER_URL, "t3://localhost:7001"); InitialContext ic = new InitialContext(props); // Look up a Connection Factory in JNDI QueueConnectionFactory qCF = (QueueConnectionFactory)ic.lookup(QCON_FACTORY); // Create a Connection QueueConnection qCon = qCF.createQueueConnection(); // Create a Session QueueSession qSession = qCon.createQueueSession(false,Session.AUTO_ACKNOWLEDGE); // Look up the Queue Queue queue = (Queue)ic.lookup(MESSAGE_QUEUE); // Create a QueueReceiver bound to the Queue QueueReceiver qReceiver = qSession.createReceiver(queue); // Start the Queue, send, and close qCon.start() ; class Listener implements MessageListener { public void onMessage( Message msg ) { try { System.out.println(((TextMessage)msg).getText()); } catch (JMSException ex) { System.out.println(ex); } } } qReceiver.setMessageListener(new Listener()); while(true); } catch ( NamingException e1 ) { System.out.println(e1); } catch ( JMSException e2 ) { System.out.println(e2); } } } 

Alternatively, an easier and more scalable means to receiving asynchronous messages is by configuring JMS Session Pools (a WebLogic JMS feature), which can receive messages from a destination and forward them to a server-side message listener class that you provide to process messages. The message listener class processes the message through a single-threaded onMessage() method. It is important to note that the message listener class does not need to implement the code to create server objects, such as connection factories and sessions, because they are created by the Session Pool. For example, Listing 15.5 provides the code for a simple SessionConsumer class that can be used in conjunction with JMS Session Pools.

Listing 15.5 The SessionConsumer Class
 import javax.jms.*; public class SessionConsumer implements MessageListener { public void onMessage( Message msg ) { try { System.out.println(((TextMessage)msg).getText()); } catch (JMSException ex) { System.out.println(ex); } } } 

After you have compiled your message listener class, it is important you deploy it to the WebLogic classpath. You can also modify your operating system or WebLogic classpath variable to include the directory where your class files reside.

To create a WebLogic session pool using the Administration Console, follow these steps:

  1. Click the Session Pools node under your JMS server node in the left pane.

  2. Click the Configure a New JMS Session Pool link in the right pane.

  3. In the displayed Configuration tab, enter values for the following attributes:

    • Name: Enter a name for your server session pool.

    • Connection Factory: Enter the connection factory the server session pool will be associated with to create sessions.

    • Listener Class: Enter the name of your message listener (consumer) class used to receive and process messages concurrently.

    • Acknowledge Mode: Enter the acknowledge mode used for non-transacted sessions. Select the default, Auto.

    • Sessions Maximum: Enter the maximum number of concurrent sessions enabled for this session pool.

    For example, Figure 15.22 shows the session pool configuration to use the default WebLogic connection factory and the SessionConsumer class as the message listener class.

    Figure 15.22. Configuring a JMS Session Pool.

    graphics/15fig22.jpg

  4. Click Create to create your session pool.

After you have defined a session pool, you must configure one or more connection consumers (queues or topics) that will be used to retrieve server sessions and process messages. To configure connection consumers using the Administration Console, follow these steps:

  1. Click the Consumers node under your newly created Session Pool node in the left pane.

  2. Click the Configure a New JMS Connection Consumer link.

  3. In the displayed Configuration tab, enter values for the following attributes:

    • Name: Enter the name for the connection consumer.

    • Messages Maximum: Enter the maximum number of messages that can be accumulated by the connection consumer.

    • Selector: Enter a JMS selector expression used to filter messages (optional).

    • Destination: The JNDI name for the destination on which the connection consumer will listen.

    For example, Figure 15.23 shows a session pool consumer configuration for the book.jms.BookQueue used for the PTPProducer JMS application in Listing 15.2.

    Figure 15.23. Configuring a consumer for a session pool.

    graphics/15fig23.jpg

  4. Click Create to create the session pool consumer.

To test the operation of a session pool, you can run the PTPProducer application in Listing 15.2, which will send messages to the book.jms.BookQueue . The message listener ( SessionConsumer ) class will process and output the messages to WebLogic command shell, as shown in Figure 15.24.

Figure 15.24. Testing the operation of a session pool.

graphics/15fig24.jpg

A Publish/Subscribe Producer

Pub/Sub producers need to look up a topic in JNDI as follows:

 
 // Look up the Topic Topic topic = (Topic)ic.lookup("book.jms.BookTopic"); 

The JNDI name is designated when the topic is created via the WebLogic Administration Console.

After getting the topic, a producer needs to create a TopicPublisher to actually send messages. Clients use the session to create a publisher bound to the topic:

 
 // Create a TopicPublisher bound to the Topic TopicPublisher tPublisher = tSession.createPublisher(topic); 

Next the client creates a message. In this example the client creates a TextMessage and initializes it with "Hello World!":

 
 // Create a TextMessage TextMessage mes = qSession.createTextMessage("Hello World!"); 

Finally the client starts the connection and sends the message five times. Then the client closes the connection:

 
 // Start the Queue, send, and close qCon.start(); for(int i = 0; i<5; i++) { tPublisher.publish(mes); } qCon.close(); 

Listing 15.6 is the complete PubSubProducer application.

Listing 15.6 The PubSubProducer Application
 import javax.naming.*; import javax.jms.*; import java.util.*; public class PubSubProducer { private final static String NAMING_FACTORY= "weblogic.jndi.WLInitialContextFactory"; private final static String TCON_FACTORY="javax.jms.TopicConnectionFactory"; private final static String MESSAGE_TOPIC="book.jms.BookTopic"; public static void main ( String[] argv ){ try { // Create a JNDI initial context Properties props = new Properties() ; props.put( Context.INITIAL_CONTEXT_FACTORY, NAMING_FACTORY); props.put( Context.PROVIDER_URL, "t3://localhost:7001"); InitialContext ic = new InitialContext(props); // Look up a Connection Factory in JNDI TopicConnectionFactory tCF = (TopicConnectionFactory)ic.lookup(TCON_FACTORY); // Create a Connection TopicConnection tCon = tCF.createTopicConnection(); // Create a Session TopicSession tSession = tCon.createTopicSession(false,Session.AUTO_ACKNOWLEDGE); // Look up the Topic Topic topic = (Topic)ic.lookup(MESSAGE_TOPIC) ; // Create a TopicPublisher bound to the Topic TopicPublisher tPublisher = tSession.createPublisher(topic); // Create a TextMessage TextMessage mes = tSession.createTextMessage("Hello World!"); // Start the Topic, send the message, and close the topic tCon.start() ; for(int i = 0; i<5; i++ ) { tPublisher.publish(mes); System.out.println(" Sending Hello World - " + i + " to the JMS Topic"); } tCon.close() ; } catch ( NamingException e1 ) { System.out.println(e1); } catch ( JMSException e2 ) { System.out.println(e2); } } } 

A Publish/Subscribe Consumer

Pub/Sub consumers share the basic steps with Pub/Sub producers. The differences begin after acquiring a topic. A Pub/Sub consumer must get a TopicSubscriber to interact with the topic:

 
 // Create a TopicSubscriber bound to the Topic TopicSubscriber tSubscriber = tSession.createSubscriber(topic); 

The Pub/Sub consumer uses a blocking read in an endless loop to receive messages from the queue. Listing 15.7 is the entire PubConsumer application.

Listing 15.7 The PubSubConsumer Application
 import javax.naming.*; import javax.jms.*; import java.util.*; public class PubSubConsumer { private final static String NAMING_FACTORY= "weblogic.jndi.WLInitialContextFactory"; private final static String TCON_FACTORY="javax.jms.TopicConnectionFactory"; private final static String MESSAGE_TOPIC="book.jms.BookTopic"; public static void main ( String[] argv ){ try { // Create a JNDI initial context Properties props = new Properties() ; props.put( Context.INITIAL_CONTEXT_FACTORY, NAMING_FACTORY); props.put( Context.PROVIDER_URL, "t3://localhost:7001"); InitialContext ic = new InitialContext(props); // Look up a Connection Factory in JNDI TopicConnectionFactory tCF = (TopicConnectionFactory)ic.lookup(TCON_FACTORY); // Create a Connection TopicConnection tCon = tCF.createTopicConnection(); // Create a Session TopicSession tSession = tCon.createTopicSession(false,Session.AUTO_ACKNOWLEDGE); // Look up the Topic Topic topic = (Topic)ic.lookup(MESSAGE_TOPIC); // Create a TopicSubscriber bound to the Topic TopicSubscriber tSubscriber = tSession.createSubscriber(topic); // Start the Topic, send the message, and close the topic tCon.start() ; TextMessage msg; while( true ) { msg = (TextMessage)tSubscriber.receive(); System.out.println(msg.getText()) ; } } catch ( NamingException e1 ) { System.out.println(e1); } catch ( JMSException e2 ) { System.out.println(e2); } } } 

To run the PubSubProducer and PubSubConsumer JMS applications:

  1. Compile the respective Java files using the javac utility.

  2. Start WebLogic Server and ensure you have a JMS server configured with a JMS Topic identified through the JNDI name "book.jms.BookTopic".

    Note

    The examples use the default WebLogic ConnectionFactory so no other WebLogic Server configuration is required to run these examples.

  3. Start a command shell for each of the JMS applicationsPubSubProducer and multiple PubSubConsumers, and also set the appropriate Java environments in each shell session.

  4. Launch the PubSubProducer and PubSubConsumer JMS Applications through the following commands in their respective command shell sessions:

       
      java PubSubProducer java PubSubConsumer  

Figure 15.25 shows both the PubSubProducer and three PubSubConsumer applications. All the consumers receive all the messages placed in the topic.

Figure 15.25. Running the PubSubProducer and PubSubConsumer Applications.

graphics/15fig25.gif

Message Selectors

Not all JMS clients need every message on a queue or topic. Clients may create QueueReceiver or TopicSubscriber objects with message selectors. A message selector acts as a filter to control which messages get delivered. Message selectors are SQL-like clauses that evaluate to true or false. If a selector is true the message will be delivered. Selector expressions may use standard JMS headers or optional properties, including user settable properties, to use in the Boolean evaluation. Message selectors cannot filter a message based upon the contents of the message body.

The PubSubProducer application (refer to Listing 15.5) can be adapted to set an optional property field. In this case each text message will get a message number. The name of the property is mesnum :

 
 // set the mesnum property for selectors mes.setIntProperty("mesnum",i); 

A subscriber, such as the PubSubConsumer application in Listing 15.6, that only wanted messages 0 and 1 would need to define a selector like "mesnum=0" or "mesnum=1", which would be a command-line parameter to the application ( argv[0] ):

 
 // Create a TopicSubscriber bound to the Topic TopicSubscriber tSubscriber = tSession.createSubscriber(topic,argv[0],true); 

The createSubscriber method takes a topic, selector, and a flag. The flag indicates whether to ignore messages that may be sent by this client.

Figure 15.26 shows the output of the modified PTPProducer and PTPConsumer applications, PubSubPFilter (Producer) and PubSubCFilter (Consumer). PubSubPFilter creates five text messages with the property mesnum set to 0 through 4. PubSubCFilter has been started two times with different message selectors.

Figure 15.26. Running the PubSubPFilter and PubSubCFilter applications.

graphics/15fig26.gif



BEA WebLogic Platform 7
BEA WebLogic Platform 7
ISBN: 0789727129
EAN: 2147483647
Year: 2003
Pages: 360

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net