跳到导航
BEA Dev2Dev Oracle and BEA
首页 资源中心 dev2dev学堂 在线技术论坛 User Group CodeShare
dev2dev 首页 > 资源中心 > 技术文章
JMSML:基于XML的标记语言 减少程序编写、监测以及测试的细节

时间:2003-07-23
作者:Kathiravan Sengodan
浏览次数:
本文关键字:JMSMLJMSJMXXML监控
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章
JMSML是一种标记语言,设计和开发它的目的在于,通过在一些简单易用的XML标签隐藏所有的JMS和JMX的Java API 的复杂性,从而使创建Java消息服务(Java Message Service,JMS)和Java管理扩展(Java Management Extensions,JMX)程序的过程更加容易。

JMS 应用:背景
典型的JMS应用程序开发过程包括在JMS提供者应用服务器上配置和管理JMS服务器组件,比如JMSConnectionFactory 和JMSDestination,以及编写使用这些服务器端管理的对象来进行Java消息传递的JMS应用客户端。

JMS应用客户端是利用JMS API编写的Java程序,并且被划分成两类程序:

  生产者:负责生成各种各样的JMS消息类型(比如Text, XML, Object, Stream, Bytes)并且把它们发送到JMS 目的地(消息队列和主题)

  消费者:负责从JMS 目的地(消息队列和主题)接收消息,即可以同步接收也可以异步接收。

JMS API是消息生产者和消费者能够使用多种服务质量(qualities of services ,QOS),它们是由底层的JMS实现和JMS提供者(比如事务和认证)提供的。

使用JMS API来编写消息生产者和消费者包括下面的几个特定步骤,而且需要按照一定顺序执行。这个过程必须对每一个为执行Java消息而编写出来的生产者和消费者重复一遍。

The JMSML方法
编写JMS应用客户端的JMSML方法不需要编写代码就能够实现。

JMS API的复杂性被抽象到了一些XML标签中,它们容易使用而且容易记忆。使用JMSML,你可以创建简单的可重用的JMS组件,比如一个"发送者", "接收者", "发布者",和 "订阅者"。除此之外,JMSML通过使用XML标签,消除了JMS API的复杂性, 使JMS server的管理变得非常简单。JMSML支持为JMS server的动态配置、管理、以及运行时管理提供服务的所有的JMX操作。

最后,JMSML通过自动验证操作和监测输出,简化了测试。

Java JMS程序是什么样子?
清单1展示了一个利用JMS API来发送文本消息"Hello World"到一个名为"exampleQueue"的JMS 队列的Java程序,它通过一个非事务支持的(nontransacted)、自动识别的(autoacknowledge)JMSSession使用了一个名为"QueueConnectionFactory"的JMSConnectionFactory(JMS连接工厂)。

JMSML程序是什么样子?
接下来的9行简单的XML代码,来自QueueSend.xml,它和清单1中QueueSend.java的74行代码作用相同。注意:借助默认的属性值,所有其它的Java JMS API细节都可以被JMSML照顾到。

1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE jmsml PUBLIC "-//BEA Systems Inc//DTD JMSML Version 1.0 JMSML//EN"
"jmsml.dtd">
3 <jmsml>
4 <operation Class="message" Type="Text" Name="MyQueueSender"
5 Factory="QueueConnectionFactory"
6 Queue="exampleQueue"
7 Body="Hello World"
8 >Send</operation>
9 </jmsml>

这种情况下,JMSML将会通过一个非事务支持的(nontransacted)、自动识别的(autoacknowledge)JMSSession创建一个QueueSender。

一旦这个操作被执行,"MyQueueSender"对象就能够被重复使用,直到程序停止运行。也就是说?quot;MyQueueSender"能够被用来向不同的消息队列发送不同的消息。


JMSML应用程序
通过前面的代码对比,你很容易就能看出JMSML容易学习和使用,而且在它功能所及的范围之内十分强大。可以在WebLogic JMS 子系统中使用JMSML来完成下面的任务。

作为WebLogic JMS子系统的一个管理和监测工具。

作为WebLogic JMS应用程序的原型工具。

作为WebLogic JMS子系统的测试工具。

