Migrating Java RMI to .NET Remoting

.Net Remoting and Java RMI are mechanisms that allow the user to invoke method/methods in another address space. The other address space could be on the same machine or a different one. These two mechanisms can be regarded as RPC in an object-oriented fashion. This article describes how to migrate java RMI applications to .NET Remoting applications, with practical examples.


Introduction

.NET and J2EE are both widely used technologies for creating Middleware solutions. Sometime we do have code that can get us more benefit from running on the .NET framework and some of the code exists in J2EE application already. And also to achieve the best of everything in short time, we sometime need to migrate our existing code to another environment instead of redesigning and rewriting them. For many customers, migration of technology will happen over time and there is a huge opportunity exists in migration space.

In these two technologies, both .Net Remoting and Java RMI are mechanisms that allow the user to invoke method/methods in another address space. The other address space could be on the same machine or a different one. These two mechanisms can be regarded as RPC in an object-oriented fashion. This article describes how to migrate java RMI applications to .NET Remoting applications, with practical examples.

Before the migration process starts, we can make a comparison of these two concepts as:

 

 

Java RMI vs. DotNet Remoting:

Java RMI VS .NET Remoting .NET Remoting Java RMI
Proxy Dynamics Statics (rmic) or dynamics
Skeletons Integrated into Framework Integrated into Framework
Distributed object Classes / Remote Interfaces Remote Interfaces
Configuration File XML/ System Property System Property
Distributed directory No RmiRegistry
Addition of protocols Channels SocketFactoryImpl
Addition of formats Formatters Serialization
Activation Server (SingleCall or Singleton) and Client activated API with dimensions waiter Activable objects
CustomProxy Custom RealProxy Dynamic Proxy
Existing protocols HTTP, TCP, SOAP JRMP, IIOP, ORMI (Orion), T3 in WebLogic
Management of error Remote Exceptions Remote Exceptions

The Migration

Let us start our migration by creating a simple RMI application that will be use in our process of migration to .NET Remoting. This small application will accept a name from client and return a welcome message.

The RMI Solution

Our RMI Solution will comprise of:

  • A remote Interface 
  • A remotable class which implements the interface
  • A Server which will sit and listen for object requests 
  • A Client that will make requests for the remotable object

Now create a folder Called RMISample. We will use this as our default folder for the RMI solution.

The Remote Interface

Create a java file call RemoteInterface.java and paste the following code. It contains two methods that will be implementing by a remotable class.

import java.rmi.Remote;

import java.rmi.RemoteException;

public interface RemoteInterface extends Remote

{ 

          public void WriteName(String str) throws RemoteException;

          public String ReadWelcome() throws RemoteException;

}

The Implementation

Create a java file call RemoteClass.java and paste the following code. Here we are implementing the remote methods ReadWelcome and WriteName. We will get a name (string) from the ReadWelcome method and will return a welcome message to the client application. 

import java.rmi.RemoteException;

public class RemoteClass implements RemoteInterface {
         
private static String strWelcomeClient;
          RemoteClass ()
          {
                    System.
out.println("Object created");
          }
         
public String ReadWelcome()
          { 
                   
return strWelcomeClient;
          }
         
public void WriteName(String strNameFromClient)
          {
                strWelcomeClient = "HI " + strNameFromClient + 
            ". Welcome to RMI World!!"; 
      }
}


Our remote object class must implement the remote interface (RemoteInterface).  And since we doesn’t throw any exception, we can omit the import of RemoteException.

The Server Application

Create a java file call Server.java and paste the following code.  In this application, we are creating an instance of the remote object and exporting it. Finally we bind this instance to the RMI registry. Here I am using cincom as the binding name.

import java.rmi.registry.Registry;

import java.rmi.registry.LocateRegistry;

import java.rmi.RemoteException;

import java.rmi.server.UnicastRemoteObject;

public class Server
{
         
public Server() {}
         
public static void main(String args[])
          {
                   
try
                    {
                             RemoteClass robj =
new RemoteClass();
                             RemoteInterface stub = (RemoteInterface)
                                       UnicastRemoteObject.exportObject(robj, 0);
                             Registry registry = LocateRegistry.getRegistry ();
                             registry.bind("cincom", stub);
                             System.
out.println("The Server is ready .... Press the
                  enter key to exit...");       
                    }
                   
catch (Exception e)
                    {
                             System.err.println("Server exception thrown: " +
                  e.toString());
                    }
          }
}

The exportObject() method takes two parameters, the instance of the remote object and the TCP port number. Here we are passing 0 for the default port number of RMI which is 1099.

The Client Application

To call our remote method, we need to create a Client application. Now create a java file call Client.java and paste the following code. Before calling the remote method, we should locate the host from the registry mechanism and then look up the remote object by its name.  In our server application, we used cincom as the name of the object. So we are using this name cincom for the lookup again.
 

import java.rmi.registry.LocateRegistry;

import java.rmi.registry.Registry;

public class Client

{

