Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / Java
Article

Building a Distributed Object System with .NET and J2EE Using IIOP.NET

Rate me:
Please Sign up or sign in to vote.
4.88/5 (49 votes)
1 Jul 20037 min read 302.6K   3.6K   95   53
This article demonstrates the use of IIOP.NET

Introduction

In Microsoft's vision, the next generation of distributed systems will communicate with WebServices. WebServices are great when it comes to integrate heterogeneous loosely coupled systems, but they have their limitations too: they have no support for remote object references. In practice, they are stateless and closer to a remote method call than to a distributed object system. Furthermore, SOAP and XML are by no means a compressed format and tend to be quite verbose.

.NET and J2EE are two similar but disjointed worlds: they currently can interact together only using WebServices. Both platforms offer great mechanisms for building tightly coupled distributed object systems: .NET's Remoting and Java's RMI, but sadly these rely on incompatible standards. Luckily, .NET's remoting is highly configurable: a different formatter for the serialization and deserialization of the objects together with a different transport channel can be easily provided.

Fig.1: Overview of a .NET channel
Image 1

This article shows how the .NET and J2EE platforms can tightly interoperate together, as it is often needed when developing distributed enterprise applications. For this purpose, we use an open-source custom remoting channel called IIOP.NET.

About IIOP.NET

IIOP.NET is a .NET remoting channel based on the IIOP protocol. IIOP is the protocol defined by the CORBA standard, the same used by Java's RMI/IIOP. IIOP.NET acts as an ORB (a CORBA object request broker); it converts .NET's type system to CORBA's type system and back, making the objects defined in your application accessible to other ORBs. RMI/IIOP implements a subset of the ORB functionalities (due to some limitations in Java's type system) and provides the same features as IIOP.NET for the J2EE platform.

Fig.2: Overview of a the distributed object system
Image 2

Using IIOP.NET is almost as simple as using the built-in remoting. The following example will show you how to access a .NET service from Java using IIOP.NET.

IIOP.NET is an open-source project hosted on sourceforge (http://iiop-net.sourceforge.net/). It was developed by Dominic Ullmann as part of his diploma thesis at ETH-Z; further work is now sponsored by his current employer (http://www.elca.ch).

Not surprisingly, IIOP.NET is not the only software you can use for this purpose. First, the open-source project Remoting.Corba is quite similar in its goals, but has no generator for creating the IDL from a dll and currently does not support CORBA's valuetypes; second, Janeva from Borland promises to do the same, but is neither free nor available yet (should be released in summer '03). We choose IIOP.NET because it is free, currently available, and has a tool to generate the IDL automatically.

The example: accessing a generic collection service

Your problem: you just implemented a great service using .NET, but your customer insists on using a Java client; You cannot use WebServices, because the client software needs to keep references to the single objects on the server: this is just not possible using WebServices unless you implement your own naming service, lease manager, and distributed garbage collection. A more appropriate approach is to use RMI/IIOP on the Java side and IIOP.NET on the .NET side.

This article is constructed around a non-trivial example (the GenericCollection tutorial in the IIOP.NET release: a .NET server provides access to a set of collections consisting of key / value pairs. A client can grab a collection, modify it by adding more pairs, or querying it about the pairs it contains. This requires the client to hold references to the objects on the server.

For the sake of simplicity, we will concentrate on the object distribution, and skip all the concurrency-related problems.

Step 1: install IIOP.NET

You will find a few directories:

  • IIOPChannel contains the channel code
  • CLSToIDLGenerator contains a generator to create the IDL definition files from a .NET assembly
  • Examples contains the examples and tutorials code. The one presented in this article is GenericCollections.

To be able to use IIOP.NET, you need Microsoft's .NET Frameword (1.0 or 1.1) and the C# compiler. The Java part of the demo requires any Java system supporting RMI/IIOP (e.g. Sun's Java SDK 1.4).

To install IIOP.NET, first unpack it; them copy the ir.idl and orb.idl files from your Java SDK lib directory into IIOP.NET's IDL directory. Compile by executing nmake in the main directory.

Step 2: define the service