使用JMSML作为测试工具
一旦JMS测试场景被确定,他们能够很容易地被转化成JMSML操作,并且被<scenario>元素包围,从而作为一个测试场景,其中的Verify属性被设置为"false"。该测试程序能够被JMSML执行模型中的某一个所执行。成功执行后,将生成一个和输入的JMSML程序同名的,后缀是.out的输出文件。需要手工验证它的正确性,然后把它保存成一个基准文件(还是和输入的JMSML程序同名,但后缀是.bmk)。

在这之后,无论什么时候执行同样的JMSML程序,如果该组<scenario>元素内的Verify属性被设为"true",JMSML将会把这个输入的JMSML程序当成是一个测试,并且会自动把输出文件与对应的基准文件进行比较,从而进行确认。

如果基准文件和输出文件吻合,那么测试就被宣布为通过,否则,将会被宣布为失败。

例子
测试被JMS管理的对象的动态创建、管理、和监测,以及JMS的消息发送和接收特性。

测试场景:创建一个名为"Warehouse"并且所有属性均为默认值的JMSServer,并且在一个名为"examplesServer"的WebLogic服务器实例上部署它。创建一个名为"orderqueue"的queue destination,并且使用所有明确定义的默认属性,然后把它添加到名为"Warehouse"的JMSServer上,输入"jms.queue.order"作为它的JNDI。向这个消息队列发送/接收消息,最后,删掉这个名为"orderqueue"的queue destination和名为"Warehouse" 的JMSServer。

清单2是上面定义的测试场景的JMSML描述。

一个JMSML一旦被编写完成,它就能够在当前的WebLogic服务器实例中运行。当前,JMSML提供了三种不同的运行程序的方法,它们是:

1.独立的命令行客户端
2.用于远程执行的Web浏览器接口
3.IDE (原型)

java com.bea.jmsml.commandline.JMSMLClient \
-protocol t3 \
-host localhost \
-port 7001 \
-username weblogic \
-password weblogic \
-filename jmstest.xml

该命令行假定执行环境按照如下方式设定:

一个名为"examplesServer"的WebLogic服务器实例正运行在本机,并且在"t3"协议被启动的情况下监听'7001端口。

WebLogic的安全性被设置成允许一个用户名为"weblogic",密码为"weblogic"的用户创建并且访问JMS服务器组件。

一个有效的JMS连接工厂被部署在"examplesServer"上,而且被绑定在JNDI名字"weblogic.examples.jms.QueueConnectionFactory"之上。

清单3中所示的测试程序被保存在"jmsml.dtd"文件所在的当前目录。

成功执行命令后,在标准输出上应该显示下面的消息。

*** jmstest processed *** \n***
Please see ./jmstest.out for the results ***


这时,当前目录下应该存在一个名为"jmstest.out"的输出文件,其中包含了所有的操作执行结果,如清单3所示。


在这个输出示例中,代码内容用不同的颜色显示,从而标识出操作类别,如下所示:
棕色:JMS接收(在通常模式下成功的发送没有输出)
红色:JMX添加、删除
蓝色:JMX列表(配置信息)
绿色:JMX列表(运行时统计)

一旦手工验证了这个输出的正确性,你就可以通过以下两步轻松地把它变成一个正确的、可重用的WebLogic JMS测试案例。

1把"jmstest.out"文件重命名为"jmstest.bmk"。
2编辑"jmstest.xml"文件,把<scenario>元素中的Verify属性设为"true"。

当下次执行同样的命令行时,JMSML把"jmstest.xml"当作一个测试案例并且在标准输出上输出测试的通过/失败结果。

这就是全部!不用进行Java编程,我们利用JMSML,快速地为BEA WebLogic 的JMS和JMX特性编写了一个完整的测试案例。这是一个可以运行的例子,就在JMSML的下载包中。

资源
可以从以下网址下载JMSML产品的二进制版本,里面附有技术白皮书:
http://dev2dev.bea.com/resourcelibrary/whitepapers/JMSML_WhitePaper.jsp

Listing 1: QueueSend.java

