Enfin un canal Corba/IIOP pour .NET Remoting !

DNG a eu plusieurs fois l'occasion d'évoquer les liens existants entre Corba et .NET Remoting. Le premier étant le middleware de prédilection du monde Java à travers le protocole IIOP, le second étant le remplaçant de DCOM.
Si plusieurs solutions à l'interopérabilité tant escomptée avaient été approchées, le canal IIOP pour .NET Remoting semblait la plus séduisante. Malheureusement jusqu'alors aucune implémentation n'était disponible. Jusqu'alors ...

e tous le projets alternatifs à .NET, le mariage de .NET Remoting et Corba est assurément l'un des plus excitants. La seule idée qu'un composant Corba ou Enterprise JavaBean puisse dialoguer avec un client .NET Remoting éveille en nous une rare exaltation (et oui il nous en faut peu ;-)). 

C'est d'ores et déjà possible me direz-vous ? Oui, mais la plupart de ces solutions souffrent de lacunes plus ou moins importantes. Prenons le cas des WebServices. Ils sont un excellent moyen pour interopérer entre systèmes hétérogènes, malheureusement ils ne permettent pas aujourd'hui de gérer des opérations aussi triviales que les callbacks ou les transactions distribuées. Il est ainsi impossible de réaliser un Chat ou une application de Trading temps réel affichant une courbe lorsque client et serveur ne partagent pas le même protocole "en mode connecté". "Mode connecté" est le noeud du problème. En effet, excepté leur caractère fermé et souvent incompatible avec les pare-feux Internet,  les protocoles en mode connecté sont la solution aux échanges à l'intérieur d'une même application.  

Une autre alternative d'interopérabilité est l'utilisation de Ponts Java/COM ou RMI/.NET Remoting tels que ceux proposés par les sociétés JaNet, Halcyon ou JnBridge. Dans certains contextes, ce type de solution s'avère délicat. Ainsi, JaNet nécessite la génération de proxies à l'aide d'outils spécialisés et souvent propriétaires. Halcyon ou JnBridge fournissent l'ensemble des API Java en .NET et inversement conduisant à coupler fortement le Framework .NET à l'outil en question (que se passera t-il lorsque les API Java ou .NET évolueront ?). Bref, les ponts conviennent parfaitement à certaines applications dites légères mais ne peuvent en aucun cas constituer une réponse unique au problème de l'interopérabilité.

Toutes ces raisons font que l'alternative la plus naturelle pour le dialogue entre mondes Corba et .NET passe par l'intégration d'un canal IIOP à l'intérieur du middleware .NET Remoting de Microsoft. En effet, contrairement à Corba qui se base sur le format GIOP pour l'échange de message, Remoting lui permet de brancher n'importe quel format en utilisant n'importe quel protocole : Soap en binaire, Soap en XML, TCP en binaire, SMTP, Jabber (si si ;-)), etc ... bref une souplesse sans équivalent ...  

Une lueur d'espoir semble donc aujourd'hui se dessiner à l'horizon avec tout d'abord l'initiative Mono qui travaille activement à l'élaboration d'un tel canal. Puis enfin Remoting.Corba, un nouveau venu dont l'objectif consiste à fournir une implémentation libre du Canal IIOP totalement managé.

L'objet de cet article sera de vous présenter essentiellement Remoting.Corba qui semble dans un état beaucoup plus avancé que son homologue Mono.  

Présentation de Remoting.Corba
Remoting.Corba (prononcer RemotingDotCorba) est un projet développé par Kristopher Johnson, un féru de programmation Corba et .NET. L'objectif de Kristopher est de fournir aux différentes communautés une version OpenSource du canal .NET Remoting. L'originalité de sa démarche provient de la nature homogène de l'ensemble. Contrairement aux solutions visant à mettre en place des ponts C++/Com, Remoting.Corba est entièrement écrit en C# et se base sur des APIs développées pour l'occasion. Pour ceux ayant déjà approché les spécifications de Corba (plus de 600 pages), vous comprendrez aisément l'ampleur de la tâche.

