Messaging made easy with Visual MainWin for J2EE and OpenJMS
One common API that is used in Java� applications is the JMS API, which allows you to implement managed messaging and message queues. When using Visual MainWin for J2EE (aka Grasshopper) from Mainsoft you can consume and use Java resources from JAR files or EJBs. In this article you will learn how to use C# or VB.NET in your Grasshopper applications to interface directly with the Java code from the OpenJMS implementation of this API. You can then use this to write and debug JMS applications using the Visual Studio .NET� development environment.
Overview
Grasshopper is the freely available plug in to the Visual Studio .NET IDE from Mainsoft that allows you to code your applications in .NET languages, and then recompile and rehost them on J2EE, by converting the MSIL code into Java bytecode. An additional, and powerful aspect of this is that you can mix Java and .NET code within the same application, and still code, debug and deploy from the Visual Studio .NET IDE. One of the many great aspects of this is that you can consume your Java assets in exactly the same way as you were writing native Java. The result is a unified runtime stack, with .NET/J2EE interoperability achieved at the bytecode level.
A typical scenario for this is an application with an ASP.NET front end to an application, and a Java back end. To interface to the Java back end, you could use expensive bridging or other interoperability solutions. But if high performance is a requirement, Web services and bridging may be infeasible.
The open standard JMS API for messaging is a nice example of how to mix Java and .NET code using Grasshopper. JMS is an open standard, and as such has many vendors competing on implementations and accessories (such as management platforms) for it. This gives you excellent choice in what you implement, and helps you find vendors that can do it for the right price. But it is closed off to .NET unless you add further to complexity and price by using some form of message bridging.
In this article you will step through how you can easily use JMS messaging with the free OpenJMS messaging server by going straight to the source � and consuming the OpenJMS JAR files.
Getting Started.
To get started, you will need Grasshopper 1.7, which can be downloaded from http://dev.mainsoft.com/. You will also need Tomcat 5.5, and this will be installed for you as part of the Grasshopper installation. Should you want to use IBM WebSphere�, BEA WebLogic� or JBoss�, you can also do this, but you�ll need the Enterprise edition of Visual MainWin� for J2EE� which may be downloaded from the same place.
Finally you�ll need a messaging server, and the one that I would recommend, and am using in the article is the OpenJMS server, which is the standard message queue MOM (Messaging Oriented Middleware) for Tomcat. It can be downloaded from http://openjms.sourceforge.net/
Installing OpenJMS is a snap. Simply download the binaries, and unzip them to your hard drive. Then, set the environment variable OPENJMS_HOME to where you unzipped them. In my case I put them in the directory C:\jms\openjms-0.7.7-alpha-3, and as such set the system environment variable to this value. To do this in Windows, right click �My Computer� on your desktop, and select �Properties�.
Then, on the �Advanced Tab� (Figure 1) select �Environment Variables�.
Figure 1. Environment Variables Setup.
The dialog will show user variable and System variables (Figure 2).
Figure 2. Environment Variables Dialog
In the System variables area, click New, and enter the values for the variable name and value as shown in Figure 3. Note that the Variable value may be different on your system. You should set it to the name of the directory where you unzipped openjms.
Figure 3. Setting the environment variable.
If you do not have a JRE or JDK on your system, you should download and install one, and make sure that your JAVA_HOME system variable is set to its install directory. The default value, for a standard JRE installation is C:\Program Files\Java\jre1.5.0_06.
Once all these are set up, from a DOS command, change to the �bin� directory under where you installed OpenJMS, and issue the �openjms run� command. You should get output like that in Figure 4.
Figure 4. Running OpenJMS in a command console.
Build the Messaging Namespace.
The next step is to build the messaging namespace. This will contain the classes that you will use to wrap the underlying JMS APIs so they can be used simply within your applications. From Visual Studio.NET, do a File->New->Project request, and select �Class Library� from the �Visual MainWin C# for J2EE Projects� folder. (See Figure 5).
Figure 5. Creating a new System.Messaging namespace.
This will create a new class library with a single class called �Class1.cs�. Remove all the code in this library and replace it with the code for System.Messaging that is in the download for this article.
Next, you will need to add references to the JAR files for OpenJMS. You can do this by right clicking the �References� node in Solution Explorer, and selecting �Add Java Reference�. This will open a common dialog. Use it to browse to the �lib� directory underneath where you installed OpenJMS. So, for example, browse to C:\jms\openjms-0.7.7-alpha-3\lib if you unzipped the OpenJMS files to the C:\jms directory.
Pick these JARs to add references to them � it may take a few minutes to complete the import:
- 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
You should now be able to compile your class library. If you encounter any compilation errors, check that you imported all the JAR files mentioned above correctly. Failing that, the full Visual Studio solution for this library is available in the download.
Build the Message Sender
Next, you�ll build a simple console application that sends messages into the Messaging Queue. This is made very simple thanks to the class library that you built above.
To get started, select File->New->Project in Visual Studio.NET. Select �Console Application� from the �Visual MainWin C# for J2EE� folder, and give it the name �Message Sender�.
Once the solution has been created, add a JAR reference to System.Messaging.jar � the class library you built earlier. You�ll find it in its project folder unless you have already deployed it elsewhere.
Then, add the same JAR Java references that you did earlier when creating the library.
At the top of Class1.cs, add the following �using� directives: using System;
using System.Messaging;
using javax.naming;
using javax.jms;
Finally, in the Main method, you�ll add the code that implements the messaging queue. You�ll start with code that sets up the messaging environment by setting properties on its Context object: static void Main(string[] args)
{
java.util.Hashtable properties = new java.util.Hashtable();
properties.put(Context__Finals.PROVIDER_URL, "tcp://localhost: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");
To learn and understand more about these properties and what they do, check out the OpenJMS documentation.
In the rest of your Main method, you�ll send 10 messages with the current time on them into the message queue. It�s safe to run this without the listener being active. OpenJMS will handle Queueing for you until you�re ready to pop them off. 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);
}
Running this application will then send the number of messages specified in the argument to the Queue, or if there is no argument, it will send 10 as shown in Figure 6. The meat of this application is in the for loop. It simply sets up a System.Messaging.Message object (found in the class library you created earlier) and initializes its body with the string �test value� and the current date and time. It then instantiates a messagequeue object and sets it up with the local server and the queue called queue1, which is a predefined queue in OpenJMS. Then, the send method on this queue is invoked, with the message passed to it as a parameter. Very simple!
Figure 6. Running the Message Sender
At this point, the messages have now been dispatched by your MessageSender and are sitting in a Queue managed by OpenJMS waiting to be picked up. Let�s not keep them waiting too long, and write a simple reader that will pull them off the queue!
Build the Message Reader
Follow the same steps that you used to create the MessageSender project above, and create a console application called �MessageGetter� that will get the messages. Be sure to add the same references that you did for that project, namely the 8 references to OpenJMS jars, and the reference to the System.Messaging class library that you created earlier.
Then, add the same �Using� directives to the top of Class1.cs that you did earlier.
Finally, here is the Main method for your class. static void Main(string[] args)
{
java.util.Hashtable properties = new java.util.Hashtable();
properties.put(Context__Finals.PROVIDER_URL, "tcp://localhost: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);
}
}
Running this application will then give you the output from Figure 7. You will see that it receives each of the messages that were pumped out by the sender. The code is very simple to the sender. You set up a MessageQueue object, and then listen in on it with the Receive() method. This returns a message object that you can query for its contents with the �Body� property.
Figure 7. Running the Message Receiver application.
Conclusion.
Grasshopper isn�t limited to the .NET namespaces that it directly supports. As Java references can be plugged directly into your application, and Java source code can run inline with your C# or VB.NET code, you can easily use external Java APIS.
In this article you learned how to use JMS messaging on the OpenJMS server from Visual Studio.NET, and saw how easy it is to send messages into a queue and get them out. The System.Messaging class library that you implemented can easily be reused in your applications, so you can go ahead and interoperate your .NET applications with JMS through Grasshopper! |