When you define a .NET service, you have the choice between objects marshalled by reference, which subclass MarshalByRefObject, and objects marshalled by value, which implement ISerializable or are decorated with SerializableAttribute. In the GenericCollections example, the objects (without implementation) are defined as:

C#
namespace Ch.Elca.Iiop.Demo.StorageSystem {
         [Serializable]
         public struct Entry {
                 public string key;
                 public string value;
         }
         public class Container: MarshalByRefObject {
                 public Container() {...}
                 public Entry[] Enumerate() {...}
                 public void    SetValue(string key, string value) {...}
                 public void    SetEntry(Entry e) {...}
                 public String  GetValue(string key) {...}
         }
         public class Manager: MarshalByRefObject {
                 public Manager() {...}
                 public Container   CreateContainer() {...}
                 public Container[] FilterContainers(Entry[] filter) {...}
                 public void        DeleteContainer(Container c) {...}
         }
}

In practice, Manager and Container objects stay on the server. The client merely receives a remote reference to them and works with a proxy object that serializes (i.e. encodes) the method calls and forwards them to the server. On the other hand, Entry structures are entirely copied to the client, which works with its own Entry clones.

You can now make the managed object available to the rest of the (IIOP) world:

C#
public class Server {
    [STAThread]
    public static void Main(string[] args) {
        // register the channel
        int port = 8087;
        IiopChannel chan = new IiopChannel(port);
        ChannelServices.RegisterChannel(chan);
        // publish the adder
        Manager manager = new Manager();
        string objectURI = "manager";
        RemotingServices.Marshal(manager, objectURI);
         
        Console.WriteLine("server running");
        Console.ReadLine();
    }
}

The above code installs an ORB listening on the URI iiop://localhost:8087/, and registers a manager instance under the name "manager" to all channels. The manager object will handle all requests (in fact, this is a server-activated singleton object).

Step 3: create the IDL description

To be able to access these objects from Java, their definition must be made available. Because Java does not understand .NET's metadata, we create a description of the objects using the IDL format using the IIOP.NET's CLSToIDLGenerator tool; this tool takes as input one type and one assembly, and emits the corresponding IDL definition file. It also recursively emits the definitions for all other types used.

Calling

CLSToIDLGenerator Ch.Elca.Iiop.Demo.StorageSystem.Manager Service.dll

generates the description for the Manager type (the full type name is required) defined in the Service.dll assembly and for all other types used by Manager. Manager.idl, Container.idl, and Entry.idl are created.

Step 4: create the Java stubs from the IDL

The Java SDK provides the idlj compiler to generate the java stubs for the IDL files. Note that you will need two more IDL files present in your Java SDK: orb.idl and ir.idl, which contain all the predefined CORBA objects for your Java platform.

Step 5: implement the client

You can now implement a client, which accesses the remote objects defined previously.

import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import Ch.Elca.Iiop.GenericUserException;
import Ch.Elca.Iiop.Demo.StorageSystem.*;

Manager m = null;
try {
         InitialContext ic = new InitialContext();
         Object obj = ic.lookup("manager");
         m = (Manager) PortableRemoteObject.narrow(obj, Manager.class);
         ... use m ...
} catch (Exception e) {
         System.out.println("Exception: " + e.getMessage());
}

This code retrieves a reference to the remote object. Now you can call the methods defined in the remote object just like normal methods:

Container c = m.CreateContainer();
c.SetValue("name","Patrik");

There is still one catch: you must write and implement the class EntryImpl . The Manager and Container types are accessed by reference, i.e. idlj generates a proxy that forwards all method calls to the server. The Entry structure instead is copied to the client (this corresponds to the classes extending marked as serializable in .NET, and to the valuetypes in CORBA): thus, you need to provide a local implementation for all its methods (idlj just provides an abstract class):

package Ch.Elca.Iiop.Demo.StorageSystem;
public class EntryImpl extends Entry { }

Because Entry has no methods to be implemented(only fields), its implementation is simple and consists of an empty class definition.

Step 6: run the client and the server

As a last step, run the distributed application. First, start the server:

D:\Demo\net:> Server
server running

and then the client:

java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory 
         -Djava.naming.provider.url=iiop://localhost:8087 Client

The internet address part of the URL is passed to the JVM in order to tell RMI/IIOP where to find the naming service.