Nous avons tenu à tester l'outil avec un exemple simple : le classique Hello afin de vérifier la qualité de cette première implémentation. Et il faut bien l'avouer, voir un middleware Microsoft tel que .NET appeler un composant Corba est une chose assez rare pour être soulignée.   

Installation et configuration

TAO

L'installation et la configuration de Remoting.Corba relève du parcours du combattant. En effet, aujourd'hui, Remoting.Corba n'a été testé qu'avec l'ORB C++ TAO. Si cet ORB est une référence dans le monde Corba du fait des nombreux services qu'il propose, son installation n'est pas des plus aisé. Une interopérabilité avec un ORB Java nous aurait beaucoup plus simplifié la tâche. Le tutorial présent sur le site de l'outil nous a été  d'un grand secours.

Une fois le compilateur IDL et autres variables d'environnement positionnés, vous obtenez une version de TAO compilée sous Visual C++ .NET. Dans notre cas, nous avons utilisé la Visual Studio 2003 RC3 reçue la veille pour les besoins du test.      

Voici ce que vous obtenez : 

Vous aurez remarqué à droite les nombreux services technique fournit par l'infrastructure de TAO. 

Installation de RemotingCorba

RemotingCorba se présente sous la forme d'une solution Visual Studio constituée de deux projets. Le premier projet contient les fichiers sources en C# du canal .NET Remoting et le second un ensemble de clients .NET Remoting utilisant le canal précédent. Excepté le désordre ambiant qu'il règne dans la solution, on remarquera l'intégration étroite entre Remoting.Corba et Nunit pour la réalisation des tests unitaires. Cela n'est pas sans poser de problème car il vous faudra récupérer séparément l'Assembly Nunit dans sa bonne version. D'ailleurs, pour tout vous avouer, nous avons eu énormément de difficulté à compiler l'ensemble. Nous vous recommandons de créer un projet séparé contenant uniquement un client .NET Remoting simple effectuant l'appel distant. 

Test du Hello  
TAO fournit en exemple un client et un serveur spécifié via une interface IDL triviale. Un serveur renvoyant au client la chaîne de caractère passé en paramètre de la méthode echo_string.

L'interface IDL utilisée :

// Echo.idl,v 1.3 
#if !defined (_ECHO_IDL)
#define
_ECHO_IDL
interface
Echo {
           
// This operation returns the message as a sequence of Objects and
           
// displays it on the screen as a string.

           
string echo_string (in string message)
            // This operation returns the message as a string and displays it on
           
// the screen.
};
#endif
/* _ECHO_IDL */ 

Le serveur C++ Corba : 

// Echo_i.cpp,v 1.21 2002/01/29 20:20:41 okellogg Exp
#include "Echo_i.h"
ACE_RCSID(Echo, Echo_i, "Echo_i.cpp,v 1.21 2002/01/29 20:20:41 okellogg Exp")

// Constructor.

Echo_i::Echo_i (void){}

// Old g++ fooler.

Echo_i::Echo_i (Echo_i &foo)
: POA_Echo (foo){}
// Destructor.

Echo_i::~Echo_i (void) {}

// Set the ORB pointer.

void Echo_i::orb (CORBA::ORB_ptr o) {
 
this->orb_ = CORBA::ORB::_duplicate (o);
}

// Return the mesg string from the server

char
* Echo_i::echo_string (const char *mesg ACE_ENV_ARG_DECL) ACE_THROW_SPEC ((CORBA::SystemException)){

  // The pointer mesg was NULL, return.
 
if (mesg == 0)
   
return 0;
 
printf("echo_string() appele ...");

 
CORBA::String_var str = CORBA::string_dup (mesg);
  return str._retn ();
}

Le client .NET Remoting:

using System;
using
System.IO;
using
System.Runtime.Remoting.Channels;
using Remoting.Corba.Channels.Iiop;
using
Remoting.Corba.Iop;

namespace corba {
           
// interface for remote CORBA object
           
interface GoodDay  {
                       
string echo_string(string p);
           
}; 

