.NET Framework Interoperability with Java RMI

I’m currently working on a project that requires a connection from a .NET Framework client to a java RMI application server. I’ve never worked with java RMI before but figured it should be trivial with everything in the .NET Framework. That was so not the case, though. I’ve been working my way through examples all day, and I was able to get it working. Now that I’ve gotten this far, I must say–it’s pretty slick!

Since I’m so proud of what I accomplished, I wanted to put together my own tutorial.

What you’ll need

  • IIOP.NET source code (here)
  • Java SDK (here)
  • Visual Studio (here)

Build IIOP.NET

Once you’ve downloaded the IIOP.NET source code, extract it somewhere on your desktop. You can build it using nmake (included with Visual Studio; read more here). I had problems building the entire directory tree, but it looked like there was a problem with something in the Examples folder. So instead, I just base build by using the command nmake build-base. Most of what I needed to complete this example could be found in the folder IDLToCLSCompiler\IDLCompiler\bin. In addition to those three files, I also needed to copy orb.idl from IDLToCLSCompiler\ILD.

Building the java server

The java server can be built with just a few, small files. Open up your favorite text editor, and create the following files. Note that your directory structure should correspond to the package names.

When you’re done, you should have a directory structure that looks like this:

\
-ILDPreprocessor.dll*
-IDLToCLSCompiler.exe*
-IIOPChannel.dll*
-MySearchServer.java
-orb.idl*
\adamprescott\wordpress\
-SearchRequest.java
-SearchResponse.java
-SearchServer.java
-SearchServerImpl.java

* denotes the files copied after building IIOP.NET

SearchRequest.java

package adamprescott.wordpress;

import java.io.Serializable;

public class SearchRequest implements Serializable  {

	public String Criteria;

}

SearchResponse.java

package adamprescott.wordpress;

import java.io.Serializable;

public class SearchResponse implements Serializable  {

	public String Response;

}

SearchServer.java

package adamprescott.wordpress;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface SearchServer extends Remote {

	public SearchResponse[] Search(SearchRequest request) throws RemoteException;

}

SearchServerImpl.java

package adamprescott.wordpress;

import java.rmi.Remote;
import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;

public class SearchServerImpl extends PortableRemoteObject implements SearchServer {

	public SearchServerImpl() throws java.rmi.RemoteException {
		super();     // invoke rmi linking and remote object initialization
	}

	public SearchResponse[] Search(SearchRequest request) throws RemoteException {
		SearchResponse[] response = new SearchResponse[1];
		response[0] = new SearchResponse();
		response[0].Response = "You searched for " + request.Criteria + "!";
		return response;
	}
}

And, finally, MySearchServer.java

import javax.naming.InitialContext;
import javax.naming.Context;
import javax.rmi.PortableRemoteObject;
import adamprescott.wordpress.SearchServer;
import adamprescott.wordpress.SearchServerImpl;

public class MySearchServer {

	public static void main(String[] args) {
		try {
			
			// Instantiate the service
			SearchServerImpl searchSvr = new SearchServerImpl();

			// publish the reference with the naming service:
			Context initialNamingContext = new InitialContext();
			initialNamingContext.rebind("searchServer", searchSvr);

			System.out.println("Server Ready...");

		} catch (Exception e) {
			System.out.println("Trouble: " + e); e.printStackTrace();
		}
	}
}

Now that you’ve got all the files, compile and run the code by executing the following commands:

javac -classpath . MySearchServer.java
rmic -classpath . -iiop adamprescott.wordpress.SearchServerImpl
rmic -idl adamprescott.wordpress.SearchServerImpl
IDLToCLSCompiler.exe -o N_SOURCES\bin MySearchServer adamprescott\wordpress\SearchServer.idl
start orbd -ORBInitialPort 1050 
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://localhost:1050 -cp . MySearchServer

Building the .NET client

The hard work is all done now, and we just need to create our .NET client. When you ran IDLToCLSCompiler.exe, it created a DLL file for you in the specified folder, N_SOURCES\bin. Making a functional client involves referencing this DLL along with IIOPChannel.dll. Create a new console project, reference those DLLs, and create your Program.cs like so:

using System;
using System.Runtime.Remoting.Channels;
using Ch.Elca.Iiop;
using Ch.Elca.Iiop.Services;
using omg.org.CosNaming;

namespace adamprescott.wordpress
{
    [Serializable] public class SearchRequestImpl : SearchRequest {}
    [Serializable] public class SearchResponseImpl : SearchResponse {}

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                const string nameServiceHost = "localhost";
                const int nameServicePort = 1050;

                // register the channel
                IiopClientChannel channel = new IiopClientChannel();
                ChannelServices.RegisterChannel(channel);

                // access COS nameing service
                CorbaInit init = CorbaInit.GetInit();
                NamingContext nameService = init.GetNameService(nameServiceHost, nameServicePort);
                var name = new[] { new NameComponent("searchServer", "") };
                
                // get the reference to the adder
                var adder = (SearchServer)nameService.resolve(name);

                var req = new SearchRequestImpl { Criteria = "Hello, World!"};
                var result = adder.Search(req);

                foreach (var r in result)
                    Console.WriteLine("result: {0}", r.Response);
            }
            catch (Exception e)
            {
                Console.WriteLine("exception: " + e);
            }

            Console.ReadLine();
        }
    }
}

Important notes:

  • Each java class must have a *Impl implementation. The reason for this is that the java classes are exported as abstract. If there were any abstract methods, they would need to be implemented as well. Since my classes only contain properties, no additional implementation is needed.
  • The .NET classes must be public, have a public parameterless constructor, and be tagged as Serializable.
  • The java and .NET classes must have the same namespaces. (This threw me off for a while!)

With the java server running, start up the .NET client and feel like a winner!

Advertisements

2 thoughts on “.NET Framework Interoperability with Java RMI”

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s