Ja.NET au banc d’essai

 

Introduction

Au cœur des outils d’interopérabilité .NET et Java, Ja.NET d’Intrinsyc s’inscrit comme l’un des principaux acteurs du marché concernant le « bridging » (pont). La société qui développe ce produit (Linar puis Intrinsic) est à l’origine de J-Integra, bien connu des développeurs Java. En effet, J-Integra permet de faire interopérer un composant COM et un programme Java afin de tirer parti des fonctionnalités d’applications Microsoft telles que MS Excel ou Word. Contrairement aux outils Halcyon et JLCA  qui fonctionnent par conversion de code source ou binaire, les produits JaNet et J-Integra ont pour but de ré-utiliser l’existant afin de les faire communiquer via des ponts. Vous comprendrez donc que techniquement, la problématique sera différente.

Au travers de cet article, vous découvrirez le processus d’installation et de configuration de JaNet mais aussi une série de tests qui ont été effectués afin de vérifier si ce produit propose réellement des fonctionnalités techniques intéressantes. Nous tâcherons aussi et surtout de recadrer l’utilisation de tels produits dans un contexte plus général d’architecture. Les ponts permettent t-ils de répondre efficacement aux besoins d’interopérabilité ? Est-il préférable de convertir une application à l’aide de JLCA ou Halcyon plutôt que d’utiliser un pont ? 

Installation et configuration

JaNet peut-être téléchargé à l’adresse suivante : http://www.intrinsyc.com/products/bridging/janet.asp . Pour utiliser le produit, vous devrez disposer d’une machine virtuelle Java. En effet, le programme d’installation recherche le fichier jvm.dll en local sur votre machine. D’ailleurs, nous avons été confronté à quelques petits soucis lors de cette opération car JaNET ne trouvait pas ce fichier.

Après quelques petits réglages, Intrinsyc Ja.NET s’installe correctement. Regardons de plus près l’arborescence du produit.


La figure suivante met l’accent sur les bibliothèques et exécutables requis par l’outil.


Les deux répertoires les plus importants sont /bin et /lib. /bin contient l’outil GenService destiné à la génération de Proxies et AssemblyReader permettant de générer le contenu d’une Assembly sous un format XML. L’ensemble du noyau de Ja.NET se trouve dans les archives Java situées dans le répertoire lib. C’est ce qui nous amène à penser que l’outil est écrit entièrement en Java, d’ailleurs, une rapide lecture de la documentation se charge de nous le rappeler.

Comment fonctionne Ja.NET ?  

Rappelez vous le principe de Ja.NET : fournir des ponts entre applications Java et .NET et inversement. Le premier réflexe consiste donc à prendre un programme C# et à appeler un autre programme écrit en Java. Comme par hasard, les équipes de Ja.NET nous fournissent déjà des exemples réalisant les opérations suivantes :

·        Accéder un composant VB.NET à partir de Java

·        Accéder à un composant Java à partir de C#

·        Accéder à un composant .NET hébergé sous IIS en Java

·        Accéder à des EJB sous WebLogic, Websphere et Oracle 9iAS à partir de C#

·        Accéder à des EJB à partir de VB.NET en utilisant Jboss

Toutes ces applications se trouvent dans le répertoire JaNet/examples. Nous allons nous empresser de les mettre en œuvre.

Accéder à un composant VB.NET à partir de Java

 Pour faire ce test, nous procédons à l’exécution des étapes suivantes :

1.     Lancer le composant .NET

2.     Générer les proxies Java à partir de ce composant

3.     Compiler, configurer et exécuter le client Java

Tout d’abord, étudions la première étape. Après un rapide coup d’œil sur la documentation, il apparaît que le composant .NET est en fait un objet distribué .NET Remoting proposant une méthode ReturnClassByValue() chargée de renvoyant au client une classe passée par valeur (Serializable). Soit. Mais alors que nous nous attendons à wrapper une classe quelconque .NET, il nous faut absolument utiliser un objet distribué, la démarche semble tout de même quelque peu lourde pour une opération aussi simple, mais poursuivons … A la lecture de la documentation (si si ça m’arrive ;-)), le produit nous indique qu’un Proxy Java doit être généré à partir de l’objet distribué afin de pouvoir effectuer l’invocation. Nous utilisons pour ce faire l’outil genjava.jar. L’écran suivant nous illustre son fonctionnement.   


 


