级别: 初级 Sheldon Wosnick (swosnick@ca.ibm.com), 顾问软件开发者, IBM WebSphere Studio Application Developer
2003 年 3 月 01 日 本教程将简单地演示涉及消息驱动 bean(message-driven bean,MDB)的点对点(Point to Point,P2P)和发布和预订(Publish and Subscribe,Pub/Sub)消息传递,为此,本教程将为您描述构造相当简单但又很全面的测试案例的过程,该案例涉及单个 MDB 和两个分开的、无状态的会话 bean 客户机。
© Copyright International Business Machines Corporation 2003. All rights reserved.
介绍
本教程将简单地演示涉及消息驱动 bean(message-driven bean,MDB)的点对点(Point to Point,P2P)和发布和预订(Publish and Subscribe,Pub/Sub)消息传递,为此,本教程将为您描述构造相当简单但又很全面的测试案例的过程,该案例涉及单个 MDB 和两个分开的、无状态的会话 bean 客户机。一个无状态的会话 bean 客户机使用 P2P 方法来发送消息,另一个使用 Pub/Sub 方法来发布消息。WebSphere® Studio Application Developer(以下简称为 Application Developer)V5.0 中的 MQ Simulator for Java Developers(MQ Simulator)支持这两种方法。您可以
下载所有的源代码,这些代码在多个可直接运行的部署模块中。
背景
J2EE 1.3 引入了这样一个要求:应用程序服务器需带有本机的 Java 消息传递服务(Java Messaging Service,JMS)提供程序。为了符合这些要求,WebSphere Application Server V5 现在带有本机的 JMS 提供程序,该提供程序构建在 WebSphere MQ 技术的基础上,它通过持久和非持久的消息来支持 P2P 和 Pub/Sub,使应用程序有机会使用进程间和基于网络的连接性进行连接。WebSphere Studio V5 还提供本机 JMS 提供程序的嵌入式版本以使该版本能和集成测试环境(被称为 MQ Simulator)一起被使用。本文并不深入讨论 JMS 提供程序。如果您想找关于 Application Developer 中的 JMS 和 MDB 的优秀的入门读物,请阅读这篇文章:
使用 WebSphere Studio Application Developer 5.0 创建和测试消息驱动 Bean(这是本教程的补充教材)。
MQ Simulator 是 Application Developer V5.0 中的新的功能部件。它是纯粹的 Java,也是占用较少内存的本机 JMS 提供程序,它能和集成测试环境一起被使用从而使开发者能够快速地切换,因为它提供了不必额外地在开发机器上安装 WebSphere MQ 或 WebSphere Application Server 就能对 JMS 应用程序进行单元测试的能力。通过提供完全集成的测试环境和 MQ Simulator,Application Developer 使您拥有一个可配置的、独立的测试环境。当然,已开发的应用程序可被部署到企业基础结构并进行测试而不必作任何修改,但是有了 MQ Simulator 就意味着开发和测试的速度比在真实的环境中快得多从而缩短了开发周期。
为了使它成为轻量级的模拟器,它不支持持久性或进程间通信。在 JVM 的持续时间里,需要这些的功能部件(例如 XA 和持久订户)被模拟。例如,它不支持在应用程序服务器 JVM 进程之外运行的客户机,该进程总是涉及某种进程间通信。然而,出于同样的原因,它支持 EJB、servlet 或 JSP 客户机 ? 实际上,任何可在 MQ Simulator 运行所在的相同的 JVM 进程中运行的客户机,还有符合这一限制的任何种类的基于 JMS 的应用程序。由于它不支持持久性,所以所有运行时被创建和使用的 JMS 资源在应用程序服务器被关闭后就不存在了。
虽然这看起来是较大的限制,因为所有的消息被保存在相同的进程空间内的内存中,但是出于这些原因它能很好地运行并且很适合于单元测试。请注意您的应用程序不必实现或引导任何特定于 MQ 的代码,而且您的应用程序可在任何符合 JMS 的系统(无论是 WebSphere MQ 还是某些其它消息传递系统)上运行而不必作修改,这一点很重要。此外,除了 Application Developer 本身外,您不需要任何其它东西(例如“真正的”WebSphere MQ 系统),因为一切都是独立的且可以直接运行。
重要:MQ Simulator 仅适用于 WebSphere Application Server V5
测试服务器实例,
不适用于(或者说不支持)WebSphere Application Server V4 服务器实例。所以,您必须象随后的演示那样创建 WebSphere Application Server V5 服务器实例和配置。此外,您需要 Application Developer V5.0 的
GA版本,因为测试版中没有 MQ Simulator。MQ Simulator 是为用于 Application Developer 的单元测试环境而
特别设计的,如果在本机 WebSphere Application Server 上启用它,那么它将无法正常运行。虽然这些限制(在进程中运行但没有持久性)对于测试环境来说是完全可以忍受的,但它对于生产系统来说是不可想象的。
您将完成的开发步骤
您将完成以下步骤:
-
为 MDB 创建和配置 EJB 项目
-
为了调用发送和发布而创建 MDB 测试器项目和两个会话 bean
-
创建和实现在会话 bean 中发送和发布消息的方法
-
实现 MDB 中的 onMessage() 方法
-
为会话 bean 测试器生成部署 RMIC 代码
-
创建和配置单元测试环境服务器实例和配置
-
为 MDB 添加 EJB 资源引用
-
为那两个会话 bean 添加资源引用
-
运行和测试 EJB bean
-
导入 EAR 文件和服务器配置(可选)
从 J2EE 透视图中的 J2EE 层次结构看,您完成的 J2EE 环境应与下面的图 1 相似:
图 1. 完成的 J2EE 环境
1. 为 MDB 创建和配置 EJB 项目
- 在名为 DefaultEAR 的企业应用程序项目中创建名为 SimpleMDB 的新的 EJB 2.0 项目。
- 为了创建名为 SimpleMessage 的新的消息驱动 bean,请选择消息驱动 bean 并输入以下属性(请参见下面的图 2):
- Bean name:SimpleMessage
- Source folder:ejbModule
- Default package:com.yourcomp
图 2. 创建消息驱动 bean
- 请把 Transaction type 和 Destination Type 分别指定为 Container 和 Queue。
- 请指定名为 SimpleListenerPort 的侦听器端口。
- 请单击
Finish(请参见图 3)。
图 3. 指定 Transaction type、Destination Type 和 ListenerPort
- 为了查看您在向导中指定的值,请打开 SimpleMessage bean 的 EJB 部署描述符。本教程演示 P2P 和 Pub/Sub,但是对于两者来说,MDB 本身是相同的,您可以使用相同的侦听器端口(请参见下面的图 4)。
图 4. SimpleMessage bean 的 EJB 部署描述符
2. 为了调用发送和发布而创建 MDB 测试器项目和两个会话 bean
- 请在新的企业应用程序项目中创建名为 MDBTester 的新的、不同的 EJB 项目。该项目包括两个您创建的普通的无状态的会话 bean:SimpleSender 和 SimplePublisher(请参见下面的图 5)。
图 5. 创建 MDBTester EJB 项目
并不存在针对以这种方式来实现我们的测试方案的 MQ Simulator 限制或约束 ? 我们也可以在单个 EAR 或 EJB 模块中创建所有的 EJB 或使用 servlet 或 JSP。然而,令人感兴趣的是向队列发送消息的会话 bean 所在的模块与从队列中获取消息的 MDB 完全不同。这样,您可以分离业务逻辑和测试 bean,还可把测试代码再次用于其它 MDB。
- 现在,为了在 MDBTester 项目中创建名为 SimpleSender 的无状态的会话 bean,请选择 Session bean 并输入这些属性(请参见下面的图 6):
- Bean name:SimpleSender
- Source folder:ejbModule
- Default package:com.yourcomp.test
图 6. 在 MDBTester 项目中创建无状态的会话 bean SimpleSender
- 请接受缺省值 stateless 和 container 以提高性能并降低网络开销,在不必要的情况下(如同这里),您只需指定 Local client view。对于 CMP 2.0 bean 来说,EJB 规范规定缺省接口是本地接口(“Local client view”),该接口与 CMP 2.0 一起被引入,它有助于减少由相同容器中的 EJB 之间的调用所产生的网络流量和其它开销。在本地接口以前,唯一的选择是远程接口,即使调用发生在一个容器中的 bean 之间也会增加开销。
- 请在 CMP 属性部分中接受缺省值,然后单击
Add(请参见图 7)。
图 7. 选择 Session type、Transaction type 和其它详细信息
3. 创建和实现在会话 bean 中发送和发布消息的方法
- 请在 SimpleSenderBean 中创建包含以下代码的新方法 sendMessage()。请注意队列名和连接工厂名没有直接指定 JNDI 名称,而是使用了 J2EE 约定
java:comp/env 。请参阅
Best Practice: Use Java:comp to Locate EJBs and Increase Application Portability,其中详细地讨论了为什么您应该在 J2EE 应用程序中把 Java:comp/env 用于 EJB 或任何有关的 JNDI 资源。
<samp>
清单 1</samp>
<tt>package com.yourcomp.test;
import javax.jms.*;
import javax.naming.*;
Import javax.naming.directory.*;
Import javax.rmi.PortableRemoteObject;
public class SimpleSenderBean implements javax.ejb.SessionBean {
QueueConnectionFactory queueConnectionFactory = null;
QueueConnection queueConnection = null;
Queue queue = null;
QueueSender queueSender = null;
QueueSession queueSession = null;
String connectionFactoryName = "Java:comp/env/Simple/jms/SimpleQCF";
String queueName = "Java:comp/env/Simple/jms/SimpleQ";
String message = "My Very Simple Message";
int numMessages = 5;
...
public void sendMessage() {
try {
System.out.println("Getting
an Intial Context ...");
Context ctx = new
InitialContext();
System.out.println("Getting
an QueueConnectionFactory ...");
queueConnectionFactory
=
(QueueConnectionFactory) PortableRemoteObject.narrow(
ctx.lookup(connectionFactoryName),
QueueConnectionFactory.class);
System.out.println(
"Got the QueueConnectionFactory: " + queueConnectionFactory);
System.out.println("Getting
a QueueConnection ...");
queueConnection
= queueConnectionFactory.createQueueConnection();
System.out.println("Got
the QueueConnection: " + queueConnection);
System.out.println("Getting
a QueueSession ...");
boolean transacted
= false;
queueSession =
queueConnection.createQueueSession(
transacted,
QueueSession.AUTO_ACKNOWLEDGE);
System.out.println("Got
the QueueSession: " + queueSession);
System.out.println("Getting
a Queue ...");
queue =
(Queue) PortableRemoteObject.narrow(
ctx.lookup(queueName),
Queue.class);
System.out.println("Got
the Queue: " + queue);
System.out.println("Getting
a QueueSender ...");
queueSender = queueSession.createSender(queue);
System.out.println("Got
the QueueSender: " + queueSender);
System.out.println("***
Sending the messages now ***");
for (int i = 1;
i < numMessages + 1; i++) {
Message theMessage = null;
System.out.println("Sending text message #" + i);
theMessage = queueSession.createTextMessage(message + " #" + i);
queueSender.send(theMessage);
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
if (queueConnection
!= null) {
try {
System.out.println(
"Closing the QueueSession and the QueueConnection
now.");
queueSession.close();
queueConnection.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
}</tt>
|
- 请把 sendMessage() 方法提升到本地接口。您可以不使用远程接口而使用在 EJB 2.0 中新增加的本地接口以减少一个 EJB 容器中的网络流量从而提高 EJB 之间的调用的吞吐量和性能(请参见图 8)。
图 8. 把 sendMessage() 方法提升为本地接口
- 类似地,对于 SimplePublisher,请把适当的 Pub/Sub JMS 实现用于建立主题会话和连接。
清单 2
<tt>
package com.yourcomp.test;
import javax.jms.*;
Import javax.naming.*;
Import javax.naming.directory.*;
Import javax.rmi.PortableRemoteObject;
public class SimplePublisherBean implements javax.ejb.SessionBean {
TopicConnectionFactory topicConnectionFactory = null;
Topic topic = null;
TopicPublisher topicPublisher = null;
TopicSession topicSession = null;
TopicConnection topicConnection = null;
String connectionFactoryName = "Java:comp/env/Simple/jms/SimpleTCF";
String topicName = "Java:comp/env/Simple/jms/SimpleT";
String outString = "Simple Topic Message";
private javax.ejb.SessionContext mySessionCtx;
...
public void publishMessage() {
try {
System.out.println("Getting
an Intial Context ...");
Context ctx = new
InitialContext();
System.out.println("Getting
an TopicConnectionFactory ...");
topicConnectionFactory
=
(TopicConnectionFactory) ctx.lookup(connectionFactoryName);
topic = (Topic)
ctx.lookup(topicName);
System.out.println(
"Got the TopicConnectionFactory: " + topicConnectionFactory);
System.out.println("Getting
a TopicConnection ...");
topicConnection
= topicConnectionFactory.createTopicConnection();
System.out.println("Got
the TopicConnection: " + topicConnection);
System.out.println("Starting
the TopicConnection ...");
topicConnection.start(); System.out.println("Getting
a TopicSession ...");
Boolean transacted
= false;
topicSession = topicConnection.createTopicSession(transacted,
Session.AUTO_ACKNOWLEDGE);
System.out.println("Got
the TopicSession: " + topicSession);
System.out.println("Getting
a TopicPublisher ...");
topicPublisher =
topicSession.createPublisher(topic);
System.out.println("Got
the TopicPublisher: " + topicPublisher);
System.out.println("Creating
a TextMessage ...");
TextMessage outMessage
= topicSession.createTextMessage(outString);
System.out.println(
"Publish the message to: " + topic.getTopicName());
topicPublisher.publish(outMessage);
try {
topicPublisher.close();
} catch (JMSException
e) {
System.out.println("Whoops! Threw a JMSException: " + e);
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
if (topicConnection
!= null) {
try {
System.out.println(
"Closing the TopicSession and the TopicConnection
now.");
topicSession.close();
topicConnection.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
}
</tt>4. 把
publishMessage() 方法提升为本地接口。
|
4. 实现 MDB 中的 onMessage() 方法
- 请用与下列代码类似的代码来实现 SimpleMDB 的 onMessage() 方法(必须承认这些代码不同于有实用价值的代码,但愿它能说明要点):
<samp>
清单 3</samp>
<tt>package com.yourcomp;
import javax.jms.*;
Import javax.naming.*;
Import javax.naming.directory.*;
Import javax.rmi.PortableRemoteObject;
public class SimpleMessageBean
implements javax.ejb.MessageDrivenBean, javax.jms.MessageListener
{
</tt><tt>
...
public void onMessage(javax.jms.Message msg) {
try {
System.out.println("Invoking
MDB onMessage() now.");
System.out.println("Message
Object is: " + MSG);
System.out.println("Text
message is: " + ((TextMessage)MSG).getText());
System.out.println();
}
catch (JMSException e) {
System.out.println("Whoops!
A JMSException occurred: " + e);
e.printStackTrace();
}
}</tt>
|
- 因为 MDB 不需要特别的部署代码,所以您不必再做任何事就可以创建和使用 MDB 以用于有用的工作。所有您真正需要做的就是至少实现 bean 中的 onMessage() 方法。
5. 为会话 bean 生成部署和 RMIC 代码
生成部署和 RMIC 代码以及用于 SimpleSender 和 SimplePublisher bean 的代码。前面已讲过,没有必要生成部署代码,因为只要有 onMessage() 方法和适当的部署描述符,消息驱动 bean 就可被使用。客户机并不通过接口来访问消息驱动 bean,一个消息驱动 bean 仅有一个 bean 类(请参见图 9)。
图 9. 生成部署和 RMIC 代码
6. 创建和配置单元测试环境服务器实例和配置
- 请在名为 Server Project(这个名称够简单的)的文件夹(也就是说这是个服务器项目)中创建名为 MyTestServer 的新的 WebSphere Application Server V5 测试环境服务器和配置(请参见图 10)。
图 10. 创建新的服务器和服务器配置
- 请把 DefaultEAR 和 MDBTesterEAR 添加到 MyTestServer 服务器配置(请参见图 11)。
图 11. 把 DefaultEAR 和 MDBTesterEAR 添加到服务器配置
- 添加新的 WASQueueConnectionFactory 和 WASQueue。您最好总是在提供应用程序分离的个别的服务器级别上配置而不是在单元或节点级别上配置。所以,请添加以下 JMS 资源,这些资源将扩展 MyTestServer 服务器的服务器配置编辑器的 JMS 选项卡上的服务器部分。请编辑 WebSphere JMS 提供程序选项页面。
- 请单击
Add,然后通过输入这些值或接受缺省值来添加新的 WASQueConnectionFactory(请参见图 12):
图 12. 添加带有这些指定值的新的 WASQueConnectionFactory
- 请添加带有这些值的新的 WASQueue 或接受缺省值(请参见图 13):
图 13. 添加带有这些指定值的新的 WASQueue 的屏幕快照
- 在同一个 JMS 页面上,请确保 JMS 服务器的初始状态被设为 START,因为在您创建服务器配置时它被缺省地设为 STOP。请把 JMS 服务器的初始状态设为 START(请参见图 14)。
图 14. 把 JMS 服务器的初始状态设为 START
- 请把名为 SimpleQ 的队列名添加到 JMS 服务器(请参见图 15)。
图 15. 把队列名添加到 JMS 服务器
- 请添加新的 WAS 主题连接工厂和 WAS 主题。对于 Pub/Sub 测试,您需要添加 TopicConnectionFactory 和 Topic。
请找到 WASTopicConnectionFactory 部分,然后单击
Add,再输入这些值或接受缺省值(请参见图 16):
图 16. 添加新的 WASTopic 连接工厂
- 请添加带有这些值的新的 WASTopic 或接受缺省值(请参见图 17):
图 17. 添加新的 WASTopic
- 完成后,队列、主题连接和目的地出现在列表中(请参见图 18)。
图 18. 列出的队列、主题连接和目的地
- 请添加新的侦听器端口。在服务器配置编辑器的 EJB 选项卡的侦听器端口部分,请添加新的侦听器端口,其名称与先前为 MDB 中的侦听器端口指定的名称相匹配。Application Developer 的 Early Availability 发行版中没有这里所说的配置侦听器端口的功能,所以,为了使用这一功能,您需要 GM 版本。
由于我们使用了名称 SimpleListenerPort,所以您还需要在这里指定这个名称。请单击
Add按钮,然后指定以下这些值并接受缺省值;否则,请单击
OK并保存服务器配置(请参见图 19)。
图 19. 添加新的侦听器端口
- 请把 DefaultEAR 和 MDBTester EAR 模块添加到服务器配置中(请参见图 20)。
图 20. 把 DefaultEAR 和 MDBTester EAR 模块添加到服务器配置中
- 请确保两个应用程序模块(DefaultEAR 和 MDBTesterEAR)被添加到相同的服务器配置中(请参见图 21)。
图 21. 把两个应用程序模块添加到相同的服务器配置中
7. 为 MDB 添加 EJB 资源引用
您需要资源引用以使不同的模块可以访问共同的资源。在这种情况下,资源是连接工厂、主题和队列,它们被绑定到 WebSphere Application Server 在运行时使用的特定的 JNDI 名称。请打开 SimpleMessage bean 的 EJB 部署描述符编辑器。请通过单击
ejb-jar.xml 文件来打开它。
- 请添加资源环境引用,您将为队列类型命名 ResourceEnvRef,把 JNDI 名设为 jms/simpleQ(请参见图 22)。
图 22. 添加资源环境引用
- 添加了引用后,条目应与下图相似(请参见图 23):
图 23. 添加了资源环境引用后条目模样的示例
- 现在请把外部资源的 EJB 资源引用添加到队列连接工厂。
图 24. 添加外部资源的 EJB 资源引用
添加了引用后,现在条目应与下面的图 25 相似:
图 25. 引用被添加后条目的示例
8. 为那两个会话 bean 添加资源引用
现在,您需要添加 MDBTester bean(SimpleSender 和 SimplePublisher)的相同类型的资源引用。
- 请添加 SimplePublisher 和 SimpleSender 的 EJB 资源引用。
图 26. 添加 SimplePublisher 和 SimpleSender 的 EJB 资源引用
- 下面的四张图形象地说明了四组值。您应该确保它们被正确地设置,前两组是关于 SimpleSender,后两组是关于 SimplePublisher。要点是保持您使用的 JNDI 名称的一致性以确保所有的引用通过相同的 JNDI 名称指向相同的资源且资源的正确类型被指定 ? 这四个主要的 JMS 资源类型中的每一个都包括:Queue、QueueConnectionFactory、Topic 和 TopicConnectionFactory。
图 27. 为 SimpleSender 设置这组值
图 28. 为 SimpleSender 设置这组值
图 29. 为 SimplePublisher 设置这组值
图 30. 为 SimplePublisher 设置这组值
9. 运行和测试 EJB bean
您已创建了 EJB 并配置了服务器环境,现在您可以测试它执行的 MDB。您可能想在调试方式中启动服务器,然后单步执行 publishMessage 或 sendMessage() 方法。
- 请通过单击服务器透视图中的服务器视图中的跑步者来启动 WebSphere Application Server V5 服务器实例。
另外,您也可以在 EJB 或该项目上运行服务器。本文描述如何手工地启动服务器。
- 请通过右键单击服务器视图中的服务器来启动 IBM® Universal Test Client。请选择
run universal test client,然后从 Test Client 的主页中打开 JNDI Explorer。
- 请逐级打开 Local EJB beans,直到找到 JNDI 名称
ejb/com/yourcomp/test ,然后单击
SimpleSenderLocalHome,这将把您带到 EJB 页面。在该页面上,请使用 Home 接口来创建或检索 SimpleSender 的实例。
- 请返回 JNDI Explorer,对于 SimplePublisher,请完成相同的步骤。然后,您可以先使用“发送者”,接着使用“发布者”,因为您有两者的实例(如果您就是想这样做)。请参见图 31。
图 31. 创建 SimpleSender 和 SimplePublisher 的实例
- 有了 home 以后,请通过运行 SimpleSenderLocal.create() 方法来创建 SimpleSenderLocal 的实例。服务器控制台窗口应该是打开的,但是,如果未被打开,请确保打开它,因为所有的 println 将在那里输出。如果您正确地完成了以上步骤,那么您将看到来自会话 bean 和 MDB 中的 println 语句的控制台输出(请参见图 32)。
图 32. 创建 SimpleSenderLocal 的实例
对于 P2P,预期的控制台输出(您的时间和日期戳记肯定会有所不同)应当与下面的输出相似:
<tt>...
[11/17/02 9:58:05:609 EDT] 30d1bea0 SystemOut O Getting
an Intial Context ...
[11/17/02 9:58:05:609 EDT] 30d1bea0 SystemOut O Getting
an QueueConnectionFactory ...
[11/17/02 9:58:05:641 EDT] 30d1bea0 SystemOut O Got
the QueueConnectionFactory:
com.ibm.ejs.jms.JMSQueueConnectionFactoryHandle@4afbbea3
managed connection factory =
com.ibm.ejs.jms.WSJMSManagedQueueConnectionFactory@185ebebd
connection manager = com.ibm.ejs.j2c.ConnectionManager@5557ebc
restricted methods enabled = false
[11/17/02 9:58:05:641 EDT] 30d1bea0 SystemOut O Getting
a QueueConnection ...
[11/17/02 9:58:05:656 EDT] 30d1bea0 SystemOut O Got
the QueueConnection:
com.ibm.ejs.jms.JMSQueueConnectionHandle@4e897ea3
managed connection =
com.ibm.ejs.jms.JMSManagedQueueConnection@4b2cfea3
physical connection = com.ibm.mq.jms.MQXAQueueConnection@4b11fea3
closed = false
invalid = false
restricted methods enabled = false
open session handles = []
temporary queues = []
[11/17/02 9:58:05:656 EDT] 30d1bea0 SystemOut O Gettinga QueueSession ...
[11/17/02 9:58:05:703 EDT] 30d1bea0 SystemOut O Got
the QueueSession: com.ibm.ejs.jms.JMSQueueSessionHandle@51be7ea2
managed session = com.ibm.ejs.jms.JMSManagedQueueSession@bdbbea3
state = ACTIVE
restricted methods enabled = false
open children = []
[11/17/02 9:58:05:703 EDT] 30d1bea0 SystemOut O Getting
a Queue ...
[11/17/02 9:58:05:703 EDT] 30d1bea0 SystemOut O Got
the Queue: queue:///WQ_SimpleQ
[11/17/02 9:58:05:703 EDT] 30d1bea0 SystemOut O Getting
a QueueSender ...
[11/17/02 9:58:05:734 EDT] 30d1bea0 SystemOut O Got
the QueueSender: com.ibm.ejs.jms.JMSQueueSenderHandle@2e3ea2
session handle = com.ibm.ejs.jms.JMSQueueSessionHandle@51be7ea2
message ID disabled = null
message timestamp disabled = null
delivery mode = null
priority = null
time to live = null
closed = false
queue = queue:///WQ_SimpleQ
physical queue sender = com.ibm.mq.jms.MQQueueSender@7eb3bea2
[11/17/02 9:58:05:734 EDT] 30d1bea0 SystemOut O ***
Sending the messages now ***
[11/17/02 9:58:05:734 EDT] 30d1bea0 SystemOut O Sending
text message #1
[11/17/02 9:58:05:766 EDT] 30d1bea0 SystemOut O Sending
text message #2
[11/17/02 9:58:05:766 EDT] 30d1bea0 SystemOut O Sending
text message #3
[11/17/02 9:58:05:766 EDT] 30d1bea0 SystemOut O Sending
text message #4
[11/17/02 9:58:05:766 EDT] 30d1bea0 SystemOut O Sending
text message #5
[11/17/02 9:58:05:766 EDT] 30d1bea0 SystemOut O Closing
the QueueSession and the QueueConnection now.
[11/17/02 9:58:05:828 EDT] 2207ea2 SystemOut
O Invoking MDB onMessage() now.
[11/17/02 9:58:05:828 EDT] 2207ea2 SystemOut
O Message Object is:
JMS Message class: jms_text
JMSType: null
JMSDeliveryMode: 2
JMSExpiration: 0
JMSPriority: 4
JMSMessageID: ID:414d51205741535f6c6f63616c686f730000000000000005
JMSTimestamp: 1033999085766
JMSCorrelationID:null
JMSDestination: queue:///WQ_SimpleQ
JMSReplyTo: null
JMSRedelivered: false
JMS_IBM_PutDate:20021007
JMSXAppID:Application Developer
JMS_IBM_Format:MQSTR
JMS_IBM_PutApplType:28
JMS_IBM_MsgType:8
JMSXUserID:swosnick
JMS_IBM_PutTime:13580576
JMSXDeliveryCount:1
My Very Simple Message #1
[11/17/02 9:58:05:828 EDT] 2207ea2 SystemOut
O Text message is: My Very Simple Message #1
...
</tt>
|
- 对于 SenderPublish,请完成相同的步骤。请创建新实例并调用 publishMessage() 方法(请参见图 33)。在此之前,请修改侦听器端口以使 MDB 侦听主题而不是在第 6 部分的第 11 步中设置的队列。否则,该 MDB 仍将侦听队列且不会产生您预期的输出。
图 33. 为 SenderPublish 创建新实例
对于 Pub/Sub,预期的控制台输出(您的时间和日期戳记肯定会有所不同):
<tt>[11/17/02 9:42:47:672 EDT] 76bd3cfe SystemOut
O Getting an Intial Context ...
[11/17/02 9:42:47:688 EDT] 76bd3cfe SystemOut O Getting
an TopicConnectionFactory ...
[11/17/02 9:42:47:719 EDT] 76bd3cfe SystemOut O Got
the TopicConnectionFactory:
com.ibm.ejs.jms.JMSTopicConnectionFactoryHandle@55e4fce1
managed connection factory =
com.ibm.ejs.jms.WSJMSManagedTopicConnectionFactory@3156bce6
connection manager = com.ibm.ejs.j2c.ConnectionManager@33937ce6
restricted methods enabled = false
[11/17/02 9:42:47:719 EDT] 76bd3cfe SystemOut O Getting
a TopicConnection ...
[11/17/02 9:42:47:766 EDT] 76bd3cfe SystemOut O Got
the TopicConnection: com.ibm.ejs.jms.JMSTopicConnectionHandle@35977ce0
managed connection = com.ibm.ejs.jms.JMSManagedTopicConnection@4a8bfce0
physical connection = com.ibm.mq.jms.MQXATopicConnection@4af9bce0
closed = false
invalid = false
restricted methods enabled = false
open session handles = []
temporary topics = []
[11/17/02 9:42:47:766 EDT] 76bd3cfe SystemOut O Starting
the TopicConnection ...
[11/17/02 9:42:47:766 EDT] 76bd3cfe SystemOut O Getting
a TopicSession ...
[11/17/02 9:42:47:828 EDT] 76bd3cfe SystemOut O Got
the TopicSession: com.ibm.ejs.jms.JMSTopicSessionHandle@118bce0
managed session = com.ibm.ejs.jms.JMSManagedTopicSession@400bbce0
state = ACTIVE
restricted methods enabled = false
open children = []
[11/17/02 9:42:47:828 EDT] 76bd3cfe SystemOut O Getting
a TopicPublisher ...
[11/17/02 9:42:47:859 EDT] 76bd3cfe SystemOut O Got
the TopicPublisher: com.ibm.ejs.jms.JMSTopicPublisherHandle@74867ce7
session handle = com.ibm.ejs.jms.JMSTopicSessionHandle@118bce0
message ID disabled = null
message timestamp disabled = null
delivery mode = null
priority = null
time to live = null
closed = false
topic = topic://SimpleTopic?brokerVersion=1
physical topic publisher = com.ibm.mq.jms.MQTopicPublisher@5157fce7
[11/17/02 9:42:47:859 EDT] 76bd3cfe SystemOut O Creating
a TextMessage ...
[11/17/02 9:42:47:859 EDT] 76bd3cfe SystemOut O Publish
the message to: topic://SimpleTopic?brokerVersion=1
[11/17/02 9:42:47:891 EDT] 76bd3cfe SystemOut O Closing
the TopicSession and the TopicConnection now.
[11/17/02 9:42:47:969 EDT] 6e2e7ce7 SystemOut O Invoking
MDB onMessage() now.
[11/17/02 9:42:47:984 EDT] 6e2e7ce7 SystemOut O Message
Object is:
JMS Message class: jms_text
JMSType: null
JMSDeliveryMode: 2
JMSExpiration: 0
JMSPriority: 4
JMSMessageID: ID:414d51205741535f6c6f63616c686f73000000000000000d
JMSTimestamp: 1033998167891
JMSCorrelationID:ID:414d51205741535f6c6f63616c686f730000000000000008
JMSDestination: topic://SimpleTopic?brokerVersion=1
JMSReplyTo: null
JMSRedelivered: false
JMS_IBM_PutDate:
JMSXAppID:WAS_localhost_server1
JMS_IBM_Format:MQSTR
JMS_IBM_PutApplType:26
JMS_IBM_MsgType:8
JMSXUserID:swosnick
JMS_IBM_PutTime:
JMSXDeliveryCount:1
Simple Topic Message
[11/17/02 9:42:47:984 EDT] 6e2e7ce7 SystemOut O Text
message is: Simple Topic Message
</tt>
|
- 为了调试 MDB(这大概是本方案中您最想测试的东西),请在 onMessage() 方法中设置断点并确保在调试方式中启动服务器。
10. 导入 EAR 文件和服务器配置(可选)
有些人可能不愿意从头开始编写代码,他们更愿意(可选)立刻运行应用程序以了解它的工作原理。这样做不会有问题,为此,所提供的
下载包括了这样做所需的一切。请按照以下的说明来导入 EAR 文件和服务器配置,然后为该配置创建服务器。所有的 JMS 资源和 JNDI 名称已被预先设置了,您在完成几个简单的步骤后就能运行应用程序。别忘了,本文并不教您如何设计和创建消息驱动 bean,本文只是为您介绍一下 Application Developer 中可用的 MQ 测试工具。
- 请选择
File=>
Import=>
EAR file;然后单击
Next。
- 请浏览至
DefaultEAR.ear 的路径并把它设为导入的 EAR 模块。
- 请输入项目名
DefaultEAR。请接受缺省的项目位置(请参见图 34)。
图 34. 导入 EAR 文件
- 请单击
Finish。
- 对于 MDBTesterEAR,请重复第 1 至第 4 步(使用名为 MDBTesterEAR 的企业应用程序项目)。
图 35. 为 MDBTesterEAR 导入 EAR 文件
- 您不必为 MDBTesterProject 中的 SimpleSender 和 SimplePublisher EJB 再次生成部署代码,因为
下载中包括它。
- 请选择
File=>Import=>Server Configuration;然后单击
Next。
- 请输入配置名
MyTestServer 。
- 请把文件夹设为
My Server Project ,该文件夹将被动态地创建。
- 请把
WebSphere version 5.0 Server Configuration 选为服务器配置类型。
- 请浏览至您解压缩(unzip)下载文件的位置(至
MyTestServer.wsc 目录)。
- 请单击
Finish,对于问您是否创建 My Server Project 的对话框,请回答“Yes”。请参见图 36。
图 36. 导入服务器配置
- 为了创建新的服务器实例,请选择
File=>New=>Other=>Server。单击
Next。
- 请把服务器名设置为
MyTestServer 并使用
My Server Project 文件夹。请把
WebSphere version 5.0 Test Environment 选为服务器类型。请单击
Finish。
- 请通过选择
Window=>Open Perspective=>Other=>Server来打开服务器透视图。
- 在服务器配置视图中,选择
MyTestServer;然后单击右键,把配置从没有配置改为
MyTestServer。请参见图 37。
图 37. 创建新服务器
- 象前面那样运行服务器并测试。如果您想调试代码,请在感兴趣的那部分代码中设置了断点后以调试方式运行服务器。
结束语
Application Developer V5.0 中新出现了一个非常高效的、轻量级环境,它使您能够在单元测试环境中快速测试和调试 MDB 和其它 JMS 应用程序。通过创建与应用程序服务器运行 MDB 在同一进程中运行的 EJB,本教程为您演示了在进程内的限制下使用 MQ Simulator 的一种方法。虽然 MQ Simulator 不是为生产系统设计的(或者说不支持生产系统),但是它在无需任何特定于工具或特定于供应商的代码的单元测试环境中是很有用的。对于那些受到进程内客户机的要求的制约的人来说,他们总可以在有必要的情况下通过管理客户机来把 Application Developer 配置成使用其它消息传递系统。在使用 MQ Simulator 来测试基于 JMS 的应用程序后,该应用程序可被部署到生产应用程序服务器中而不必作任何修改,而该服务器被设置成可以使用完全的 WebSphere MQ 系统或某些其它消息传递系统。
下载 | 名字 | 大小 | 下载方法 |
|---|
| SimpleMDB.zip | 57 KB | HTTP |
关于作者  | 
|  |
Sheldon Wosnick是 IBM WebSphere Studio Application Developer(属于 IBM 多伦多实验室的 Server Tools 小组)的一名顾问软件开发者。目前,他跟他的组员一起负责 WebSphere Studio Application Developer 的整个服务器运行时和单元测试环境。以前,他是 VisualAge for Java WebSphere Tools 小组的成员。有时他被亲切地称为“运行时家伙”,他为 VisualAge for Java 设计和集成了 WebSphere Test Environment 和 Apache Tomcat Test Environment,这是 VisualAge for Java 中两个深受欢迎的功能部件。他还集成了本教程中演示的 IBM MQ Simulator for Java Developers(MQ Simulator)。您可以通过
swosnick@ca.ibm.com与 Sheldon 联系。
|
对本文的评价
|