Starting from a minimal install of Ubuntu 8.04.1, outlined below are the steps required to get a basic JMS installation running under OpenJMS and IKVM.
Install the Mono runtime and compiler tools for C# 2.0
sudo apt-get install mono-runtime mono-gmcs mono-gac mono-jit mono-utils cli-common
Download and Unpack IKVM
wget http://downloads.sourceforge.net/ikvm/ikvmbin-0.36.0.11.zip
unzip ikvmbin-0.36.0.11.zip
The IKVM.NET needs the 1.0 runtime
sudo apt-get install libmonosystem1.0-cil
Download and Unpack JMS
wget http://prdownloads.sourceforge.net/openjms/openjms-0.7.7-beta-1.tar.gz
tar -xzvf openjms-0.7.7-beta-1.tar.gz
Now the interesting part, converting OpenJMS Java byte code in to CIL instructions for the Mono C# runtime. This will convert all of the jar files in the openjms lib directory in to one assembly openjms-0.7.7-beta-1.dll to be included in any C# projects. There will be some errors spit out about MANIFEST, PROPERTY, and missing classes. These are not an issue.
cd openjms-0.7.7-beta-1/lib
mono ~/bin/ikvm-0.36.0.11/bin/ikvmc.exe -nowarn 0109 \
-nostacktraceinfo -out:openjms-0.7.7-beta-1.dll \
-r:/home/vmuser/bin/ikvm-0.36.0.11/bin/IKVM.OpenJDK.ClassLibrary.dll \
*.jar
Now a quick pause to get OpenJMS running under Java. To demonstrate any C# examples will require a working OpenJMS queue to send to.
If one is not already installed, a Java runtime environment is needed. OpenJDK from Sun will do and is in the Ubuntu package repositories.
sudo apt-get install openjdk-6-jdk
Then make sure to set the JAVA_HOME environmental variable in the .bashrc file
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk
The OpenJMS server comes with a few queues and topics already configured. To start the service run startup.sh script from the openjms-0.7.7-beta-1/bin directory. To configure other queues, topics and subscriptions edit the file ~/bin/openjms-0.7.7-beta-1/config/openjms.xml.
cd ~/bin/openjms-0.7.7-beta-1/bin
./startup.sh &
Ok, back to the code example. Below is the source to a simple C# console application that can send a text based message to queue1, a default queue in the OpenJMS server. Place this in a file called Sender.cs and compile. Notice how the Java namespaces and data types are callable from C#. Amazing stuff!
using System;
using javax.jms;
using javax.naming;
namespace BlogDemo {
public class Sender {
public static void Main(string[] args) {
Context context = null;
ConnectionFactory factory = null;
Connection connection = null;
String destinationName = null;
Destination destination = null;
Session session = null;
MessageProducer sender = null;
int count = 1;
if(args.Length < 1 || args.Length > 2) {
System.Console.WriteLine("usage: Sender [count]");
return;
}
destinationName = args[0];
if(args.Length == 2) {
count = Int32.Parse(args[1]);
}
try {
java.util.Hashtable env = new java.util.Hashtable();
env.put(Context.__Fields.INITIAL_CONTEXT_FACTORY,
"org.exolab.jms.jndi.InitialContextFactory");
env.put(Context.__Fields.PROVIDER_URL,
"tcp://localhost:3035");
context = new InitialContext(env);
factory = (ConnectionFactory) context.lookup("ConnectionFactory");
destination = (Destination) context.lookup(destinationName);
connection = factory.createConnection();
session = connection.createSession(false, Session.__Fields.AUTO_ACKNOWLEDGE);
sender = session.createProducer(destination);
connection.start();
for(int i = 0; i < count; i++) {
TextMessage message = session.createTextMessage();
message.setText("Hello " + (i + 1));
sender.send(message);
System.Console.WriteLine("Sent: " + message.getText());
}
} catch (JMSException ex) {
ex.printStackTrace();
} catch (NamingException ex) {
ex.printStackTrace();
} finally {
if(context != null) {
try {
context.close();
} catch (NamingException ex) {
ex.printStackTrace();
}
}
if(connection != null) {
try {
connection.close();
} catch (JMSException ex) {
ex.printStackTrace();
}
}
}
}
}
}
Move the dependency assemblies in to place, then compile it with gmcs.
cp ~/bin/openjms-0.7.7-beta-1/lib/openjms-0.7.7-beta-1.dll ~/bin
cp ~/bin/ikvm-0.36.0.11/bin/IKVM.OpenJDK.ClassLibrary.dll ~/bin
cp ~/bin/ikvm-0.36.0.11/bin/IKVM.Runtime.dll ~/bin
gmcs -target:exe -out:~/bin/Sender.exe \
-r:IKVM.OpenJDK.ClassLibrary.dll -r:openjms-0.7.7-beta-1.dll \
Sender.cs
Assuming that OpenJMS is running, submit 100 messages to queue name queue1
mono ./Sender.exe queue1 100