The java client will prompt you for an operation to perform. First input "1" to create a new collection, and then insert a few keys and values, terminate with an empty key. Keep in mind that every command you issue, is executed on the server; in fact, by starting two clients, you will access exactly the same data.

Here's a small session log:

Main Menu:
0. Terminate
1. Create Container
2. Select Container
1

Container Menu:
0. Return to previous menu
1. Set Entry
2. Show Entries
1
Enter an key / value pair:
  key: site
value: CodeProject

Container Menu:
0. Return to previous menu
1. Set Entry
2. Show Entries
1
Enter an key / value pair:
  key: URL
value: http://www.codeproject.com

Container Menu:
0. Return to previous menu
1. Set Entry
2. Show Entries
2
List Entries
  Entry[site] = CodeProject
  Entry[URL] = http://www.codeproject.com

Container Menu:
0. Return to previous menu
1. Set Entry
2. Show Entries
0

Main Menu:
0. Terminate
1. Create Container
2. Select Container
2

Select Containers: enter a list of key / values pairs; terminate with an empty key
  key: site
value: CodeProject
  key:

Matches:

Container 1
List Entries
  Entry[site] = CodeProject
  Entry[URL] = http://www.codeproject.com
Select container number or 0 to return to previous menu
0

Main Menu:
0. Terminate
1. Create Container
2. Select Container
0

Conclusions

This article has shown how to access objects created and hosted under .NET from J2EE using IIOP.NET. The implementation of a distributed application is as simple as using only Java's RMI/IIOP. It is obviously possible to work in the opposite way hosting the objects on J2EE and remotely accessing them from .NET: IIOP.NET includes also a generator to create the proxies for .NET given the IDL of the objects.

IIOP.NET allows to transparently access remote objects using the CORBA standard under .NET. It is well integrated in .NET's remoting framework, and as such, that it can be used together with the other remoting channels already available without any code change.

Remoting and RMI are the technologies available in .NET and J2EE to create tightly coupled interaction in a distributed object system. WebServices are a more appropriated for loosely coupled systems.

Links and References

Projects and products:

Technologies:

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Switzerland Switzerland
Patrik Reali was a senior software engineer for ELCA Informatique (www.elca.ch) in Zurich, Switzerland; in January 2005, he joined Google. He is specialized in systems and programming languages, with a strong interest for the .NET and Java platforms.

He got a PhD in computer science at ETH-Zurich working on the research operating system and language Oberon.

Together with Dominic Ullmann, he administers the open source project IIOP.NET.