1 import java.util.*;
2 import javax.naming.*;
3 import javax.jms.*;
4
5 public class QueueSend
6 {
7 public final static String
8 JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
9 public final static String
10 JMS_FACTORY="QueueConnectionFactory";
11 public final static String QUEUE="exampleQueue";
12
13 private QueueConnectionFactory qconFactory;
14 private QueueConnection qcon;
15 private QueueSession qsession;
16 private QueueSender qsender;
17 private Queue queue;
18 private TextMessage msg;
19
20 public void init(Context ctx, String queueName)
21 throws NamingException, JMSException
22 {
23 qconFactory = (QueueConnectionFactory)
24 ctx.lookup(JMS_FACTORY);
25 qcon = qconFactory.createQueueConnection();
25 qsession = qcon.createQueueSession(false,
26 Session.AUTO_ACKNOWLEDGE);
27 queue = (Queue) ctx.lookup(queueName);
28 qsender = qsession.createSender(queue);
29 msg = qsession.createTextMessage();
30 qcon.start();
31 }
32
33 public void send(String message)
34 throws JMSException
35 {
36 msg.setText(message);
37 qsender.send(msg);
38 }
39
40 public void close()
41 throws JMSException
42 {
43 qsender.close();
44 qsession.close();
45 qcon.close();
46 }
47
48 /** main() method.
49 *
50 * @param args WebLogic Server URL
51 * @exception Exception if operation fails
52 */
53 public static void main(String[] args)
54 throws Exception
55 {
56 if (args.length != 1) {
57 System.out.println("Usage: java QueueSend WebLogicURL");
58 return;
59 }
60 InitialContext ic = getInitialContext(args[0]);
61 QueueSend qs = new QueueSend();
62 qs.init(ic, QUEUE);
63 qs.send("Hello World")
64 qs.close();
65 }
66
67 private static InitialContext getInitialContext(String url)
68 throws NamingException
69 {
70 Hashtable env = new Hashtable();
71 env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
72 env.put(Context.PROVIDER_URL, url);
73 return new InitialContext(env);
74 }

Listing 2: jmstest.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE jmsml PUBLIC "-//BEA Systems Inc//DTD JMSML Version 1.0 JMSML//EN" "jmsml.dtd">

<jmsml>

<scenario Name="Dynamic Queue creation" Verify="false">

<purpose>
To test the dynamic creation of queue
</purpose><expectedresult>
JMS queue destination should be successfully created with the specified attributes.
In order to verify this, two additional operations are performed as shown below.

1. Take the statistics information of the JMSServer "Warehouse", before and after the
creation of the queue destination, to see if the newly created queue
has been added to the current destination count of the JMSServer "Warehouse".

2. A sender and receiver will be created to send and receive a text message to and
from the newly created "orderqueue".

If the above two operations are successful, the test is declared as PASSED.
Otherwise the test is declared as FAILED.
</expectedresult>

<operation Class="mbean"
Type="JMSServer"
Name="Warehouse"
Targets="examplesServer"
>Add</operation>

<operation Class="mbean"
Type="JMSServer"
Name="Warehouse"
>List</operation>

<operation Class="mbean"
Type="JMSServerRuntime"
Name="Warehouse"
>List</operation>

<operation Class="mbean" Type="Queue"
Name="orderqueue"
JMSServer="Warehouse"
JNDIName="jms.queue.order"
BytesMaximum="1024000"
BytesThresholdHigh="1000000"
BytesThresholdLow="4096"
MessagesMaximum="100000"
MessagesThresholdHigh="90000"
MessagesThresholdLow="1000"
PriorityOverride="6"
TimeToLiveOverride="7200000"
DeliveryModeOverride="Persistent"
StoreEnabled="default"
>Add</operation>

<operation Class="mbean" Type="Queue"
Name="orderqueue"
>List</operation>

<operation Class="mbean" Type="JMSServerRuntime"
Name="Warehouse"
>List</operation>

<operation Class="mbean" Type="DestinationRuntime"
Name="orderqueue"
>List</operation>

<operation Class="message" Type="Text"
Name="sender"
Factory="weblogic.examples.jms.QueueConnectionFactory"
Queue="jms.queue.order"
Body="Test message to order queue"
>Send</operation>

<operation Class="mbean" Type="DestinationRuntime"
Name="orderqueue"
>List</operation>

<operation Class="message" Type="Text"
Mode="Synchronous"
Name="receiver"
Factory="weblogic.examples.jms.QueueConnectionFactory"
Queue="jms.queue.order"
>Receive</operation>

<operation Class="mbean" Type="DestinationRuntime"
Name="orderqueue"
>List</operation>

<operation Class="mbean" Type="Queue"
Name="orderqueue"
>Remove</operation>

<operation Class="mbean" Type="JMSServerRuntime"
Name="Warehouse"
>List</operation>

<operation Class="mbean" Type="JMSServer"
Name="Warehouse"
>Remove</operation>

</scenario>

</jmsml>

Listing 3: jmstest.out

JMSServer : Warehouse was added to server : examplesServer !
Name = Warehouse
Targets[0] = examplesServer
BytesMaximum = -1
BytesThresholdHigh = -1
BytesThresholdLow = -1
MessagesMaximum = -1
MessagesThresholdHigh = -1
MessagesThresholdLow = -1

---------------------------------------------
Name = Warehouse
SessionPoolsCurrentCount = 0
SessionPoolsHighCount = 0
SessionPoolsTotalCount = 0
DestinationsCurrentCount = 0
DestinationsHighCount = 0
DestinationsTotalCount = 0
MessagesCurrentCount = 0
MessagesHighCount = 0
MessagesPendingCount = 0
MessagesReceivedCount = 0
BytesCurrentCount = 0
BytesHighCount = 0
BytesPendingCount = 0
BytesReceivedCount = 0

---------------------------------------------
Queue Destination : orderqueue was added to JMSServer : Warehouse !
Name = orderqueue
JNDIName = jms.queue.order
JMSServer = Warehouse
StoreEnabled = default
Type = Queue
BytesMaximum = 1024000
BytesThresholdHigh = 1000000
BytesThresholdLow = 4096
MessagesMaximum = 100000
MessagesThresholdHigh = 90000
MessagesThresholdLow = 1000
PriorityOverride = 6
TimeToLiveOverride = 7200000
DeliveryModeOverride = Persistent

---------------------------------------------
Name = Warehouse
SessionPoolsCurrentCount = 0
SessionPoolsHighCount = 0
SessionPoolsTotalCount = 0
DestinationsCurrentCount = 1
DestinationsHighCount = 1
DestinationsTotalCount = 1
MessagesCurrentCount = 0
MessagesHighCount = 0
MessagesPendingCount = 0
MessagesReceivedCount = 0
BytesCurrentCount = 0
BytesHighCount = 0
BytesPendingCount = 0
BytesReceivedCount = 0

---------------------------------------------
Name = orderqueue
ConsumersCurrentCount = 0
ConsumersHighCount = 0
ConsumersTotalCount = 0
MessagesCurrentCount = 0
MessagesHighCount = 0
MessagesPendingCount = 0
MessagesReceivedCount = 0
BytesCurrentCount = 0
BytesHighCount = 0
BytesPendingCount = 0
BytesReceivedCount = 0

---------------------------------------------
Name = orderqueue
ConsumersCurrentCount = 0
ConsumersHighCount = 0
ConsumersTotalCount = 0
MessagesCurrentCount = 1
MessagesHighCount = 1
MessagesPendingCount = 0
MessagesReceivedCount = 1
BytesCurrentCount = 27
BytesHighCount = 27
BytesPendingCount = 0
BytesReceivedCount = 27

---------------------------------------------
@receiveMessage() : Message Received [0] : Test message to order queue
Name = orderqueue
ConsumersCurrentCount = 1
ConsumersHighCount = 1
ConsumersTotalCount = 1
MessagesCurrentCount = 0
MessagesHighCount = 1
MessagesPendingCount = 0
MessagesReceivedCount = 1
BytesCurrentCount = 0
BytesHighCount = 27
BytesPendingCount = 0
BytesReceivedCount = 27

---------------------------------------------
Queue : orderqueue was removed from JMSServer : Warehouse !
---------------------------------------------
Name = Warehouse
SessionPoolsCurrentCount = 0
SessionPoolsHighCount = 0
SessionPoolsTotalCount = 0
DestinationsCurrentCount = 1
DestinationsHighCount = 1
DestinationsTotalCount = 1
MessagesCurrentCount = 0
MessagesHighCount = 1
MessagesPendingCount = 0
MessagesReceivedCount = 1
BytesCurrentCount = 0
BytesHighCount = 27
BytesPendingCount = 0
BytesReceivedCount = 27

---------------------------------------------
JMSServer : Warehouse was removed from server : examplesServer !

 作者简介
Kathiravan Sengodan具有超过11年的载软件行业经验。目前,他是BEA WebLogic JMS/Messaging组的一名软件工程师。
dot dot dot

dot
  作者其它文章
您对本文的评价
您对这篇文章的看法如何?
太棒了!5分 不错啊 4分 一般般 3分 有待提高 2分 不好 1分

   
相关产品
相关技术