使用 Visual MainWin for J2EE 和 OpenJMS 轻松实现消息传递
Java™ 应用程序中使用的一个常见 API 是 JMS API,它允许您实现托管消息和消息队列。当使用 Mainsoft 的 Visual MainWin for J2EE(又名 Grasshopper)时,您可以从 JAR 文件或 EJB 中消耗和使用 Java 资源。在本文中,您将学习如何在 Grasshopper 应用程序中使用 C# 或 VB.NET 直接与此 API 的 OpenJMS 实现的 Java 代码进行交互。然后,您可以使用它在 Visual Studio .NET® 开发环境中使用此来编写和调试 JMS 应用程序。
概述
Grasshopper 是 Mainsoft 提供的免费 Visual Studio .NET IDE 插件,它允许您使用 .NET 语言编写应用程序,然后通过将 MSIL 代码转换为 Java 字节码来在 J2EE 上重新编译和重新托管它们。此外,它还有一个强大的方面,那就是您可以在同一个应用程序中混合使用 Java 和 .NET 代码,并且仍然可以从 Visual Studio .NET IDE 中编写、调试和部署。 这其中许多出色的方面之一是,您可以像编写原生 Java 一样消耗您的 Java 资产。 结果是一个统一的运行时堆栈,其中.NET/J2EE在字节码级别实现了互操作性。
一个典型的场景是应用程序具有 ASP.NET 前端和一个 Java 后端。为了与 Java 后端接口,您可以使用昂贵的桥接或其他互操作性解决方案。但如果高性能是要求,Web 服务和桥接可能不可行。
消息传递的开放标准 JMS API 是一个很好的例子,说明如何使用 Grasshopper 混合 Java 和 .NET 代码。JMS 是一个开放标准,因此有许多供应商竞相提供其实现和配件(如管理平台)。这为您提供了极大的选择空间,并帮助您找到价格合适的供应商。但除非您使用某种形式的消息桥接来增加复杂性和成本,否则它对 .NET 是封闭的。
在本文中,您将逐步了解如何通过直接访问源头——即消耗 OpenJMS JAR 文件——轻松地使用免费 OpenJMS 消息服务器进行 JMS 消息传递。
入门。
要开始,您需要 Grasshopper 1.7,可以从 http://dev.mainsoft.com/ 下载。您还需要 Tomcat 5.5,它将作为 Grasshopper 安装的一部分为您安装。 如果您想使用 IBM WebSphere®、BEA WebLogic® 或 JBoss®,您也可以这样做,但您需要 Visual MainWin® for J2EE™ 的企业版,可以从同一个地方下载。
最后,您需要一个消息服务器,我推荐的并且在本文中使用的服务器是 OpenJMS 服务器,它是 Tomcat 的标准消息队列 MOM(面向消息的中间件)。您可以从 http://openjms.sourceforge.net/ 下载
安装 OpenJMS 非常简单。只需下载二进制文件,然后将其解压缩到您的硬盘驱动器。然后,将环境变量 OPENJMS_HOME 设置为您解压缩它们的位置。在本例中,我将它们放在目录 C:\jms\openjms-0.7.7-alpha-3 中,因此将系统环境变量设置为此值。在 Windows 中执行此操作,右键单击桌面上的“我的电脑”,然后选择“属性”。
然后,在“高级”选项卡(图 1)中选择“环境变量”。

图 1. 环境变量设置。
对话框将显示用户变量和系统变量(图 2)。

图 2. 环境变量对话框
在系统变量区域,单击“新建”,然后输入变量名和值,如图 3 所示。请注意,变量值在您的系统上可能不同。您应将其设置为解压缩 openjms 的目录名称。

图 3. 设置环境变量。
如果您系统中没有 JRE 或 JDK,您应该下载并安装一个,并确保您的 JAVA_HOME 系统变量已设置为其安装目录。对于标准 JRE 安装,默认值是 C:\Program Files\Java\jre1.5.0_06。
设置好所有这些后,从 DOS 命令,切换到您安装 OpenJMS 目录下的“bin”目录,然后发出“openjms run”命令。您应该会看到类似图 4 中的输出。

图 4. 在命令控制台中运行 OpenJMS。
构建消息命名空间。
下一步是构建消息命名空间。这将包含您将用于包装底层 JMS API 的类,以便在您的应用程序中轻松使用它们。从 Visual Studio.NET,执行“文件”->“新建”->“项目”请求,然后从“Visual MainWin C# for J2EE Projects”文件夹中选择“类库”。(参见图 5)。

