Migrating Java RMI to .NET Remoting

Introduction

 
.NET and J2EE are both widely used technologies for creating Middleware solutions. Sometimes we do have code that can get us more benefit from running on the .NET framework and some of the code exists in the J2EE application already. And also to achieve the best of everything in a short time, we sometimes 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 the 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 used in our process of migration to .NET Remoting. This small application will accept a name from the client and return a welcome message.
 
The RMI Solution
 
Our RMI Solution will comprise of:
  • A remote Interface 
  • A remotable class that implements the interface
  • A Server that 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 implemented by a remotable class.
  1. import java.rmi.Remote;    
  2. import java.rmi.RemoteException;    
  3. public interface RemoteInterface extends Remote    
  4. {     
  5.           public void WriteName(String str) throws RemoteException;    
  6.           public String ReadWelcome() throws RemoteException;    
  7. }    
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. 
  1. import java.rmi.RemoteException;    
  2. public class RemoteClass implements RemoteInterface {    
  3.           private static String strWelcomeClient;    
  4.           RemoteClass ()    
  5.           {    
  6.                     System.out.println("Object created");    
  7.           }    
  8.           public String ReadWelcome()    
  9.           {     
  10.                     return strWelcomeClient;    
  11.           }    
  12.           public void WriteName(String strNameFromClient)    
  13.           {    
  14.                 strWelcomeClient = "HI " + strNameFromClient +     
  15.             ". Welcome to RMI World!!";     
  16.       }    
  17. }   