            class App  {
                       
public static void Test() {
                        
            try    {
                        
                        // read the IOR from the file
                        
                        string ior;
                        
                        using (StreamReader iorFile = new StreamReader( @"c:\echo.ior"))
                        
                        {
                                                
            ior = iorFile.ReadToEnd();
                        
                        }
                                                //
Initialise le canal IIOP
                        
                                    ChannelServices.RegisterChannel(new IiopClientChannel());
                        
                        Console.WriteLine(".NET Remoting call Corba server...");
                                                GoodDay server = (GoodDay) Activator.GetObject(typeof(GoodDay), ior);
                        
                        Console.WriteLine( server.echo_string("Hello DotNetGuru !") );
                        
            }
                        
            catch (Exception ex)  {
                        
                        Console.Error.WriteLine("Exception: " + ex.ToString());
                        
            }

                        
            Console.Out.WriteLine("Press [Enter] to exit");
                        
            Console.ReadLine();
                       
}
           
}
}

Le serveur Corba se lance en prenant soin de stocker préalablement sa référence IOR dans un fichier texte. Pour ceux parmi vous non familier avec Corba, un IOR est une chaîne de caractère normalisée et interopérable contenant toutes les informations permettant à un client de retrouver un objet distant (host, port, object_id, ...). Nous aurions pu également passer par un service de nommage mais par souci de simplicité nous avons préféré réaliser un appel direct. A ce propos, RemotingDotCorba dans son implémentation actuelle gère également l'accès au Naming service. Référez vous au tutorial en ligne pour plus d'informations.

Nous vous passons les étapes de génération de stub et de squelette dans TAO qui s'effectuent à travers Visual Studio .NET et le compilateur IDL maison de tao (idl_tao.exe). Voici le résultat obtenu : 

Inutile de vous dire que le résultat nous a agréablement surpris. Rappelons qu'il aura fallu plus d'un an pour voir une interopérabilité directe entre .NET et Corba à travers une vraie communication IIOP. Autant dire que le résultat est à la hauteur de nos espérances.   

Les limitations 
Bien entendu RemotingDotCorba n'en est qu'à ses débuts et souffre de nombreux manques. L'outil ne propose ainsi aucun compilateur intégré permettant de générer les interfaces C# à partir du langage IDL. Ce qui oblige à écrire l'interface C# du hello à la main. Quant au déploiement, nul besoin de générer de quelconques Proxies, l'outil de Kristopher se chargeant de faire une invocation dynamique (RealProxy) totalement masquée à l'utilisateur. 

Les autres limitations du produit sont les suivantes : 

  • Une application .NET ne peut agir en tant que serveur IIOP

  • l'outil est basé sur les spécifications Corba 2.6 (non Corba 3)

  • Seul GIOP/IIOP 1.0 sera supporté

  • les types suivants ne sont pas supportés : long long, unsigned long long, float, double, long double, fixed-point, decimal, valuetypes, TypeCode, any, wchar, wstring, union, array, structs, sequences

  • Pas de support de contexte Transactionnel ou de sécurité 

  • Gestion de la connexion très succincte (non optimisé) 

A la décharge de l'outil, il faut rappeler que RemotingDotCorba n'a pas pour objectif de fournir l'intégralité des services techniques proposés dans les spécifications de l'OMG mais simplement de fournir une infrastructure minimale. Kristopher nous en dit plus à la fin de l'article.     

JacORB et RemotingDotCorba
Nous avons essayé de faire communiquer sur le même principe que l'exemple précédent l'ORB Corba JacORB tant apprécié de la communauté Java, et RemotingDotCorba. Après quelques tentatives, nous avons réussi à communiquer avec le serveur Hello en Java mais l'invocation et le passage de paramètre ont quant à eux très vite posé problème. Faute de temps et de documentation sur l'outil, nous n'avons poussé plus loin nos recherches mais nous restons persuadé que JacORB pourrait très bien constituer une alternative à TAO comme exemple de référence. 

N'hésitez pas vous aussi à effectuer le test et à nous faire part de vos conclusions. 