图 5. 创建新的 System.Messaging 命名空间。
这将创建一个新的类库,其中包含一个名为“Class1.cs”的类。删除此库中的所有代码,并替换为本文下载中的 System.Messaging 代码。
接下来,您需要添加对 OpenJMS JAR 文件的引用。您可以通过右键单击“解决方案资源管理器”中的“引用”节点并选择“添加 Java 引用”来完成此操作。这将打开一个通用对话框。使用它来浏览 OpenJMS 安装目录下的“lib”目录。例如,如果您将 OpenJMS 文件解压缩到 C:\jms 目录,则浏览到 C:\jms\openjms-0.7.7-alpha-3\lib。
选择这些 JAR 添加引用——导入可能需要几分钟才能完成
- commons-codec-1.3.jar
- commons-logging-1.0.4.jar
- concurrent-1.3.4.jar
- jms-1.1.jar
- jndi-1.2.1.jar
- openjms-0.7.7-alpha-1.jar
- openjms-common-0.7.7-alpha-1.jar
- openjms-net-0.7.7-alpha-1.jar
- spice-jndikit-1.1.jar
您现在应该能够编译您的类库。如果您遇到任何编译错误,请检查您是否正确导入了上面提到的所有 JAR 文件。如果不行,此库的完整 Visual Studio 解决方案可在下载文件中找到。
构建消息发送器
接下来,您将构建一个简单的控制台应用程序,该应用程序将消息发送到消息队列。由于您上面构建的类库,这变得非常简单。
要开始,请在 Visual Studio.NET 中选择“文件”->“新建”->“项目”。从“Visual MainWin C# for J2EE”文件夹中选择“控制台应用程序”,并将其命名为“Message Sender”。
创建解决方案后,添加一个 JAR 引用到 System.Messaging.jar——您之前构建的类库。除非您已将其部署到其他地方,否则您会在其项目文件夹中找到它。
然后,添加与创建库时相同的 JAR Java 引用。
在 Class1.cs 的顶部,添加以下“using”指令 using System;
using System.Messaging;
using javax.naming;
using javax.jms;
最后,在 Main 方法中,您将添加实现消息队列的代码。您将从设置消息传递环境的代码开始,通过设置其 Context 对象的属性来实现 static void Main(string[] args)
{
java.util.Hashtable properties = new java.util.Hashtable();
properties.put(Context__Finals.PROVIDER_URL, "tcp://:3035");
properties.put(Context__Finals.INITIAL_CONTEXT_FACTORY,
"org.exolab.jms.jndi.InitialContextFactory");
properties.put(Context__Finals.SECURITY_PRINCIPAL, "admin");
properties.put(Context__Finals.SECURITY_CREDENTIALS, "openjms");
要了解更多关于这些属性及其作用的信息,请查阅 OpenJMS 文档。
在您的 Main 方法的其余部分,您将发送 10 条带有当前时间的消息到消息队列。在监听器未激活的情况下运行它是安全的。OpenJMS 将为您处理队列,直到您准备好取出它们。 string queueServer = "localhost";
string queueName = "queue1";
int N = 10;
if (args != null && args.Length > 0)
{
N = Convert.ToInt32(args[0]);
}
for (int i = 0; i < N; i++)
{
System.Messaging.Message theMessage = new System.Messaging.Message();
theMessage.Body = "test value " + i
+ " " + System.DateTime.Now.ToShortTimeString();
MessageQueue mq = new MessageQueue("FormatName:DIRECT=OS:" +
queueServer + "\\" + queueName);
mq.Send(theMessage);
Console.WriteLine("Sent Message: {0}", theMessage.Body);
}
Console.ReadLine();
java.lang.System.exit(0);
}
运行此应用程序将发送在参数中指定的数量的消息到队列,如果未指定参数,则会发送 10 条消息,如图 6 所示。此应用程序的核心在于 for 循环。它只需设置一个 System.Messaging.Message 对象(在您之前创建的类库中找到),并将其正文初始化为字符串“test value”以及当前日期和时间。然后,它实例化一个 messagequeue 对象,并将其设置为本地服务器和名为 queue1 的队列,queue1 是 OpenJMS 中预定义的队列。然后,调用此队列上的 send 方法,并将消息作为参数传递。非常简单!

图 6. 运行消息发送器
此时,消息已由您的 MessageSender 分派,并位于 OpenJMS 管理的队列中,等待被提取。我们不要让它们等待太久,而是编写一个简单的读取器来将它们从队列中取出!
构建消息读取器
按照创建 MessageSender 项目的相同步骤,创建一个名为“MessageGetter”的控制台应用程序,该应用程序将获取消息。请确保添加与该项目相同的引用,即对 OpenJMS jar 的 8 个引用,以及对您之前创建的 System.Messaging 类库的引用。
然后,将与之前在 Class1.cs 顶部添加的“using”指令相同的指令添加到 Class1.cs 的顶部。
最后,这是您的类的 Main 方法。 static void Main(string[] args)
{
java.util.Hashtable properties = new java.util.Hashtable();
properties.put(Context__Finals.PROVIDER_URL, "tcp://:3035");
properties.put(Context__Finals.INITIAL_CONTEXT_FACTORY,
"org.exolab.jms.jndi.InitialContextFactory");
properties.put(Context__Finals.SECURITY_PRINCIPAL, "admin");
properties.put(Context__Finals.SECURITY_CREDENTIALS, "openjms");
string queueServer = "localhost";
string queueName = "queue1";
int N = 10;
if (args != null && args.Length > 0)
{
N = Convert.ToInt32(args[0]);
}
for (int i = 0; i < N; i++)
{
MessageQueue mq = new MessageQueue("FormatNameIRECT=OS:" +
queueServer + "\\" + queueName);
System.Messaging.Message theMessage = mq.Receive();
Console.WriteLine("Received message: {0}", theMessage.Body);
}
}
运行此应用程序将为您提供图 7 中的输出。您将看到它接收了发送器发送的每条消息。代码与发送器非常相似。您设置一个 MessageQueue 对象,然后使用 Receive() 方法监听它。这将返回一个消息对象,您可以通过“Body”属性查询其内容。

图 7. 运行消息接收器应用程序。
结论。
Grasshopper 不限于它直接支持的 .NET 命名空间。由于 Java 引用可以直接插入您的应用程序,并且 Java 源代码可以与您的 C# 或 VB.NET 代码内联运行,因此您可以轻松使用外部 Java API。
在本文中,您了解了如何从 Visual Studio.NET 在 OpenJMS 服务器上使用 JMS 消息传递,并看到了将消息发送到队列并从中取出的简单方法。您实现的 System.Messaging 类库可以轻松地在您的应用程序中重用,因此您可以通过 Grasshopper 实现 .NET 应用程序与 JMS 的互操作! |