          private static RemoteInterface stub = null;

          private Client() {}

          public static void main(String[] args)

          {

                    try

                    {

                             Registry reg = LocateRegistry.getRegistry("localhost");
                 
// localhost  OR your server name                                                                   

                             stub = (RemoteInterface) reg.lookup("cincom");

                    }

                    catch (Exception e)

                    {

                             System.err.println("Client exception thrown: " +
                  e.toString());

                    }

                    String strArgs;

                    if (args.length == 0)

                    {

                             strArgs = "Client";

                    }

                    else

                    {

                             strArgs = args[0];

                    }

                    try

                    {

                             stub.WriteName(strArgs);   

                             System.out.println(stub.ReadWelcome());

                    }

                    catch(Exception e)

                    {

                             System.out.println("Remote method exception thrown: " +
                  e.getMessage());             
            }

          }                 

}

Running Application

  • open a dos command prompt
  • change the current working directory to your RMI directory …/RMISample/
  • compile all the java files using  java –d .  *.java
  • Note: If you are using jdk below 1.5.0, you must use rmic utility to generate a stub class  using rmic –v1.2 Server
  • run the rmiregistry using start rmiregistry
  • start the Server using start java Server
  • run the Client with a name as argument using Client TestName

You will get an output as

HI TestName. Welcome to RMI World!!

Migrating the application to .NET Remoting

Introduction

The migration can be done in two ways. First, we can do the migration page by page (class by class). And in another (general) technique, we can have a remotable class, a server and a client with configuration files to set up our channels and formatters. Now let us start the migration using the first technique.

First Technique

In this technique, we will do the migration page by page (class by class). Parallel to the RMI application, our .NET Remoting system will comprise of:

  • An Interface 
  • A remotable class which implements the interface
  • A Server which will sit and listen for object requests 
  • A Client that will make requests for the remotable object

The Project

Create a folder Called Remoting.

The Interface

Inside the Remoting folder create a csharp file call RemoteInterface.cs and paste the following code.

public interface RemoteInterface
{ 
         
void WriteName(string str); 
         
string ReadWelcome();
}

The Implementation

Inside the Remoting folder create another java file call RemoteClass.cs and paste the following code.

using System;

public class RemoteClass : MarshalByRefObject, RemoteInterface

{  

          private static string strWelcomeClient;

          RemoteClass()

          {

                    Console.WriteLine("Object created");

          }

          public string ReadWelcome()

          {   

                    return strWelcomeClient;   

          }

          public void WriteName(string strNameFromClient)

          {       

                    strWelcomeClient = "HI " + strNameFromClient +
            ". Welcome to Remoting World!!";

          }
}

Here we are implementing the methods ReadWelcome and WriteName.

The Server Application

Again inside the Remoting folder create one more java file call RemoteClass.cs and paste the following code.  For communication among applications and appDomains, .NET framework includes two default channels:

  • HttpChannel (using SOAP formatting)
  • TcpChannel (using binary formatting)

Here we are using TcpChannel.

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Tcp;

 

public class Server

{

          public static Main(string [] args)

          { 

                    TcpChannel channel = new TcpChannel(8888);

                    ChannelServices.RegisterChannel(channel);  

    

                    RemotingConfiguration.RegisterWellKnownServiceType(

                             typeof(RemoteClass), "cincom", 
                  WellKnownObjectMode.SingleCall );

         

                    System.Console.WriteLine("The Server is ready .... Press the
                  enter key to exit...");

                    System.Console.ReadLine();

        }
}


In object activation, Marshal By Value objects have a simple activation scheme, they are crerated when the client first requests them. But Marshal By Reference objects have two activation schemes:

  • Server Activated Objects (SAO)
  • Client Activated Objects (CAO)

Server activated objects have two registration types, Singleton and SingleCall.  Singleton objects are instantiated one time only, and services all client requests in a multi-threaded fashion. SingleCall object are at the other extreme, every time a remote method is invoked on these types of SAO a new remote object is created. In our case we are using SingleCall type.

The Client Application

Now create another folder call Client. Copy the RemoteInterface.cs file and create another file Client.cs inside that folder. Now paste the following code to that new file.

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Tcp;

 

public class Client

{