Our remote object class must implement the remote interface (RemoteInterface).  And since we don’t throw any exceptions, 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.
  1. import java.rmi.registry.Registry;  
  2. import java.rmi.registry.LocateRegistry;  
  3. import java.rmi.RemoteException;  
  4. import java.rmi.server.UnicastRemoteObject;  
  5. public class Server  
  6. {  
  7.           public Server() {}  
  8.           public static void main(String args[])  
  9.           {  
  10.                     try  
  11.                     {  
  12.                              RemoteClass robj = new RemoteClass();  
  13.                              RemoteInterface stub = (RemoteInterface)  
  14.                                        UnicastRemoteObject.exportObject(robj, 0);  
  15.                              Registry registry = LocateRegistry.getRegistry ();  
  16.                              registry.bind("cincom", stub);  
  17.                              System.out.println("The Server is ready .... Press the  
  18.                   enter key to exit...");         
  19.                     }  
  20.                     catch (Exception e)  
  21.                     {  
  22.                              System.err.println("Server exception thrown: " +  
  23.                   e.toString());  
  24.                     }  
  25.           }  
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.
  1. import java.rmi.registry.LocateRegistry;  
  2. import java.rmi.registry.Registry;  
  3.    
  4. public class Client  
  5. {  
  6.           private static RemoteInterface stub = null;  
  7.           private Client() {}  
  8.           public static void main(String[] args)  
  9.           {  
  10.                     try  
  11.                     {  
  12.                              Registry reg = LocateRegistry.getRegistry("localhost");  
  13.                   // localhost  OR your server name                                                                     
  14.                              stub = (RemoteInterface) reg.lookup("cincom");  
  15.                     }  
  16.                     catch (Exception e)  
  17.                     {  
  18.                              System.err.println("Client exception thrown: " +  
  19.                   e.toString());  
  20.                     }  
  21.                     String strArgs;  
  22.                     if (args.length == 0)  
  23.                     {  
  24.                              strArgs = "Client";  
  25.                     }  
  26.                     else  
  27.                     {  
  28.                              strArgs = args[0];  
  29.                     }  
  30.                     try  
  31.                     {  
  32.                              stub.WriteName(strArgs);     
  33.                              System.out.println(stub.ReadWelcome());  
  34.                     }  
  35.                     catch(Exception e)  
  36.                     {  
  37.                              System.out.println("Remote method exception thrown: " +  
  38.                   e.getMessage());               
  39.             }  
  40.           }                   
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 an 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 that implements the interface
  • A Server that 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 creates a csharp file call RemoteInterface.cs and paste the following code.
  1. public interface RemoteInterface  
  2. {   
  3.           void WriteName(string str);   
  4.           string ReadWelcome();  
The Implementation
 
Inside the Remoting folder create another java file call RemoteClass.cs and paste the following code.
  1. using System;  
  2. public class RemoteClass : MarshalByRefObject, RemoteInterface  
  3. {    
  4.           private static string strWelcomeClient;  
  5.           RemoteClass()  
  6.           {  
  7.                     Console.WriteLine("Object created");  
  8.           }  
  9.           public string ReadWelcome()  
  10.           {     
  11.                     return strWelcomeClient;     
  12.           }  
  13.           public void WriteName(string strNameFromClient)  
  14.           {         
  15.                     strWelcomeClient = "HI " + strNameFromClient +  
  16.             ". Welcome to Remoting World!!";  
  17.           }  
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.
  1. using System;  
  2. using System.Runtime.Remoting;  
  3. using System.Runtime.Remoting.Channels;  
  4. using System.Runtime.Remoting.Channels.Tcp;  
  5.    
  6. public class Server  
  7. {  
  8.           public static Main(string [] args)  
  9.           {   
  10.                     TcpChannel channel = new TcpChannel(8888);  
  11.                     ChannelServices.RegisterChannel(channel);    
  12.       
  13.                     RemotingConfiguration.RegisterWellKnownServiceType(  
  14.                              typeof(RemoteClass), "cincom",   
  15.                   WellKnownObjectMode.SingleCall );  
  16.            
  17.                     System.Console.WriteLine("The Server is ready .... Press the  
  18.                   enter key to exit...");  
  19.                     System.Console.ReadLine();  
  20.         }  
In object activation, Marshal By Value objects have a simple activation scheme, they are created 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 objects 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.
  1. using System;  
  2. using System.Runtime.Remoting;  
  3. using System.Runtime.Remoting.Channels;  
  4. using System.Runtime.Remoting.Channels.Tcp;  
  5.    
  6. public class Client  
  7. {  
  8.           public static Main(string [] args)  
  9.           {  
  10.                     TcpChannel chan = new TcpChannel();  
  11.                     ChannelServices.RegisterChannel(chan);  
  12.    
  13.                     // Create an instance of the remote object  
  14.                     RemoteInterface obj = (RemoteInterface) Activator.GetObject(  
  15.                              typeof(RemoteInterface), "tcp://localhost:8888/cincom" );  
  16.             // localhost  OR your server name  
  17.                     if( obj.Equals(null) )  
  18.                     {  
  19.                              System.Console.WriteLine("Error: unable to locate server");  
  20.                     }  
  21.                     else  
  22.                     {                      
  23.                              String strArgs;  
  24.                              if (args.Length == 0)  
  25.                              {  
  26.                                        strArgs = "Client";  
  27.                              }  
  28.                              else  
  29.                              {  
  30.                                        strArgs = args[0];  
  31.                              }  
  32.                              obj.WriteName(strArgs);                          
  33.                              System.Console.WriteLine(obj.ReadWelcome());  
  34.                     }         
  35.         }  
  36. }  
  37.   
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 Server 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 an 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 that 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.
  1. using System;  
  2. public class RemoteClass : MarshalByRefObject  
  3. {         
  4.           private static string strWelcomeClient;     
  5.           public RemoteClass()  
  6.           {  
  7.                     Console.WriteLine("Object created");  
  8.           }     
  9.           public string ReadWelcome()  
  10.           {                   
  11.                     return strWelcomeClient;               
  12.           }     
  13.           public void WriteName(string strNameFromClient)  
  14.           {                   
  15.                     strWelcomeClient = "HI " + strNameFromClient +  
  16.             ". Welcome to Remoting World!!";                   
  17.         }  
The Server  
 
Create a console application project called Server. Add a reference to the RemoteClass.dll and add a class (Server) as below. 
  1. using System;  
  2. using System.Runtime.Remoting;  
  3. using System.Runtime.Remoting.Channels;  
  4.    
  5. public class Server  
  6. {  
  7.           public static  Main(string [] args)  
  8.           {                   
  9.                     RemotingConfiguration.Configure("Server.exe.config");  
  10.                     System.Console.WriteLine("The Server is ready .... Press the  
  11.             enter key to exit...");  
  12.                     System.Console.ReadLine();  
  13.         }  
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.
  1. <configuration>  
  2.           <system.runtime.remoting>  
  3.       <application>  
  4.         <service>  
  5.             <wellknown  
  6.               mode="SingleCall"  
  7.               type="RemoteClass, RemoteClass"  
  8.               objectUri="RemoteClass.rem"  
  9.             />  
  10.         </service>  
  11.         <channels>  
  12.             <channel ref="http" port="8888"/>  
  13.         </channels>  
  14.       </application>  
  15.   </system.runtime.remoting>  
  16. </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.
  1. using System;  
  2. using System.Runtime.Remoting;  
  3. using System.Runtime.Remoting.Channels;  
  4.    
  5. public class Client  
  6. {  
  7.           public static Main(string [] args)  
  8.           {                   
  9.                     RemotingConfiguration.Configure("Client.exe.config");  
  10.                     RemoteClass obj = new RemoteClass();  
  11.    
  12.                     if( obj.Equals(null) )  
  13.                     {  
  14.                              System.Console.WriteLine("Error: unable to locate server");  
  15.                     }  
  16.                     else  
  17.                     {                      
  18.                              String strArgs;  
  19.                              if (args.Length == 0)  
  20.                              {  
  21.                                         strArgs = "Client";  
  22.                              }  
  23.                              else  
  24.                              {  
  25.                                        strArgs = args[0];  
  26.                              }  
  27.                              obj.WriteName(strArgs);                          
  28.                              System.Console.WriteLine(obj.ReadWelcome());  
  29.                              System.Console.ReadLine();  
  30.                     }                   
  31.         }  
Add an app.config file to you project and add the following entries:
  1. <configuration>  
  2.           <system.runtime.remoting>  
  3.       <application>  
  4.         <client>  
  5.             <wellknown  
  6.               type="RemoteClass, RemoteClass"  
  7.               url="http://localhost:8888/RemoteClass.rem"  
  8.             />  
  9.         </client>  
  10.       </application>  
  11.           </system.runtime.remoting>  
  12. </configuration> 
If you are running on a 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!!