This topic discusses how to send JMS messages to be processed by message-driven beans from page flows, web services, and EJBs. It contains the following sections:
Note. This topic discusses only how to use JMS in the context of EJBs, page flows, and web services. To learn more about the JMS API, see your favorite J2EE book or the Java documentation at http://java.sun.com.
In WebLogic you can use a JMS control to send JMS messages to a topic or queue. JMS controls can be used to send messages in page flows and web services; they cannot be used to send JMS messages in EJBs. You can use JMS controls to both send and receive messages. In this case you will only be using the JMS control to send messages, as a message-driven bean will be used to process received messages. For details on how to create JMS controls for topics and queues, see JMS Control.
The advantage of using a JMS control is that the details of the JMS messaging API are by and large taken care of by the JMS control. For example, the following code samples shows the definition of a JMS control to send messages to a queue:
/** * @jc:jms send-type="queue" send-jndi-name="jms.SamplesAppMDBQ" * connection-factory-jndi-name="weblogic.jws.jms.QueueConnectionFactory" */ public interface sendToQueueControl extends JMSControl, com.bea.control.ControlExtension { /** * this method will send a javax.jms.Message to send-jndi-name */ public void sendJMSMessage(Message msg); static final long serialVersionUID = 1L; }
As the definition shows, you must still define the name of the queue to which to send the JMS message as well as the name of a QueueConnectionFactory. However, to send a message using this JMS control, you simply need to invoke the method sendJMSMessage and pass a message as the parameter. The JMS control handles the creation of a factory instance, a connection, session, and so forth.
When using a JMS control from a page flow or web service, you can use a built-in control to encapsulate all the message sending related logic, instead of defining this directly in the page flow or web service. For instance, the following built-in control code snippet uses the JMS control defined above to send 20 messages at one time to a queue.
... public class MessageSenderImpl implements MessageSender, ControlSource { /** * @common:control */ private messageDriven.sendToQueueControl queueSend; /** * @common:operation * @common:message-buffer enable="true" */ public void add20ViaQueue(int currentNum) throws JMSException { String name; for(int i = 0; i < 20; i++) { MapMessage msg = queueSend.getSession().createMapMessage(); msg.setStringProperty("Command", "Add"); name = Integer.toString(currentNum + i); msg.setString("tokenName", name); queueSend.sendJMSMessage(msg); } } }
For more information on built-in controls, see Building Custom Java Controls. The use of JMS controls and built-in controls in a page flow is demonstrated in the Message-Driven Bean Sample.
To send JMS message from an EJB, you cannot use JMS controls and must use the 'standard' JMS messaging API. (You can also use the standard messaging API in page flows and web services if you do not want to use a JMS control.) The following code sample shows a session bean sending a message to a queue. The queue and QueueConnectionFactory are defined using @ejbgen:resource-env-ref and @ejbgen:resource-ref annotations. In the bean's ejbCreate method the queue and QueueConnectionFactory are located (this only need to be done once), while the method executeTask contains the correct procedure to create a connect, session, sender, and message before sending the JMS message.
/** * @ejbgen:resource-ref * auth="Container" * jndi-name = "weblogic.jws.jms.QueueConnectionFactory" * name = "jms/QueueConnectionFactory" * type="javax.jms.QueueConnectionFactory" * * @ejbgen:resource-env-ref * jndi-name="jms.ASampleJmsQ" * name="jms/ASampleJmsQ" * type = "javax.jms.Queue" * * ... */ public class ASessionBean extends GenericSessionBean implements SessionBean { private QueueConnectionFactory factory; private Queue queue; public void ejbCreate() { try { javax.naming.Context ic = new InitialContext(); factory = (QueueConnectionFactory) ic.lookup("java:comp/env/jms/QueueConnectionFactory"); queue = (Queue) ic.lookup("java:comp/env/jms/ASampleJmsQ"); } catch (NamingException ne) { throw new EJBException(ne); } } /** * @ejbgen:local-method */ public void executeTask(String prop1, String prop2) { try { //interpret the properties ... //send a message QueueConnection connect = factory.createQueueConnection(); QueueSession session = connect.createQueueSession(true,Session.AUTO_ACKNOWLEDGE); QueueSender sender = session.createSender(queue); MapMessage recordingMsg = session.createMapMessage(); recordingMsg.setString("Property1", prop1); recordingMsg.setString("Property2", prop2); sender.send(recordingMsg); connect.close(); } catch(JMSException ne) { throw new EJBException(ne); } } }
The JMS messaging API defines various message types, allowing for different types of information to be included in the body of a JMS message. Frequently used message types are TextMessage to send a text string, MapMessage to create sets of name-value pairs, and ObjectMessage to send a serializable object. For more details on the various message types, see your favorite J2EE documentation or the javax.jms.Message API documentation at http://java.sun.com.
A JMS message can also contain message properties. There are different types of properties which can serve a number of functions. One common use of a message property is to set a message selector. A message selector is a property that is used by a message-driven bean to determine whether it should process this message or should leave its processing up to another message-driven bean listening to the same topic or queue.
The following example shows how to set a String property that will act as a message selector for a JMS MapMessage:
Message msg = session.createMapMessage(); msg.setStringProperty("MyMessage", "Build 126"");
A message-driven bean that is defined to specifically process this type of message will include a message selector property:
* @ejbgen:message-driven * message-selector="MyMessage = 'Build126'" * ejb-name = MDBean * ... */ public class MDBean extends GenericMessageDrivenBean implements MessageDrivenBean, MessageListener { ...
In other words, this bean will respond specifically to this type of message and will leave the processing of other messages up to other beans listening to this topic or queue. By using a message selector you can send different types of messages to the same channel instead of having to create a separate queue/topic for every type of message. For more details on the various message properties, see your favorite J2EE documentation or the javax.jms.Message API documentation at http://java.sun.com.