          public static Main(string [] args)

          {

                    TcpChannel chan = new TcpChannel();

                    ChannelServices.RegisterChannel(chan);

 

                    // Create an instance of the remote object

                    RemoteInterface obj = (RemoteInterface) Activator.GetObject(

                             typeof(RemoteInterface), "tcp://localhost:8888/cincom" );

            // localhost  OR your server name

                    if( obj.Equals(null) )

                    {

                             System.Console.WriteLine("Error: unable to locate server");

                    }

                    else

                    {                    

                             String strArgs;

                             if (args.Length == 0)

                             {

                                       strArgs = "Client";

                             }

                             else

                             {

                                       strArgs = args[0];

                             }

                             obj.WriteName(strArgs);                        

                             System.Console.WriteLine(obj.ReadWelcome());

                    }       

        }
}

 

Running Application

  • open Visual studio command prompt from Visual studio tools.
  • change the Current working directory to your remoting directory …/Remoting/
  • compile all the csharp files using  csc *.cs
  • run the Srver using start Server
  • change the current working directory to your client folder …/Client/
  • compile all the csharp files using  csc *.cs
  • run the Client with a name (TestName) as argument using Client TestName

You will get an output as

HI TestName. Welcome to Remoting World!!

Second Technique  

This time we will follow the general .NET Remoting technique and we will use configuration files to set up our channels and formatters.  This time our .NET Remoting system will comprise of:

  • A remotable object (Abstract class and implementation) 
  • A Sever console application which will sit and listen for object requests 
  • Configuration file for the Server
  • A Client console application that will make requests for the remotable object 
  • Configuration file for the Client.

The Remotable object

Create a new class library project called and add the following class (RemoteInterface) to the project and compile it. From this process we will get RemoteClass.dll.

using System;

public class RemoteClass : MarshalByRefObject

{       

          private static string strWelcomeClient;   

          public RemoteClass()

          {

                    Console.WriteLine("Object created");

          }   

          public string ReadWelcome()

          {                 

                    return strWelcomeClient;             

          }   

          public void WriteName(string strNameFromClient)

          {                 

                    strWelcomeClient = "HI " + strNameFromClient +
            ". Welcome to Remoting World!!";                 

        }
}

 

The Server  

Create a console application project called Server. Add a reference to the RemoteClass.dll and add a class (Server) as below. 

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

 

public class Server

{

          public static  Main(string [] args)

          {                 

                    RemotingConfiguration.Configure("Server.exe.config");

                    System.Console.WriteLine("The Server is ready .... Press the
            enter key to exit...");

                    System.Console.ReadLine();

        }
}

To configure through a configuration file, add an app.config file and add the following lines. As in earlier case, we are using SingleCall activation type.

<configuration>

          <system.runtime.remoting>

      <application>

        <service>

            <wellknown

              mode="SingleCall"

              type="RemoteClass, RemoteClass"

              objectUri="RemoteClass.rem"

            />

        </service>

        <channels>

            <channel ref="http" port="8888"/>

        </channels>

      </application>

  </system.runtime.remoting>
</
configuration>

The Client Application

Create another console application project called Client. Add a reference to the RemoteClass.dll and add a class (Client) as below.

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

 

public class Client

{

          public static Main(string [] args)

          {                 

                    RemotingConfiguration.Configure("Client.exe.config");

                    RemoteClass obj = new RemoteClass();

 

                    if( obj.Equals(null) )

                    {

                             System.Console.WriteLine("Error: unable to locate server");

                    }

                    else

                    {                    

                             String strArgs;

                             if (args.Length == 0)

                             {

                                        strArgs = "Client";

                             }

                             else

                             {

                                       strArgs = args[0];

                             }

                             obj.WriteName(strArgs);                        

                             System.Console.WriteLine(obj.ReadWelcome());

                             System.Console.ReadLine();

                    }                 

        }
}

Add an app.config file to you project and add the following entries:

<configuration>

          <system.runtime.remoting>

      <application>

        <client>

            <wellknown

              type="RemoteClass, RemoteClass"

              url="http://localhost:8888/RemoteClass.rem"

            />

        </client>

      </application>

          </system.runtime.remoting>

</configuration>

If you are running in different machine than, instead of localhost, use the name of the computer where the Server application is running.

Running Application

  • Run the Server application.
  • You will get a message as

The Server is ready .... Press the enter key to exit...

  • Run the Client application

You will get an output as

HI Client. Welcome to Remoting World!!