Comments and Discussions

 
GeneralNMAKE Error Pin
saifmasadeh12-Apr-11 6:09
saifmasadeh12-Apr-11 6:09 
Generalinvalid character ` in valuetype identifier Pin
michael.dibley11-Aug-09 11:39
michael.dibley11-Aug-09 11:39 
QuestionCan't send objects .Net <-> Java Pin
Pohn_Gerald10-Jul-08 1:19
Pohn_Gerald10-Jul-08 1:19 
QuestionAccessing statefull session bean with .NET Pin
grinder12-Dec-07 5:39
grinder12-Dec-07 5:39 
GeneralError trying to connect to IIOP.Net object Pin
Paul Janssen23-Jan-07 11:19
Paul Janssen23-Jan-07 11:19 
QuestionHow to remove SSL Pin
User 95887413-Sep-06 7:52
User 95887413-Sep-06 7:52 
QuestionHow to access jacorb-appligator-java-server behind fireware? Pin
jmp0000000016-Aug-06 8:14
jmp0000000016-Aug-06 8:14 
QuestionPortableRemoteObject.narrow? Pin
levere16-Aug-06 7:22
levere16-Aug-06 7:22 
Generali have recieved the org.omg.CORBA.MARSHAL exception Pin
zubairy23-Jul-06 23:00
zubairy23-Jul-06 23:00 
QuestionHelp Required, client cannot connect to Server[modified] Pin
zubairy20-Jul-06 21:22
zubairy20-Jul-06 21:22 
GeneralHelp ACE/TAO idl wstring to CLS string Pin
sbrink201017-May-06 7:39
sbrink201017-May-06 7:39 
Sigh | :sigh: I have been trying to build a simple client in C# (managed) that connects to a simple server that is in ACE/TAO C++ unmanaged (IDL). I get simple methods that have arguments that are int and floats working but I can not get a simple function that uses string. I have read the IDL to CLS Mapping specification many times but can not figure out what mapping system to use. I have also looked at most of the examples (the ones I could compile) and still can not find a clear answer.

The details of my problem follow but I have a few basic questions:
Is there a book, Manual or Users guide for IIOP.NET?
Given a method in IDL that has a string or wstring what is the CLS that will map to it?
The Mapping specification shows ::CORBA::WStingValue as an OMG IDL type not wstring is there a good example of using this in the IDL?

I thing that IIOP.NET is great at this point but I need to know how to use string to move on. Could you please help?

Thank You
Steven S. Brink
System Engineer
Harris Corp.


******Here is my problem

My IDL is this

module Interfaces
{
// The adder interface
interface IAdder
{
double add(in double arg1, in double arg2);

boolean send_message( in wstring user_name,
in wstring info_type);
};
};

The add works fine but when I try send_message I get exceptions and the server never gets to send_message. The C# code is as follows.

string sUser_name = "Test sUserName";
string sInfo_type = "Info Type";

bool b = Msg.send_message( sUser_name, sInfo_type);

The code to create the .dll in C#:

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;

namespace Interfaces
{
public interface IAdder
{
double add(double arg1, double arg2);

bool send_message( string user_name,
string info_type);
}
};




The exception is:

Adder Test Results 24 + 25 = 49
Caught Exception:omg.org.CORBA.MARSHAL: CORBA system exception : omg.org.CORBA.M
ARSHAL, completed: Completed_No minor: 0

Server stack trace:


Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage req
Msg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgDa
ta, Int32 type)
at Interfaces.IAdder.send_message(String user_name, String info_type)
at EASE.DotNetNSTempleteClient.InteractWithUser(IAdder Msg) in c:\documents a
nd settings\sbrink\my documents\visual studio projects\aceiiopmix\cguiprobe\dotn
etnstempleteclient\dotnetnstempleteclient.cs:line 149
Received Message:

What am I doing wrong, I'm sure this is easier then I am making it?

Steven Brink
GeneralCannot connect ot ORB Pin
amitaamita19-Dec-05 1:59
amitaamita19-Dec-05 1:59 
GeneralRe: Cannot connect ot ORB Pin
balpeckDude10-Jan-06 1:03
balpeckDude10-Jan-06 1:03 
QuestionURGENT....use IIOP.NET with IIS v5.1 and Appserv8.1 ? Pin
d97yer27-Sep-05 4:44
d97yer27-Sep-05 4:44 
GeneralNmake fails Pin
bgolda18-Jul-05 5:28
bgolda18-Jul-05 5:28 
GeneralRe: Nmake fails Pin
balpeckDude10-Jan-06 1:04
balpeckDude10-Jan-06 1:04 
GeneralRe: Nmake fails Pin
Ayman Nageeb27-Mar-11 3:10
Ayman Nageeb27-Mar-11 3:10 
GeneralHelp Required Pin
dhaval20126-Jan-04 19:15
sussdhaval20126-Jan-04 19:15 
QuestionWhat about Windows CE? Pin
Serje20-Nov-03 4:12
Serje20-Nov-03 4:12 
AnswerRe: What about Windows CE? Pin
Patrik Reali20-Nov-03 5:46
Patrik Reali20-Nov-03 5:46 
GeneralRe: What about Windows CE? Pin
bob1405200229-Sep-04 6:34
bob1405200229-Sep-04 6:34 
QuestionCan IIOP.NET use IOR's? Pin
nursed30-Oct-03 4:15
nursed30-Oct-03 4:15 
AnswerRe: Can IIOP.NET use IOR's? Pin
Patrik Reali2-Nov-03 22:14
Patrik Reali2-Nov-03 22:14 
Generaljboss problem Pin
frankie7619-Sep-03 5:07
frankie7619-Sep-03 5:07 
GeneralNew Article: accessing EJBs from .NET with IIOP.NET Pin
Patrik Reali28-Aug-03 22:18
Patrik Reali28-Aug-03 22:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.