GenJava nous a généré plusieurs fichiers correspondant aux proxies et aux paramètres passés par valeur. Une fois ces deux fichiers compilés, il reste (encore !) une étape supplémentaire : lancer l’outil Janetor (rien à voir avec Albator) afin de configurer l’URL du composant distribué. Cet outil est en fait une interface graphique du fichier de configuration Janet.xml, il permet de paramétrer le protocole et le canal à utiliser pour l’invocation. Inutile de vous dire que toutes ces étapes complexifient considérablement la tâche du développeur et sont à renouveler en cas de modification des interfaces …. Sans compter le caractère propriétaire de l’ensemble…

 A titre indicatif, voici le code source du Proxy généré par JaNet :

/**

 * Class vb_server.VbServerNamespace.ClassByReference

 * Generated by GenJava v 1.0.346 and GenService v

 * Sun Mar 03 15:29:02 CET 2002

 * Copyright (C) 2001, Intrinsyc Software Inc.  All rights reserved.

 */

 

package vb_server.VbServerNamespace;

 

import com.intrinsyc.janet.*;

import com.intrinsyc.janet.remoting.ObjRef;

 

 

/**

 * This file is a Java proxy file generated by JaNET, the Java/.NET

 * integration product from Intrinsyc Software Inc.

 *

 * @author Ja.NET (GenJava tool)

 * @version 1.0

 */

 

public class ClassByReference extends RemoteProxy {

 

 

 

  public ClassByReference(ObjRef objRef) throws RemoteException {

    super(objRef);

  }

 

  public  ClassByReference() throws RemoteException  {

    super("vb_server.VbServerNamespace.ClassByReference", "vb_server",

      new int[] {},

      new Object[] {},

      new String[] {});

  }

 

 

  public  ClassByReference(String URI, String format, boolean clientActivated)

                                                       throws RemoteException  {

    super("vb_server.VbServerNamespace.ClassByReference", "vb_server",

      URI, format, clientActivated,

      new int[] {},

      new Object[] {},

      new String[] {});

  }

 

  // vb_server.VbServerNamespace.ClassByValue ReturnClassByValue(System.String)

 

  /**

   * Method ReturnClassByValue

   *

   * @param name

   * @return vb_server.VbServerNamespace.ClassByValue

   * @throws RemoteException

   */

  public vb_server.VbServerNamespace.ClassByValue ReturnClassByValue(String name)

                                                          throws RemoteException  {

    vb_server.VbServerNamespace.ClassByValue[] retval = new vb_server.VbServerNamespace.ClassByValue[1];

 

    invokeMethod("ReturnClassByValue",

      new int[] {STRING, OBJECT_BY_VALUE | RETURN},

      new Object[] {name, retval},

      new String[] {"System.String", "vb_server.VbServerNamespace.ClassByValue"});

    return retval[0];

  }

 

 

  // for internal use only

 

  /**

   * Constructor ClassByReference

   *

   * @param className

   * @param assembly

   * @param parameterTypes

   * @param parameterValues

   * @param parameterTypeNames

   *

   * @throws RemoteException

   *

   */

  protected ClassByReference(String className, String assembly,

        int[] parameterTypes, Object[] parameterValues,

        String[] parameterTypeNames) throws RemoteException {

    super(className, assembly,

      parameterTypes, parameterValues, parameterTypeNames);

  }

 

  // for internal use only

 

  /**

   * Constructor ClassByReference

   *

   * @param className

   * @param assembly

   * @param URI

   * @param format

   * @param clientActivated

   * @param parameterTypes

   * @param parameterValues

   * @param parameterTypeNames

   *

   * @throws RemoteException

   */

  protected ClassByReference(String className, String assembly,

        String URI, String format, boolean clientActivated,

        int[] parameterTypes, Object[] parameterValues,

        String[] parameterTypeNames) throws RemoteException {

    super(className, assembly, URI, format, clientActivated,

      parameterTypes, parameterValues, parameterTypeNames);

  }

 

  public static final String __janetAssemblyName = "vb_server";

  public static final String __janetClassName =

   

"vb_server.VbServerNamespace.ClassByReference";

}

 


