<!----><st1:city><st1:place>Enterprise</st1:place></st1:city> JavaBeans Distilled<!----><o:p></o:p>
<o:p> </o:p>
作者: Tnk Luo<o:p></o:p>
<o:p> </o:p>
第七次:
<o:p> </o:p>
消息驱动Bean(续)<o:p></o:p>
<o:p> </o:p>
JMS 应用客户程序<o:p></o:p>
To get a better idea of how JMS is used, we can create a Java application whose sole purpose is receiving and processing reservation messages. We will develop a very simple JMS client that simply prints a description of each ticket as it receives the messages. We'll assume that the TravelAgent EJB is using the TextMessage to send a description of the ticket to the JMS clients. The following code shows how the JMS application client might look:<o:p></o:p>
为更好的理解如何使用JMS,可以开发一个Java应用,其唯一的用途在于接收和处理预定消息。在这里,将开发一个非常简单的JMS客户。当该客户接收到消息时,会打印出所每张票的描述信息。假定TravelAgent EJB使用TextMessage以发送票的描述给JMS客户。下列代码显示了JMS应用客户可能的样子:<o:p></o:p>
import javax.jms.Message;<o:p></o:p>
import javax.jms.TextMessage;<o:p></o:p>
import javax.jms.TopicConnectionFactory;<o:p></o:p>
import javax.jms.TopicConnection;<o:p></o:p>
import javax.jms.TopicSession;<o:p></o:p>
import javax.jms.Topic;<o:p></o:p>
import javax.jms.Session;<o:p></o:p>
import javax.jms.TopicSubscriber;<o:p></o:p>
import javax.jms.JMSException;<o:p></o:p>
import javax.naming.InitialContext;<o:p></o:p>
<o:p></o:p>
<o:p></o:p>
public class JmsClient_1 implements javax.jms.MessageListener {<o:p></o:p>
<o:p></o:p>
public static void main(String [] args) throws Exception {<o:p></o:p>
<o:p></o:p>
if(args.length != 2)<o:p></o:p>
throw new Exception("Wrong number of arguments");<o:p></o:p>
<o:p></o:p>
new JmsClient_1(args[0], args[1]);<o:p></o:p>
<o:p></o:p>
while(true){Thread.sleep(10000);}<o:p></o:p>
<o:p></o:p>
}<o:p></o:p>
<o:p></o:p>
public JmsClient_1(String factoryName, String topicName) throws Exception {<o:p></o:p>
<o:p></o:p>
InitialContext jndiContext = getInitialContext();<o:p></o:p>
<o:p></o:p>
TopicConnectionFactory factory = (TopicConnectionFactory)<o:p></o:p>
jndiContext.lookup("TopicFactoryNameGoesHere");<o:p></o:p>
<o:p></o:p>
Topic topic = (Topic)jndiContext.lookup("TopicNameGoesHere");<o:p></o:p>
<o:p></o:p>
TopicConnection connect = factory.createTopicConnection();<o:p></o:p>
<o:p></o:p>
TopicSession session = <o:p></o:p>
connect.createTopicSession(false,Session.AUTO_ACKNOWLEDGE); <o:p></o:p>
<o:p></o:p>
TopicSubscriber subscriber = session.createSubscriber(topic);<o:p></o:p>
<o:p></o:p>
subscriber.setMessageListener(this);<o:p></o:p>
<o:p></o:p>
connect.start();<o:p></o:p>
}<o:p></o:p>
<o:p></o:p>
public void onMessage(Message message) {<o:p></o:p>
try {<o:p></o:p>
<o:p></o:p>
TextMessage textMsg = (TextMessage)message;<o:p></o:p>
String text = textMsg.getText();<o:p></o:p>
System.out.println("\n RESERVATION RECIEVED:\n"+text);<o:p></o:p>
<o:p></o:p>
} catch(JMSException jmsE) {<o:p></o:p>
jmsE.printStackTrace();<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
<o:p></o:p>
public static InitialContext getInitialContext() {<o:p></o:p>
// 创建具体产品厂商的JNDI上下文<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
JmsClient_1的构建器含有来自JNDI InitialContext的TopicConnectionFactory和Topic。这些对象是使用具体厂商产品的properties创建的,从而使得客户能够连接到TravelAgent EJB使用的同一JMS供应者。比如,WebLogic应用服务器中getInitialContext()方法的代码如下:(JNDI也允许将properties放置在jndi.properties文件中,该文件包含有用于InitialContext的property值,并能够在运行时被动态找到。本书中,显式的给出了properties值。)<o:p></o:p>
public static InitialContext getInitialContext() {<o:p></o:p>
Properties env = new Properties();<o:p></o:p>
env.put(Context.SECURITY_PRINCIPAL, "guest");<o:p></o:p>
env.put(Context.SECURITY_CREDENTIALS, "guest");<o:p></o:p>
env.put(Context.INITIAL_CONTEXT_FACTORY,<o:p></o:p>
"weblogic.jndi.WLInitialContextFactory");<o:p></o:p>
env.put(Context.PROVIDER_URL, "t3://localhost:7001");<o:p></o:p>
return new InitialContext(env);<o:p></o:p>
}<o:p></o:p>
一旦客户获得了TopicConnectionFactory和Topic,就可以采取和TravelAgent EJB相同的方式创建TopicConnection和TopicSession。它们的主要区别在于这里的TopicSession对象创建了TopicSubscriber对象,而不是TopicPublisher。其中,TopicSubscriber被明确设计成处理来自特定Topic的消息:<o:p></o:p>
TopicSession session = <o:p></o:p>
connect.createTopicSession(false,Session.AUTO_ACKNOWLEDGE); <o:p></o:p>
<o:p></o:p>
TopicSubscriber subscriber = session.createSubscriber(topic);<o:p></o:p>
<o:p></o:p>
subscriber.setMessageListener(this);<o:p></o:p>
<o:p></o:p>
connect.start();<o:p></o:p>
TopicSubscriber能直接接收消息,或者能够将消息的处理委派给接口javax.jms.MessageLister。在例子中,JmsClient_1实现了MessageListener接口,使得它可以处理消息。MessageListener对象实现了单一的方法,onMessage(),每当新消息发送到订阅者的topic中时,该方法都会被调用。在这里,每次TravelAgent EJB发送预定消息到topic中时,JMS客户中的onMessage()方法都会被调用,使得它能够接收到消息的拷贝并处理它:<o:p></o:p>
public void onMessage(Message message) {<o:p></o:p>
try {<o:p></o:p>
TextMessage textMsg = (TextMessage)message;<o:p></o:p>
String text = textMsg.getText();<o:p></o:p>
System.out.println("\n RESERVATION RECIEVED:\n"+text);<o:p></o:p>
<o:p></o:p>
} catch(JMSException jmsE) {<o:p></o:p>
jmsE.printStackTrace();<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
待续。。。。。。。。
<o:p> </o:p>
(作者其它文章:http://www.csdn.net/develop/author/netauthor/worldheart/ )