L'initiative Mono
Dans sa version actuelle (0.21) Mono fournit également le même type de canal. Toutefois, il est loin d'être finalisé et n'est toujours pas compatible IIOP 1.0. Son auteur Dietmar Maurer semble encore en phase initiale d'implémentation et recherche des contributeurs. Voici une copie d'écran du repository CVS de Mono concernant le canal IIOP :

En tout et pour tout une douzaine de classes et un rapide coup d'oeil sur le fichier README nous indique : 
Warning: This is more or less a stub for a CORBA channel, its not CORBA compatible at all! We recently detected a runtime GC bug, so maybe you have to turn of GC in the runtime to run the examples in Test/*

L'interview de Kristopher Johnson  
Nous avons souhaité poser quelques questions à Kristopher Johnson au sujet de son outil.

1) Hello Kristopher, what is the roadmap of RemotingDotCorba ?
My plans for Remoting.Corba are detailed here:
http://kristopherjohnson.net/cgi-bin/twiki/view/KJ/RemotingDotCorba#UpcomingWork
This is a personal "hobby" project, so I don't have a schedule for implementing new features. Version 1.1 took about a week and a half to create from scratch, but I won't be working as intensively on it for a while. I plan to put Remoting.Corba on SourceForge to make it easier for others to contribute.

2) Are you planning to offer your product to mono project ?
Remoting.Corba has a MIT?BSD-style license, and anyone who wants to incorporate it into another project is welcome to do so. I have not been involved with Mono, but would be glad to assist.
I have been in contact with Sergio Perani, creator of the Harmless ORB (http://harmless.sourceforge.net), and it is likely that we will coordinate our efforts. I don't know whether there will be any sort of "merge" of the projects.

3) What are the technical issues that you faced with during your development ?
I don't think there were any difficult or interesting technical issues.
The .NET Remoting architecture is designed to be extensible, but the classes are not very well documented. Creating my own Remoting channel required a lot of looking at other examples and a lot of trial and error debugging. Even now, I'm not really sure whether the implementation is "right" (but it does seem to work).
I decided early on that I would not create an IDL compiler, mostly because of the amount of work it would entail. (I was planning to just spend a couple of days playing around with this stuff). So most of the work was in figuring out how to use reflection to get all the metadata needed to generate and interpret IIOP messages based upon method signatures.
I use a test-first development process. For each little bit of functionality, I first write a unit test (which fails at first), and then I write the code that gets the test to succeed. This process and the NUnit framework helped enormously in getting Remoting.Corba up and running quickly.

4) Will it be possible to invoke an EJB component from a .NET client with RemotingDotCorba ?
I have not tried invoking EJB components from RemotingDotCorba, but I believe it should be possible as long as Java's IIOP implementation is not incompatible with Remoting.Corba's, and as long as the EJB component's interface doesn't require any CORBA data types that are not supported by Remoting.Corba. Interoperability with Java is one of my goals, so if there are any incompatibilities, I would work on resolving them.
So far, I have only tested interoperation with the TAO CORBA implementation. I plan to add Java and omniORB interoperability tests in the near future.

Thank you Kristopher !

Conclusion
Le peu que nous ayons vu de RemotingDotCorba nous a réellement séduit. Et dire qu'un tel outil n'a nécessité qu'une semaine et demi de développement. Pourquoi diable dans ce cas avoir attendu plus d'un an pour mettre en oeuvre ce canal tant attendu par la communauté Java et Corba ? 

De plus en plus de décideurs vont être amené à se poser la question de l'interopérabilité en mode connecté entre .NET et le monde Java là où les Web Services n'apportent pas de solution. Dans ce cadre, ce mariage pour un monde plus ouvert arrive à point et nous apporte un bol d'air frais dans une période plus propice aux dépôt de brevets en tout genre ...       

 Ressources 

 Le site officiel de RemotingDotCorba : http://kristopherjohnson.net/cgi-bin/twiki/view/KJ/RemotingDotCorba
 Tutoriel  : http://kristopherjohnson.net/cgi-bin/twiki/view/KJ/RemotingDotCorbaTutorial
 Le site SourceForge : http://remoting-corba.sourceforge.net/