Bref, concernant l’invocation de composants .NET à partir de JaNET, il est nécessaire de disposer d’objets distribués en .NET Remoting, c’est le mode d’interopérabilité choisi par l’outil. Etudions maintenant l’opération inverse, l’appel d’un composant EJB (pour faire simple ;-)) à partir d’un programme C#.

Accéder à un composant EJB à partir de C# 

Un rapide coup d’œil sur la documentation semble indiquer que la tâche sera des plus rudes. En effet, pas moins de 8 étapes (!!) ponctuées de paramétrages en tout genre. Bien entendu, le principe reste similaire, c’est pourquoi nous avons préféré vous montrer uniquement le plus important : l’outil gennet.jar réalisant l’opération inverse de genjava.jar avec une génération de proxies .NET.  Pour le lancer : C:\java –jar gennet.jar, spécifiez le fichier .EAR et l’outil se charge de lire à l’intérieur et d’effectuer un certain nombre de traitements. En tout et pour tout, plus d’une dizaine d’écrans en tout genre contenus dans trois assistants différents, de quoi s’arracher les cheveux ;-) …

 

Bref, vous aurez compris encore une fois que l’utilisation de JaNet n’est pas des plus triviales. Ajoutez à cela la multiplication des assistants, et vous comprendrez pourquoi nous avons préféré nous arrêter là pour la partie  test. Jugez-en par vous même sur la figure précédente.

1) Intérêt de Ja.NET dans l’Architecture générale

Au travers des différentes explications et mise en œuvre de cet article, il apparaît que JaNET se base essentiellement sur une interopérabilité réseau. C’est à dire que les composants .NET et Java dialoguent entre eux via .NET Remoting de Microsoft. Si cette interopérabilité existe déjà par le biais de standards tels que les WebServices, elle prouve bien qu’il est aujourd’hui possible d’intégrer l’ORB de Microsoft dans un environnement Java sans faire appel à du code natif. D’un autre coté, si nous avions repris l’ensemble des exercices précédents avec une communication client/serveur via des WebServices, nous aurions gagné un temps considérable car les plate-formes intègrent déjà la notion de Proxy. C’est pourquoi nous sommes en mesure de nous interroger sur de tels choix de la part de JaNET ? la question reste en suspens. 

Enfin, il est à noter que dans une architecture, l’intégration via des ponts à l’intérieur d’une même application est une démarche qu’il faut adopter avec précaution. Premièrement, nous l’avons vu, cela complexifie énormément la maintenance du système qui est composée de plusieurs briques hétérogènes. Deuxièmement, cela ralentit les communications entre client et serveur car vous passez par des phases de marshalling/demarshalling des paramètres sur le réseau. D’ailleurs c’est aussi une des raisons pour laquelle Microsoft devrait porter COM+ au plus vite vers l’environnement managé .NET, les performances s’en trouveraient grandement améliorées.

 


 

Conditions et tarifs

JaNet est décliné en deux versions : Standard et Entreprise. Voilà la matrice des tarifs correspondant à chaque version.

J2SE : Standard

Licenses

5 Licenses

50 Licenses

500 Licenses

J2SE

$375

$3,250

$20,000

 

J2EE : Entreprise

Licenses

1-5 License

5+ Licenses

J2EE

$2000*

Contactez le service commercial janet_sales@intrinsyc.com

 

Conclusion

JaNET est ce qu’il est commun d’appeler un coup médiatique et marketing. J-Integra brillait surtout par sa capacité à intégrer un composant Ole Automation tel que  Excel ou Word dans une application Java alors que JaNet se contente de faire communiquer des objets via .NET Remoting. D’ailleurs, J-Integra est toujours proposé au catalogue d’Intrinsyc et gageons qu’il restera le produit phare de la gamme.

Au delà de ces aspects purement techniques, le tableau n’est pas pour autant sombre. Ce produit est la preuve même qu’il est dorénavant possible de faire communiquer les ORB Java RMI ou Corba et .NET Remoting. Nul besoin de passer par du code natif (JNI) pour effectuer cette opération, JaNET le prouve. Quant à savoir quel est l’intérêt à multiplier les protocoles en tout genre à des fins d’interopérabilité, nous sommes en droit de nous interroger. Aujourd’hui les WebServices sont un excellent moyen de standardiser les échanges entre systèmes hétérogènes alors pourquoi ajouter un degré supplémentaire de complexité ?

 

Auteur : Sami Jaber

Copyright : DotNetGuru Ó 2002