引言
异步消息传递的核心是面向消息的中间件(Message-Oriented Middleware,MOM),如 IBM MQSeries?。下面让我们了解一下其工作方式:为了发送消息,System A 使用 MOM 公开的 API 将消息放入 MOM 中。希望接收消息的 System B 可以使用 MOM 公开的 API 从 MOM 获取消息。如果您没有使用 MOM API 所需的 MOM 库,则可以使用一般 Web 服务,以公开用于将消息放入 MOM 的方法。希望发送消息的系统将需要一个 Web 服务客户机。系统希望发送消息时将调用此客户机,此客户机将调用 Web 服务,此 Web 服务会将消息放入到 MOM 中。
配置 WebSphere Application Server Version 6 进行缺省消息传递
为了说明本文中的概念,我们需要配置 WebSphere Application Server V6(以下称为 WAS)。要配置 WAS,请执行以下步骤:
创建总线
创建总线成员
创建目的地
创建 JMS 队列
创建 JMS 激活规范
使用 Web 服务将消息放入 MOM
清单 1. putMessage 方法
public void putMessage(String message){
try {
Properties prop = new Properties();
prop.put(InitialContext.INITIAL_CONTEXT_FACTORY,
"com.ibm.websphere.naming.WsnInitialContextFactory");
prop.put(InitialContext.PROVIDER_URL,
"corbaloc:iiop:localhost:2809");
InitialContext context = new InitialContext(prop);
//Do the lookup for Queue connection factory.
QueueConnectionFactory
factory =(QueueConnectionFactory)context.lookup("JMS/MyQueue_CF");
//Do the lookup for Queue.
Destination queue = (Destination) context.lookup("JMS/queue");
//Create connection and start it.
Connection connection = factory.createConnection();
connection.start();
System.out.println("connection created");
//Create session and message producer.
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer producer=session.createProducer(queue);
System.out.println("producer created");
System.out.println(producer.getDestination().toString());
//Prepare the text message.
TextMessage msg=session.createTextMessage();
msg.setText(message);
//Send the message.
producer.send( msg);
System.out.println("sent message : "+msg.getText());
} catch (Exception e) {
e.printStackTrace();
}
}
配置数据库
创建示例表
清单 2. 用于创建示例表的 SQL
CREATE TABLE customer
(
pkey INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START
WITH 1, INCREMENT BY 1, NO CACHE ) PRIMARY KEY,
fname VARCHAR(20),
lname VARCHAR(20),
ccode VARCHAR(10)
);
创建 Java SP
此 Java 存储过程(Java Stored Procedure,Java SP)是本文概念中的关键。调用此 Java SP 时将调用的 Java 类中将包含调用 Web 服务的代码。请运行以下 SQL 命令来创建 Java SP:
清单 3. 用于创建 Java SP 的 SQL
CREATE PROCEDURE MyPROCEDURE ( IN var0 INTEGER,IN var1 VARCHAR(20) )
SPECIFIC SQL060622110835012
DYNAMIC RESULT SETS 1
NOT DETERMINISTIC
LANGUAGE Java
EXTERNAL NAME 'MyPROCEDURE.invokeWS'
FENCED
THREADSAFE
PARAMETER STYLE JAVA
下面的代码列表显示的是 MyPROCEDURE Java 类。此类具有一个名为 invokeWS 的方法。此方法具有三个参数,主键、对表执行的操作(创建、更新、删除)和结果集。我使用了 Axis API 来编写此方法中的 Web 服务客户机代码。为了编译和运行此类,请确保您的类路径中包含各个 Axis jar 文件。
清单 4. Java SP 的 Java 类
import java.sql.*;
import java.io.FileOutputStream;
import java.io.PrintStream;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.Service;
import javax.xml.rpc.Call;
import javax.xml.rpc.ParameterMode;
import javax.xml.namespace.QName;
public class MyPROCEDURE
{
public static void invokeWS ( int var0, String var1, ResultSet[] rs1 )
throws SQLException, Exception
{
try{
//create service factory
ServiceFactory factory = ServiceFactory.newInstance();
// define qnames
String targetNamespace = "http://asyncmessage.ibm.com";
QName serviceName = new QName(targetNamespace,"AsynchronousMessageWSService");
QName portName = new QName(targetNamespace,"AsynchronousMessageWS");
QName operationName = new QName(targetNamespace,"putMessage");
// create service
Service service = factory.createService(serviceName);
// create call
Call call = service.createCall();
// set port and operation name
call.setPortTypeName(portName);
call.setOperationName(operationName);
// add parameters
call.addParameter("message",
new QName(targetNamespace,"string"),ParameterMode.IN);
call.setReturnType(new QName("",""));
// set end point address
call.setTargetEndpointAddress("http://localhost:9080/AsyncMessagingSamples
/service/AsynchronousMessageWS");
// invoke the remote web service
call.invoke(new Object[]
{ "Message from DB2 : a row with primary key"+var0+" is "+var1+"d"});
}catch(Exception e)
{
try{
FileOutputStream fout=new FileOutputStream("errors.txt");
e.printStackTrace(new PrintStream(fout));
}catch(Exception e1){}
}
}
}
在示例表上创建触发器
在示例代码中,我们在 customer 表上创建了三个触发器,分别用于 Insert、Update 和 Delete 操作。例如,只要在 customer 表中插入、更新或删除行,就会使用这些触发器。当发生这三个事件中的一个时,就会执行触发器。这些触发器将随后调用 Java SP,而后者又会调用 invokeWS 方法。请运行以下 SQL 命令来创建触发器:接下来让我们看看如何进行此工作:
清单 5. 用于在示例表上创建触发器的 SQL
//Trigger for row insertion
CREATE TRIGGER event_create
AFTER INSERT ON CUSTOMER REFERENCING NEW AS N
FOR EACH ROW MODE DB2SQL
call MYPROCEDURE(N.pkey,'create') ;
//Trigger for row updation
REATE TRIGGER event_udpate
AFTER UPDATE ON CUSTOMER REFERENCING NEW AS N
FOR EACH ROW MODE DB2SQL
call MYPROCEDURE(N.pkey,'update') ;
//Trigger for row deletion
CREATE TRIGGER event_delete
AFTER DELETE ON CUSTOMER REFERENCING OLD AS O
FOR EACH ROW MODE DB2SQL
call MYPROCEDURE(N.pkey,'delete')
创建 MDB
为了完成此方案,我们需要创建消息驱动的 Bean(Message Driven Bean,MDB)。此 MDB 将订阅队列,而我们的 Web 服务会将消息放入到此队列中。有关如何配置 MDB 的详细信息,请参考参考资料部分中列出的文章“将消息驱动 Bean 和 JMS 应用程序部署到服务集成总线中”。清单 6 显示了摘自 ibm-ejb-jar-bnd.xmi 文件和本文中使用的示例 MDB 的 onMessage 方法的代码片段。
注意:为了便于阅读,已将 ibm-ejb-jar-bnd.xmi 中的某些部分删除,而重要属性则使用了粗体进行标记。
清单 6. 摘自 onMessage 和 ibm-ejb-jar-bnd.xmi 文件的代码片段
.........................................................
<ejbBindings .....
activationSpecJndiName="eis/MyQueue_activation_spec" destinationJndiName="JMS/queue">
..........................................................
<resRefBindings ......... jndiName="JMS/MyQueue_CF">
..........................................................
<resRefBindings ..... jndiName="JMS/queue">
...........................................................
</ejbBindings>
public void onMessage (javax.jms.Message msg)
{
try {
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***"+((TextMessage)msg).getText()+"***");
System.out.println("***********************************");
System.out.println("***********************************");
} catch (JMSException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
投入使用
我们已经完成所需的步骤。请在 WebSphere Application Server 中部署 Web 服务。现在,只要我们在 customer 表中创建、更新或删除行,就会由 MDB 向 WebSphere Application Server 的 SystemOut.log 写入一条消息。如果您在 customer 表中使用主键 100 创建一个行,对应的消息将与如下所示类似:"Message from DB2: a row with primary key 100 is created"。
结束语
在本文中,我们了解了可以如何使用 Web 服务启用 HTTP 上的异步消息传递功能。这个方法的主要好处是它具有平台和语言独立性,允许您自由地编写 JMS 客户机来向 MOM 发送消息。