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!!