Tuesday, September 2, 2008

OpenJMS From C#

One of the problems many enteprise programmers struggle with, and see as a barrier to begin using C# on Linux at work, is the lack of support for MSMQ and messaging. The good news is mature messaging exists in Java in the form of JMS implementations. With packages like IKVM, C# coders can take advantage of these Java messaging technologies.

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

Monday, September 1, 2008

Ubutu 8.04.1 Install Notes

Constantly having to install Ubuntu at home, for co-workers, or family members. This is a consolidated place to keep and share notes with others. The goal of this mini-guide, is to achieve a minimal Ubuntu installation, with XFCE4 as the window manager.


  1. Download the CD from the web site for the server edition, it installs no window manager by default, which will be done later our way
    mkdir -p /home/vmuser/downloads/iso
    cd /home/vmuser/downloads/iso
    wget http://releases.ubuntu.com/hardy/ubuntu-8.04.1-server-i386.iso


  2. Perform a minimal install, no MySQL, Apache, etc...


  3. Remove apparmor, basically SELinux for Ubuntu
    sudo /etc/init.d/apparmor stop
    sudo update-rc.d -f apparmor remove
    sudo apt-get remove apparmor apparmor-utils


  4. Install OpenSSH for remote access
    sudo apt-get install openssh-server ssh


  5. Install XFCE4, with a couple of useful tools
    sudo apt-get install xfce4 xserver-xorg xfonts-base xfce4-terminal mousepad


  6. Install Firefox
    sudo apt-get install firefox


  7. Install VMware Server 1.0.6
    sudo apt-get install libxtst6
    mkdir -p /home/vmuser/src
    cd /home/vmuser/src
    tar -xzvf /home/vmuser/downloads/VMware-server-1.0.6-91891.tar.gz
    cd vmware-server-distrib
    sudo ./vmware-install.pl
    cd /usr/lib/vmware/lib
    mv libpng12.so.0/libpng12.so.0 libpng12.so.0/libpng12.so.0.bak
    sudo ln -sf /usr/lib/libpng12.so.0 libpng12.so.0/libpng12.so.0
    mv libgcc_s.so.1/libgcc_s.so.1 libgcc_s.so.1/libgcc_s.so.1.bak
    sudo ln -sf /usr/lib/libgcc_s.so.1 libgcc_s.so.1/libgcc_s.so.1