使用WebLogic 8.1的jCOM在VB中向JMS队列发送消息
1.简介
随着企业信息化的不断深入和信息技术的不断进步,企业内的信息系统间和不同企业的信息系统的集成是不少企业面临的问题。最初的EAI方案主要面对企业内的信息系统的集成,采用的多是点对点方式,很少有采用消息总线方式进行集成。近年来随着Web服务、特别是中间件技术的发展,消息总线的集成方式成为业内的主流。
Java 消息传递服务(JMS)定义了一个可以用来在应用程序间交换消息的公共 API。它允许应用程序间的异步通信。WebLogic 8.1作为业界领先的J2EE应用服务器,支持JMS 1.1规范。
使用JAVA语言可以很方便的利用JMS服务。但是使用其它语言,尤其是Windows平台下的Visual Basic,Delphi,PB等语言,没有直接的方法调用JMS的消息服务。如何通过JMS整合Windows平台下的应用是一个需要解决的问题。
从WebLogic 6.1开始,BEA在WebLogic 里整合了jCOM,这为Windows平台下的开发语言以COM方式调用WebLogic 提供的服务开辟了一条切实可行的途径。 虽然BEA更推荐采用Web Service方式实现WebLogic与Windows平台下的应用进行集成。但是由于COM计算模型在Windows平台下已经十分成熟,而且得到了众多开发工具的支持。更为重要的是,在Windows平台下很多已经存在的应用系统都利用或是支持COM技术。jCom的存在使得WebLogic 与Windows平台下已有应用系统的集成多了一个选择。
本文主要通过介绍jCOM的一个应用实例,讨论如何利用jCOM,在VISUAL BASIC中编写应用,向WebLogic 中的JMS队列发送消息。
2.jCOM环境与工具简介
按照BEA的官方介绍,jCOM提供了与 Microsoft 环境间的内在互操作性,即允许从 VB、ASP和其他基于 COM+的产品,访问部署BEA WebLogic Server 中的对象。jCOM可以使JAVA对象访问Windows下的COM对象,同样也可以在Windows下像访问COM对象那样去访问JAVA对象。
从实现原理上说,jCOM通过提供JAVA与COM之间不同的对象计算模型所采用的不同通信协议之间转换的“桥梁”来实现了JAVA与COM对象之间的互操作。
在WebLogic 安装完毕后,与jCOM相关的工具会安装在%WL_HOME%server\in下。在这里先简要介绍在下面会用到的两个工具:regjvm和regjvmcmd。jCOM中所包含的其它工具的详细介绍请参看BEA提供的Edocs文档。
regjvm
Regjvm是一个用VC编写的(通过程序图标就看得出,J)有GUI界面的工具。为了在WebLogic jCOM中,COM客户端访问COM对象一样去访问JAVA对象,必须用regjvm在COM客户端去注册一个JVM。被COM客户端访问的JAVA对象运行在这个JVM中。Regjvm可以创建、删除和管理COM客户端所有的JVM。
regjvmcmd
regjvmcmd是一个regjvm对应的命令行工具。在GUI界面完成的所有功能通过本命令行工具都可以完成。
需要说明的是regjvm 与regjvmcmd 只是修改COM客户端所在机器注册表的工具。
3.开发步骤
3.1启动WebLogic Server
首先启动WebLogic Server。安装完WebLogic 8.1后,可以通过configuration wizard创建一个新的Domain,在Domain里创建Server,Server监听7001端口。
3.2创建JMS环境
进入WebLogic Server Console。选中左边的JMS节点,创建一个新的JMS Server,然后选中底部的Configure Destinations。配置一个新的 JMS Queue,名称是TryQueue。输入 TryQueue作为JNDI Name。
3.3编写JVM注册类
首先我们来实现JVM注册类JMSTest(JVM注册类的名称没有限制,在本例中其名称为JMSTest)。创建一个java文件名为JMSTest.java,存放在c:scriptssourcejCOM下。文件内容如下:
import javax.naming.*;
public class JMSTest {
public static void main(String[] args) throws Exception {
try {
// Register JVM
com.bea.jcom.Jvm.register("JMS");
while (true) {
Thread.sleep(5000);
}
}
catch (Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
JVMTest.java逻辑并不复杂,其中有几点值得注意:JVMTest必须要有main方法,main方法中完成的主要工作是执行com.bea.jcom.Jvm.register("JMS")注册JVM。
”JMS”是注册的JVM的名称。可以选用任何的字符串作为注册的JVM的名称。
3.4编写通过COM访问的java类
接下来我们创建一个JAVA Class,包装对JMS的访问,发送消息,以及封装JNDI的查询操作。在VB中我们会通过COM方式来访问这个JAVA class。程序的源码如下:
import javax.naming.*;
import javax.jms.*;
import java.util.*;
public class test {
public void SendMessage( QueueSender mQueueSender, Message mMessage)
throws javax.jms.JMSException {
mQueueSender.send(mMessage);
}
public Object ContextLookup( String mClassName )
throws NamingException {
Hashtable ht = new Hashtable();
ht.put(Context.INITIAL_CONTEXT_FACTORY,"WebLogic.jndi.WLInitialContextFactory");
ht.put(Context.PROVIDER_URL,"t3://localhost:7001");
InitialContext mContext = new InitialContext(ht);
Object obj = mContext.lookup(mClassName);
return obj;
}
}
test类里有两个方法,SendMessage与ContextLookup。SendMessage是用来向JMS对列发送消息。ContextLookup用来封装JNDI,根据传递进来的字符串查找对象。注意在这里,ContextLookup是访问本机WebLogic提供的JNDI服务。
源程序编辑好后,用javac进行编译。本例中,生成的class文件与java源文件存放在同一路径c:scriptssourcejCOM下。
3.5编写VB客户端代码
启动VB 6.0,新建一个标准EXE工程。在Form上建立一个button。
在button的onclick事件里写入如下代码:
Private Sub Command1_Click()
Dim oTest As Object
Set oTest = GetObject("JMS:test")
Dim oConnectionFactory As Object
Set oConnectionFactory = oTest.ContextLookup("javax.jms.QueueConnectionFactory")
Dim oQueue As Object
Set oQueue = oTest.ContextLookup("TryQueue")
Dim oQueueConnection As Object
Set oQueueConnection = oConnectionFactory.createQueueConnection()
Dim oQueueSession As Object
Set oQueueSession = oQueueConnection.createQueueSession(False, 0)
Dim oSender As Object
Set oSender = oQueueSession.createSender(oQueue)
Dim oMessage As Object
Set oMessage = oQueueSession.createTextMessage()
oMessage.SetText ("this is a test message")
Call oTest.SendMessage(oSender, oMessage)
MsgBox "sent ok"
End Sub
代码使用了VB的GetOject函数,用JVM name+”:”+java class name组成字符串,来取得对JVM中运行的test对象的引用。其它的代码很简单,就不再详述了。
为了上述工程编译后的可执行文件能顺利执行,需在环境变量path中加入”C:\ea81WebLogic81server\in”。其目的是提供对jCom中ntvinv.dll的访问路径。
3.6用Regjvmcmd注册JVM
接下来要做的工作是用Regjvmcmd来注册JVM。JCOM支持COM客户端采用三种方式访问JVM,在实际应用中可以根据需要选择其中的一种。下面分别介绍这三种不同的访问方式:
DCOM 模式
Native 模式(进程外访问)
Native mode in process (进程内访问)
DCOM模式
在DCOM方式下,COM客户端可以和运行java代码的JVM分处在不同的两台机器上。你可以用Windows平台下的COM客户端去访问UNIX主机上运行的JVM。在DCOM方式下,可以在远程主机上采用如下的命令启动JVM:
C:\ea81jdk141_05\injava -classpath C:\ea81WebLogic81serverlibWebLogic.jar;c:scriptssourcejCOM -DJINTEGRA_DCOM_PORT=5000 JMSTest
这里有几点需要注意。首先时执行前面写好的JMSTest,JMSTest主要工作是注册名称为”JMS”的JVM。其次在命令行上指定的DCOM的端口号,这里端口号指定为5000。
在COM客户端运行的机器上执行以下命令注册JVM:
regjvmcmd JMS localhost[5000]
命令行中的JMS就是所注册的JVM的名称,这里注册所用的名称要与JMSTest中在main函数里调用com.bea.jcom.jvm.register("JMS")注册的名称一致。
在实验环境中COM客户端与提供服务的JVM运行在同一台计算机上。若是运行在不同的机器上,参数localhost需换成启动JVM的那台远程主机的名称或IP地址。
Native mode (进程外访问)
在Native mode模式下,COM客户端和运行java代码的Server必须处在同一台的机器上,它们分别是两个不同的进程。
采用如下的命令启动JVM:
C:\ea81jdk141_05\injava -classpath C:\ea81WebLogic81serverlibWebLogic.jar;c:scriptssourcejCOM -DJINTEGRA_NATIVE_MODE JMSTest
命令行上加入-DJINTEGRA_NATIVE_MODE参数,说明是以Native mode提供对COM客户端的服务。
执行以下命令注册JVM:
regjvmcmd /native JMS
加入/native说明注册的JMS JVM采用的是Native mode。
命令行中的JMS是所注册的JVM的名称,这里注册所用的名称要与JMSTest中在main函数里调用com.bea.jcom.jvm.register("JMS")注册的名称一致。
Native in process方式
在Native in process模式下,COM客户端和运行java代码的JVM处在同一台的机器上。与Native模式不同的是,COM客户端在自己的进程内启动提供服务的JVM。
采用如下的命令注册JVM:
regjvmcmd /native /inproc /java2 JMS classpath=C:\ea81WebLogic81serverlibWebLogic.jar;c:scriptssourcejCOM jvm=C:\ea81jdk141_05jre\inclientjvm.dll main=JMSTest
命令行上加入/native /inproc参数,说明是以Native in process mode启动JVM。后面的参数指定了启动JVM所需的参数。命令行中的jvm参数指定JDK中jvm.dll的路径。main参数指定包含main函数的类名。
在Native in process mode模式下不需要显式的启动JMSTest,在COM客户端获取JVM中提供服务的java对象时,COM运行环境会自动加载在regjvmcmd命令行上指定的JVM。
完成了上述步骤后,我们可以运行前面建立的VB工程。在界面中点击button,系统弹出对话框:
4.应用分发
刚才的实验,VB的应用和WebLogic Server都是运行在同一台机器上。在实际应用过程中,前台应用与WebLogic Server应该是运行在不同的机器上。如何分发程序就是我们接下来要面对的问题。
根据jCOM提供的3种不同的运行方式,程序的分发也有所不同。下面就这三种运行方式对应的分发模式作一简要的说明:
DCOM模式
DCOM模式的分发比较简单。假定WebLogic Server运行在10.210.0.20上。
- 首先在VB应用运行的机器上安装JDK;
- 然后拷贝%WL_HOME%server\in下的JintMk.dll,ntvinv.dll,regjvmcmd.exe和regjvmcmd目录以及ntvinv目录,把它们复制到在VB应用运行的机器上某个子目录里。
- 在VB应用运行的机器上打开DOS窗口,运行:regsvr32 JintMk.dll
注册JintMk.dll,注意是在JintMk.dll复制到的目录里运行上述命令;JintMk.dll十分重要,它隐藏了jCOM很多的秘密,J
- 接着在同一DOS窗口下运行命令:regjvmcmd JMS 10.210.0.20[5000];
- 回到10.210.0.20,在命令行敲入:
C:\ea81jdk141_05\injava -classpath C:\ea81WebLogic81serverlibWebLogic.jar;c:scriptssourcejCOM -DJINTEGRA_DCOM_PORT=5000 JMSTest
完成前面的准备工作后,就可以运行用VB写的应用了。regjvmcmd.exe和regjvmcmd目录在分发完成后可以删除;
Native mode与Native in process mode
- 首先在VB应用运行的机器上安装JDK;
- 然后拷贝%WL_HOME%server\in下的JintMk.dll,ntvinv.dll,regjvmcmd.exe和regjvmcmd目录以及ntvinv目录,把它们复制到在VB应用运行的机器上。
- 复制license.bea和%WL_HOME%serverlibweblogic.jar到在VB应用运行的机器上。
- 复制JMTest.class,test.class到在VB应用运行的机器上。
- 在VB应用运行的机器上打开DOS窗口,运行regsvr32 JintMk.dll注册JintMk.dll,注意JintMk.dll的路径;
- 接着在同一DOS窗口下运行命令:regjvmcmd /native JMS 10.210.0.20;
- 接着运行:java -classpath WebLogic.jar;. -DJINTEGRA_NATIVE_MODE JMSTest 完成前面的准备工作后,就可以运行用VB写的应用了。regjvmcmd.exe和regjvmcmd目录在分发完成后可以删除; Native in process mode与Native mode略有不同,只是把6,7两步运行的命令替换一下: regjvmcmd /native /inproc /java2 JMS classpath=C:jmsWebLogic.jar;c:jms jvm=C:jdk141_05jre\inclientjvm.dll main=JMSTest 运行上述命令时注意一下命令行中涉及的文件的路径。5.总结 到此为止,如何利用jCOM提供的JAVA-COM桥提供的服务,在VB中向WebLogic JMS对列发送消息已经叙述完毕。对于jCOM中提供的三种调用方式也作了详细介绍,在实际应用中可以根据需要进行选择。 在BEA WebLogic 8.1中提供的jCOM例程里都是通过COM对象直接访问WebLogic 中的EJB对象。在本例中,提供另外一种方式,展现了如何用COM客户端通过jCOM去访问普通的JAVA Object。 jCOM为JAVA对象和COM对象之间的互操作提供了完备与强大的支持。jCOM提供的这些强大的特性结合WebLogic JMS提供的消息服务,为整合不同操作系统,不同开发平台下的复杂应用提供了一种崭新而又便捷的途径。 由于VB作为Windows平台流行的开发工具,提供了很便捷的方式访问COM对象,所以本文采用了VB构造COM客户端去访问WebLogic的JMS队列。其它支持COM的开发语言,诸如VC,Delphi,PowerBuilder也可以参照本文介绍的方法来访问WebLogic的JMS队列。还有一点需要说明,本文提供了COM客户端以迟后编连的方式访问JAVA对象,jCOM还支持以静态编连的方式访问JAVA对象。详细情况可以参看BEA的jCom Edocs文档。