Page d'accueil | Applications | Delphi | eBooks pour MS Reader | Me contacter
TECHNOLOGIES

Collaboration d'ActiveX et design pattern Médiateur

(Janvier 2001)

Le modèle de conception "Médiateur" offre une solution originale pour faire collaborer des ActiveX ensemble, situés dans des conteneurs ActiveX n'appartenant pas nécessairement à la même application.
Dans ce modèle, la classe ayant le rôle de médiateur possède une référence de tous les objets devant participer à la réalisation d'une tâche et contient toute la logique du traitement. Cela évite que tous les objets se fassent référence les uns aux autres en complexifiant les traitements.

La mise en ouvre de ce modèle s'appuie ici sur des ActiveX qui sont des ActiveForm créés avec Delphi et utilisant des interfaces OLE automation. Mais je gage que le lecteur pourra réutiliser les principes exposés dans cet article avec son propre outil de développement et/ou d'autres technologies.
Si vous permettez à votre navigateur d'exécuter des ActiveX, vous pourrez aussi tester le résultat de cette mise en ouvre dans une page HTML. Pour cela, reportez vous à la rubrique Ressources à la fin de cet article.


Exposition du problème

Nous souhaitons offrir une interface utilisateur (UI) pour la saisie de nombres sous la forme d'un ActiveX présentant des touches numériques ; cette saisie sera reflétée par un ou plusieurs autres objets COM basés sur un autre ActiveX se contentant d'afficher ce qui aura été saisi.

Voici le diagramme de classes UML de ces ActiveX d'interface utilisateur implémentés dans l'OCX VposUI.ocx :


Les classes TFrmKbUI et TFrmDisplayUI sont les coclasses implémentant chacune une interface COM distincte. Par simplification, ces interfaces ne définissent qu'une seule méthode identique, MiseAJour, susceptibe d'être appelée par le médiateur pour demander au contrôle de se rafraîchir. A ce moment les ActiveX "DisplayUI" pourront interroger le médiateur pour connaître le nombre à afficher.


Le médiateur

Le médiateur est implémenté dans l'exécutable Vpos.exe comprenant un objet OLE automation, TCoVlp, par la classe TMediateur. Cette classe est définie avec le modèle Singleton, c'est-à-dire que l'on ne crée et n'utilise qu'une seule instance de cette classe.
L'objet automation TCoVlp, qui est invoqué par les ActiveX d'interface utilisateur, est chargé de faire le lien avec l'instance unique du médiateur.

Le diagramme de classes UML de Vpos.exe est présenté ci-dessous :


La classe TFrmVpos représente la fiche principale de l'application, que l'on peut choisir de montrer ou non. Elle peut servir à présenter des messages destinés au déboguage par exemple.

Le diagramme de séquence ci-dessous présente les principales étapes d'exécution, en partant de l'instanciation de l'ActiveX UI "clavier" dans un conteneur :



Test

Pour tester ce code, vous devez tout d'abord télécharger l'exécutable Vpos.exe (renfermant le médiateur), placé dans le fichier Vpos.zip. Dézippez-le pour ensuite exécuter "Vpos /regserver", ce qui enregistrera le serveur dans la base de registres de Windows (Vpos.exe se désinstalle tout d'abord en exécutant "Vpos /unregserver", puis en supprimant ce fichier).
Vpos.zip

Vous pouvez maintenant utiliser le lien ci-dessous vers une page HTML qui comprend les ActiveX de VposUI.ocx (votre navigateur doit autoriser l'exécution d'ActiveX sur votre machine) :
medt.html


Retour à la page d'accueil

Commande

(Octobre 2002)

Cet article présente une implémentation en Pascal Objet du modèle de conception " Commande ". Ce modèle de conception est décrit dans l'ouvrage " DESIGN PATTERNS " (voir la rubrique Ressources en fin d'article).
La définition de ce modèle est la suivante :
" Encapsuler une requête comme un objet, autorisant ainsi le paramétrage des clients par différentes requêtes, files d'attente et récapitulatifs de requêtes, et de plus, permettant la réversion des opérations. "

La classe Pascal Objet sur lequel repose ce modèle est TCommand, les classes TMacroCommand (collection d'objet TCommand) et TMacroCommandLog en sont dérivées, comme illustré dans le diagramme de classes UML ci-dessous :



Un projet Delphi 6 très simple est fourni comme exemple d'utilisation de ces classes pour en montrer l'intérêt.

TCommand est une classe abstraite possédant la méthode virtuelle abstraite execute qui réalise l'action à effectuer ; une classe commande concrète (dérivant de TCommand) est créée avec les arguments qui serviront à l'exécution de la méthode surchargée execute. Une fois qu'un objet commande est instancié, un client peut invoquer à tout moment sa méthode execute.

La classe TCommand est basée sur TComponent afin d'utiliser le mécanisme de lecture/écriture de composant Delphi depuis ou dans un flux.
L'application exemple (voir la rubrique Ressources) déclare la classe TMaCommande dérivée de TCommand, afin de conserver dans des objets les choix successifs de l'utilisateur entre une entrée, un plat principal et un dessert.

Chaque objet TMaCommande conserve un choix de l'utilisateur sous forme d'entier (0..2), de sorte que si la méthode execute est appelé, le bouton radio correspondant de l'interface utilisateur est sélectionné.
Tous les choix faits depuis le démarrage de l'application sont conservés dans un objet descendant de TMacroCommand, TMacroCommandLog, qui permet de gérer une collection d'objets commandes.
La méthode surchargée execute de TMacroCommand se contente d'appeler cette même méthode avec tous les objets commandes qu'elle contient.

TMacroCommandLog a la particularité de conserver dans un fichier tout objet commande ajouté à la collection, de sorte que si l'on redémarre l'application, nous pouvons appliquer à nouveau tous les choix de l'utilisateur (comme après un crash système par exemple).
Pour que les opérations de lecture/écriture fonctionnent, l'unité Unit1 déclare dans sa section initialisation l'instruction :
RegisterClasses([TMaCommande]);


Il existe d'autres indications d'utilisation de ce modèle, telles que les transactions ou les opérations " défaire " (undo). Un objet commande pourrait également être transmis à un autre récepteur sur une machine distante et y être exécuté (par sérialisation/désérialisation dans une chaîne de caractères OLE via DCOM par exemple) !


Ressources

Livre " DESIGN PATTERNS "
Catalogue de modèles de conception réutilisables
Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides

Command.pas et projet d'exemple (Delphi 6)
cmdprj.zip


Retour à la page d'accueil

Distributed COM

(Février 2002)

Cet article décrit comment un programme client peut invoquer un objet COM situé sur une autre machine au moyen de DCOM (extension distribué du modèle objet COM Microsoft), et quels sont les paramétrages à effectuer de part et d'autre.
Si le serveur COM est de type automation, nous montrerons que le client n'a besoin de connaître que le nom de la machine distante et l'identificateur de la classe, sans aucun paramétrage particulier.

Cet article est d'avantage destiné à l'environnement Delphi, mais les principes utilisés s'appliquent à tout environnement de développement supportant COM. Nous préciserons à chaque fois ce qui est spécifique à Delphi.


Serveur COM

Nous partirons d'un serveur hors processus (exécutable) comprenant un objet automation (classe COM supportant l'interface IDispatch). Dans l'EDI Delphi, il suffit de créer une nouvelle application et d'y ajouter un objet automation au moyen de l'assistant adéquat.
Supposons que vous ayez saisi "Service" comme nom de CoClass.



L'éditeur de la bibliothèque de types vous permettra de compléter votre interface IService héritée de IDispatch déclarée dans l'unité générée par l'assistant. Cette unité, dont le nom est celui du projet suivi de "_TLB", comprend la classe utilitaire CoService définissant deux fonctions de classe destinées à instancier votre classe COM en renvoyant un pointeur d'interface ayant le type IService.
La première de ces méthodes, "Create", crée un objet local, la seconde, "CreateRemote" un objet distant sur la machine dont le nom est passé en paramètre. Au final, se sont respectivement les fonctions de l'API Windows CoCreateInstance et CoCreateInstanceEx qui sont appelées de manière interne.


Recensement du serveur

Le recensement du serveur peut être fait depuis Delphi, ou bien en démarrant l'application (auto-recensement), ou encore en démarrant l'application avec l'argument /regserver.
Dans le cas d'un objet COM en processus (DLL), l'utilitaire Microsort regsvr32 peut être appelé avec le chemin complet de la dll.


Appel distant du client

L'unité représentant en Pascal Objet la bibliothèque de types de votre serveur (unité projet_TLB) peut être réutilisée par une application cliente s'exécutant sur une autre machine. De cette manière, votre code s'appuie sur l'utilisation du pointeur d'interface IService (liaison précoce). Par exemple :

var
  Service: IService;
begin
  Service := CoService.CreateRemote('HOSTNAME');
  ... // faire quelque chose avec le pointeur d'interface IService
end;

Dans le code ci-dessus l'objet Service est créé sur la machine distante 'HOSTNAME'. Par défaut tous les chemins UNC, tels que \\serveur ou serveur, et les noms DNS, tels que serveur.com ou 144.19.56.38, sont permis.
La fonction CoCreateInstanceEx, appelée de manière interne par CreateRemote, ne recherche pas dans la base de registres du client le CLSID désiré (GUID de classe de l'objet Service), mais contacte plutôt le SCM qui réside sur la machine distante spécifiée et lui demande de rechercher le base de registres de ce serveur.
Avec cette technique, il est nécessaire soit de recenser l'activeX sur la machine cliente, ce qui oblige à avoir une copie de votre exécutable sur cette machine, soit de recenser uniquement la bibliothèque de types.
Votre projet comprend cette bibliothèque de types sous forme de ressource Windows incluse dans l'exécutable et sous forme de fichier projet.tlb. L'utilitaire Borland tregsvr.exe, situé normalement dans le répertoire Bin de Delphi vous permettra de recenser le fichier projet.tlb.
Il suffirait à un environnement de développement compatible COM d'importer cette bibliothèque de types pour obtenir les méthodes et propriétés de l'objet Service.

Il existe un moyen de se passer de tout paramétrage sur le poste client, du fait que le serveur supporte l'interface IDispatch.
En pascal objet nous utiliserions un variant de la manière suivante :

const
CLASS_MonService: TGUID = '{F845A45F-1A3C-4866-B44F-F92FB491015B}';
var
  Service: Variant;
begin
  Service := CreateRemoteComObject('HOSTNAME', CLASS_MonService) as IDispatch;
  ... // faire quelque chose avec Service
end;

La seule contrainte est de connaître le CLSID de la classe COM à invoquer sur la machine distante. Dans l'unité projet_TLB, ce GUID apparaît comme constante dans la partie interface de l'unité.
Le code du programme client utiliserait donc la liaison tardive (pas de vérification à la compilation) comme pour n'importe quel autre objet automation.


Appel local, mais distant !

Pour les applications instanciant des objets COM locaux, il est toujours possible d'utiliser DCOM sans devoir changer une seule ligne de code. Moyennant des modifications de la base de registres concernant les classes de votre serveur, vous pouvez spécifier sur quelle machine doit être instancié un objet COM. Pour vous y aider, utilisez l'utilitaire de configuration DCOM dcomcnfg.exe (voir la rubrique Ressources plus loin). Après avoir sélectionné "Service objet" comme application, cliquez sur le bouton Propriétés. Dans la boîte de dialogue qui s'ouvre vous pouvez alors sélectionner le nom de la machine sur laquelle instancier votre activeX.





Ressources

Utilisation de l'utilitaire dcomcnfg
http://support.microsoft.com/default.aspx?scid=kb;FR;q176799

Description de CoCreateInstanceEx
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/cmf_a2c_5ry0.asp


Retour à la page d'accueil

Jini

(Mars 2001)

Installation de Jini

Ces explications supposent que vous utilisez le JDK 1.3 et Jini version 1.1 installés respectivement dans les répertoires D:\jdk1.3 et D:\jini1_1.
J'ai défini la variable d'environnement JINI_HOME avec la valeur "d:\jini1_1", à l'aide de la boîte de dialogue "Propriétés système" de ma machine Windows NT 2000. D'autre part, la variable d'environnement path devra contenir l'accès à D:\jdk1.3\bin.

Pour vérifier que tout est bien installé, on pourra démarrer les services Jini par l'utilitaire StartService :

java -cp %JINI_HOME%\lib\jini-ext.jar;%JINI_HOME%\lib\jini-examples.jar com.sun.jini.example.launcher.StartService

Pour cela, il vous faut d'abord ouvrir le fichier de propriétés jini11_win32.properties situé dans le répertoire D:\jini1_1\example\launcher.
Dans les pages à onglet, il suffira de remplacer C:\files par D:\ pour donner le chemin d'accès à l'installation de Jini.
Dans les pages "Reggie" et "LookupBrowser" du classeur, il faut également remplacer hostname pour la valeur de l'entrée "Codebase" par le nom de la machine qui permettra le téléchargement des fichiers nécessaires.
Assurez-vous aussi que la valeur de l'entrée "Log directory" ne contient que des noms de répertoires existants.
A noter que l'on peut préciser pour rmid l'utilisation d'un fichier de règles de sécurité, comme par exemple D:\jini1_1\example\lookup\policy.all. Par défaut aucun fichier de règles de sécurité n'est fourni (none).
Démarrez alors dans l'ordre, le serveur HTTP, le démon activation (RMID) et enfin le service lookup (Reggie).
Vous pouvez ensuite exécuter l'application LookupBrowser à partir de la page "Run" ; celui-ci doit afficher dans sa fenêtre :

Groups: <all>
1 registrar, not selected

Sélectionnez alors dans le menu "Registrar", l'article de menu ayant comme nom celui de votre macine ; la partie inférieure de la fenêtre doit présenter au moins un service Jini, reggie, s'exécutant sur votre machine.


Démarrer les services Jini par la ligne de commande

Pour permettre le téléchargement de code, il faut exécuter un serveur web quelque part sur le réseau qui pourra fournir le code nécessaire pour les applications. On pourra utiliser celui de Jini fourni dans le package tools.jar :

java -jar %JINI_HOME%\lib\tools.jar -port 8080 -dir %JINI_HOME%\lib -verbose

Démarrer le démon RMI Activation est tout aussi simple :

rmid -J-Djava.security.policy=%JINI_HOME%\example\lookup\policy.all

Une instance de ce démon doit être exécutée sur toute machine sur laquelle réside des objets activables, ce qui inclut le service Jini reggie, le gestionnaire de transaction et JavaSpaces.

Démarrer enfin le service lookup par :

set POLICYFILE=%JINI_HOME%\example\lookup\policy.all
set JARFILE=%JINI_HOME%\lib\reggie.jar
set CODEBASE=http://bgoetzmann:8080/reggie-dl.jar

java -jar %JARFILE% %CODEBASE% %POLICYFILE% d:\reggie_log

Les fichiers de règles de sécurité indiquent quelles seront les ressources accessibles par un programme à l'exécution.
Ici nous voulons exécuter la fonction main contenue dans le fichier archive reggie.jar, ce qui est précisé par l'option -jar.
Codebase précise où le code qui sera téléchargé par les clients réside, notamment pour accéder à reggie : il s'agit d'une URL, avec comme nom d'hôte, la machine exécutant le serveur web. Il convient de remplacer bgoetzmann par le nom de la machine adéquate.
Les deux derniers arguments sont le répertoire réservé au log de reggie et le groupe pour lequel le service est accessible.


Ecriture d'un service Jini

Le livre Core Jini, de W. Keith Edwards, est un excellent livre puisque l'auteur couvre tout Jini et fournit de nombreux exemples de programmes.
D'autre part, l'auteur met à disposition sur son site web, une bibliothèque de classes, le Service Writer Toolkit (SWT), destinée à écrire des services Jini en offrant des tâches communes à la plupart des services Jini (voir la rubrique ressources ci-desous).

Je propose le téléchargement de fichiers source Java d'un simple service Jini, dont la classe est basée sur la classe BasicUnicastService du SWT, ainsi que celui d'une application cliente utilisant ce service.
Ce service est identique à celui du chapître 5 de Core Jini, pour lequel l'objet proxy communique avec le service par RMI pour renvoyer une chaîne de caractères au travers d'une interface partagée entre le client et le service. Le but de service est de présenter l'utilisation du SWT.
La classe BasicUnicastService prend en charge l'exécution d'un serveur web pour permettre le chargement des classes utiles aux clients.
Comme le service comporte un objet serveur RMI, Backend, il est nécessaire d'appliquer le compilateur de stubs rmic sur cette classe et de rendre les classes générées disponibles pour les clients.


Ressources

Téléchargement de Jini :
http://developer.java.sun.com/developer/products/jini/


Le Service Writer Toolkit de W. Keith Edwards est disponible à l'adresse :
http://www.kedwards.com


Utilitaires au développement Jini par Iain Shigeoka :
http://sourceforge.net/projects/jini-tools


Les sources du service Jini utilisant la classe BasicUnicastService, et celui d'un client Jini :
srcjini.zip


Les services de base de Jini peuvent être démarrés avec l'application graphique LookupRunner, en version beta, de Bald Mountain Software. Cette version ne fonctionnera plus au 1er janvier 2001.
http://www.bald-mountain.com/jini.html


Retour à la page d'accueil

JXTA

(Juillet 2002)

JXTA

JXTA (pour juxtapose) est une plate-forme de développement d'applications P2P (peer-to-peer ou poste-à-poste) initié à l'origine par Sun Microsystems.
Défini par une série de protocoles légers conçus pour gérer n'importe quelle application P2P, JXTA est compatible avec l'ensemble des plates-formes informatiques.
Programmé initialement en Java, et gérant les transferts de données en XML, JXTA est capable de tourner sur n'importe quel OS, et donc sur n'importe quelle machine dotée d'un minimum de capacité de traitement, du PC de bureau au téléphone mobile.


NetSend

Cet article présente l'application NetSend qui est une application JXTA permettant, tout comme la commande NET SEND de Windows NT, d'où elle tire son nom, d'envoyer des messages vers une machine du réseau.
Une fois l'application démarrée, une boîte de dialogue permet à l'utilisateur d'envoyer un message personnel, en utilisant la syntaxe " <Nom de machine> <Message> ", à une autre machine du réseau qui exécute NetSend. Le message apparaît alors instantanément dans une fenêtre modale sur la machine distante, avec le nom du pair à l'origine du message.
Les sources de cette application, NetSendApp.java et NetSend.java, sont disponibles dans la rubrique Ressources à la fin de l'article.


Environnement de développement

L'environnement de développement de NetSend est le suivant :

- OS : Windows 2000 Professionnel
- JDK : 1.4
- JXTA : JXTA build 49b, 08-02-2002
- EDI : Forte for Java v. 3.0

Nous avons défini la variable d'environnement système JXTA_HOME, en accédant aux propriétés système de Windows 2000, avec pour valeur, le chemin contenant les binaires de JXTA. Cette variable sera utilisée dans les fichiers de commande permettant de démarrer l'application NetSend.
Dans le prohet de l'EDI Forte for Java, il est nécessaire d'ajouter jxta.jar dans les fichiers systèmes pour pouvoir compiler les sources de NetSend.


Exécution de NetSend

Voici la commande qui permet d'exécuter NetSend :

java -classpath "%JXTA_HOME%\jxta.jar";"%JXTA_HOME%\log4j.jar";"%JXTA_HOME%\jxtasecurity.jar";"%JXTA_HOME%\jxtaptls.jar";"%JXTA_HOME%\cryptix32.jar";"%JXTA_HOME%\cryptix-asn1.jar" NetSend


Conception de NetSend

NetSend peut servir d'exemple quand à la manière de démarrer une application sur la plate-forme JXTA qui s'accompagne de la publication des trois annonces liées à celle-ci, et de la création d'un groupe.
En effet, un pair déclare les ressources disponibles sur le réseau par des annonces prenant la forme de documents XML ; ces ressources peuvent ainsi être découvertes et utilisées par les autres pairs.
Les pairs qui démarrent NetSend rejoignent un groupe particulier et publient chacun une annonce de " Pipe ", sorte de canal de communication, qu'un autre pair peut utiliser afin d'y envoyer un message.

L'annonce du Pipe possède un identificateur unique et il faut prendre en compte le mécanisme de mise en cache des annonces découvertes. C'est pourquoi, à la première exécution, NetSend sauvegarde l'annonce du Pipe créé dans un fichier nommé PipeAdv.xml, afin de le réutiliser pour les exécutions suivantes et de garder ainsi le même identificateur.


Ressources

http://www.jxta.org

http://platform.jxta.org

Téléchargement la plate-forme JXTA avec des programmes de démonstration :
http://download.jxta.org/easyinstall/install.html


Livres :
JXTA : Java P2P Programming (D. Brookshier, ...)
JXTA (B. Wilson)
http://www.brendonwilson.com/projects/jxta


Les fichiers sources de NetSend
NetSend.zip


Retour à la page d'accueil

OBJECT EVERYWHERE Editeur

(Décembre 2000)

« OBJECT EVERYWHERE Editeur » est une application Java permettant de modifier le fichier XML servant à conserver tous les articles de ce site, en dehors de toute considération de présentation.




La séparation du contenu des articles de la manière dont ils vont être présentés dans des pages HTML offre une très grande souplesse dans la chaîne de publication du site. En effet on pourra dissocier la modification du « contenu » qui est ici un ensemble d'articles décrit par un fichier XML associé une grammaire (la DTD), de sa présentation obéissant à des règles de style (fichiers XSL).
Contenu et règles de style peuvent même évolués de manière indépendante.

Utiliser une application spécifique pour modifier la base des articles me paraît important, parce que cela permet de s'affranchir de toute connaissance préalable d'XML et d'être certain d'obtenir un document « bien formé » et « valide ».

La capture d'écran ci-dessous présente la page permettant le modifier le corps d'un article.




Une fois le document modifié on peut alors passer à la génération des pages HTML en utilisant un parseur XSL. XSL est une des applications d'XML qui, au travers de fichiers de style XSL, génère en sortie des balises HTML à partir d'un fichier XML.
La création des fichiers de style demande une connaissance précise des balises servant à manipuler les éléments du fichier d'entrée.
La génération des pages HTML peut s'effectuer, soit de manière dynamique côté serveur (avec une servlet par exemple) ou client (applet par exemple), soit de manière statique. Dans ce dernier cas, les fichiers HTML sont produits avant de les envoyer sur le site web. C'est le cas de ce site et vous avez, sous les yeux, le résultat de cette transformation obtenue avec quatre fichiers de style XSL.


Les outils

« OBJECT EVERYWHERE Editeur » a été développé en Java, avec Forte for Java, et les composants beans XML Master d'IBM. Ces derniers rendent le développement d'application XML rapide, puisque l'on peut utiliser des composants visuels prenant en charge automatiquement la modification du fichier XML. Ceux-ci sont associés à des éléments XML représentés par des composants non visuels. D'autre part on est assuré de produire un document conforme à sa DTD (Document Type Definition).
La transformation XML-HTML est prise en charge par le produit IBM XSL Editor, mais peut l'être aussi avec un autre parser XSL.


Ressources

Les composants Java beans XML Master sont disponibles sur le site d'IBM alphaWorks :
http://www.alphaworks.ibm.com/tech/xmas

XSL Editor est accessible sur ce même site :
http://www.alphaworks.ibm.com/tech/xsleditor


Retour à la page d'accueil

Pont CORBA Java-Delphi

(Août 2001)

L'objet de cet article est de montrer comment une application cliente Java peut invoquer un objet défini dans une application serveur développée avec Delphi, en utilisant le support CORBA de Java 2 et l'implémentation CORBA Visigenic pour Delphi.

Client : Java 2 (JDK 1.3), Forte for Java
Serveur : Pascal Objet, Delphi 6, Visibroker 4.1

Les ORB (Object Request Broker) sont interopérables parce qu'ils se conforment à la norme CORBA ; dans la pratique cela peut être délicat...
Le programme de démonstration du répertoire "COSNaming40" de Delphi 6 utilise le service de nom "NameService" accessible à partir d'autres ORB pour permettre l'accès aux objets qui y sont recensés. N'ayant pas réussi à y accéder depuis l'ORB de Java 2 (JDK 1.3), l'application cliente Java utilise l'IOR (Interoperable Object Reference) de l'objet disponible dans l'application serveur.

Les programmes client et serveur partent de la définition d'interface suivante du fichier Hello.idl :

module HelloApp
{
  interface Hello
  {
    string sayHello();
  };
};

L'application cliente Java se contentera d'invoquer la méthode sayHello pour obtenir le fameux "Hello World !".
Les définitions de classes de support pour Java et Delphi sont obtenus respectivement avec l'exécution des outils idlj du JDK 1.3 et idl2pas de Delphi 6 (il faut avoir installé Visibroker 4.1).


Client Java

import HelloApp.*; // Le package contenant les classes "stubs"
import org.omg.CORBA.*;


public class HelloClient
{
  public static void main(String args[])
  {
    try{

      // Créer et initialiser l'ORB
      ORB orb = ORB.init(args, null);

      String ref = "IOR:01202..."; // L'IOR de l'objet serveur

      org.omg.CORBA.Object objRef = orb.string_to_object(ref);

      Hello helloRef = HelloHelper.narrow(objRef);

      // Appeler la méthode sayHello de l'objet serveur
      String hello = helloRef.sayHello();
      System.out.println(hello);

    } catch(Exception e) {
        System.out.println("ERROR : " + e);
        e.printStackTrace(System.out);
      }
  }
}


Serveur Delphi

L'application serveur est une application Delphi comportant une fiche avec un objet de type TMemo et dont l'unité suit (les unités HelloApp_c, HelloApp_i, HelloApp_impl et HelloApp_s ont été générées par idl2pas) :

unit ServerMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Corba, HelloApp_c, HelloApp_i, HelloApp_impl, HelloApp_s, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  protected
    FHello : Hello; // objet "skeleton"
    procedure InitCorba;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.InitCorba;
begin
  CorbaInitialize;

  // Créer le serveur
  FHello := THelloSkeleton.Create('Hello', THello.Create);
  BOA.ObjIsReady(FHello as _Object);

  // Afficher l'IOR de l'objet
  Memo1.Text := Orb.ObjectToString(FHello as CorbaObject);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  initCorba;
end;

end.


La classe THello déclarée dans l'unité "HelloApp_impl" définie la méthode sayHello qu'il suffit de compléter en saisissant par exemple :
Result := 'Hello World !';


Exécution

Voici l'ordre dans lequel exécuter chaque partie. Tout d'abord lancer l'osagent de Visibroker, suivi de l'application serveur. Le contrôle TMemo affiche alors l'IOR de l'objet serveur à reporter dans le code source Java du client.
Le client peut alors être exécuté pour afficher le traditionnel message "Hello World !".
Cette façon de faire n'est pas très élégante ! Une meilleur solution consisterait à ce que l'application écrive l'IOR dans un fichier qui serait alors rendu disponible au travers d'un serveur web. L'application cliente Java réclamerait ce fichier par une requête HTTP avant de réaliser ses invocations.

Retour à la page d'accueil

Pont Java-ActiveX

(Septembre 2000)

La bibliothèque Java Bridge2Java, que l'on peut télécharger sur le site d'IBM alphaWorks, permet d'accéder à des ActiveX depuis un programme Java.
L'installation fournit un exécutable -Bridge2Java.exe- qui pourra générer toutes les déclarations de classes et d'interfaces Java à partir d'une bibliothèque de types, incluse dans un module exécutable Windows ou bien dans un fichier de type .tlb ou .olb.
Ces classes servent donc à créer des contrôles ActiveX et contiennent l'ensemble des méthodes d'accès tirées de la bibliothèque de types.
On peut ainsi réutiliser le code sous forme d'activeX dans un environnement Java s'exécutant sous Windows, comme le montre les exemples fournies.
Par example, utiliser Word comme serveur OLE automation pour créer un nouveau document et y insérer du texte.
Ou encore, afficher le contrôle ActiveX de navigation d'Internet Explorer dans une applet Java.

Voici comment on peut appeler une méthode Echo de l'interface IBridge, implémenter par un objet OLE automation instancié dans un exécutable Windows, appelé project1.exe et écrit avec l'EDI Delphi.
Cette méthode prend comme seul argument une chaîne de caractère Unicode et la renvoie sans modification, tandis que Project1 affiche celle-ci dans une zone d'édition.
Appliqué sur le serveur d'objet, Bridge2Java.exe génère deux sources Java, IBridge.java et Bridge.java, Bridge étant pour notre serveur le nom de la CoClasse implémentant l'interface IBridge.
IBridge.java comprend la classe IBridge dérivant de la classe Dispatch de la bibliothèque Bridge2Java et reprenant en particulier la méthode Echo :

public String Echo(String Texte) {}
Le source Bridge.java contient la déclaration de la classe Bridge descendant de IBridge, avec quatre constructeurs.

Lors de l'exécution du programme de test Java, l'application Project1 renfermant l'objet Brigde se lance (si elle ne l'était pas), affiche le célèbre message 'Hello world !', puis se termine, du fait que le pointeur d'interface est libéré comme il se doit par te programme TestBgridge :

/*
 * TestBridge.java
 *
 * Created on 8 septembre 2000, 11:52
 */

import Project1.*;

/**
 *
 * @author BGoetzmann
 * @version
 */
public class TestBridge extends Object {

    /** Creates new TestBridge */
    public TestBridge() {
    }

    /**
    * @param args the command line arguments
    */
    public static void main (String args[]) {
        Bridge bridge;

        try {
            com.ibm.bridge2java.OleEnvironment.Initialize();

            bridge = new Bridge();

            System.out.println(bridge.Echo("Hello world !"));
        }
        catch (com.ibm.bridge2java.ComException e) {
            System.out.println("Exception COM");
            System.out.println( Long.toHexString((e.getHResult())) );
        }
        catch (Exception e) {
            System.out.println("Exception " + e.getMessage());
        }
        finally {
            com.ibm.bridge2java.OleEnvironment.UnInitialize();
        }
    }

}


Ressources

Téléchargement de Bridge2Java :
http://www.alphaworks.ibm.com/tech/bridge2java


Retour à la page d'accueil

Script XML

(Février 2000)

L'utilitaire présenté ici montre comment on peut utiliser XML comme langage de script de haut niveau. Ce qui m'a donné l'idée de cet article est le programme Java TaskGuide d'IBM, qui utilise des scripts XML pour générer automatiquement des assistants (wizards) destinés à guider l'utilisateur dans la saisie d'information.
Cet exemple est généralisable à tout type d'application.
L'application doit être capable de parcourir le script et de l'interpréter en vue d'effectuer certaines opérations.

Dans notre utilitaire nous voulons automatiser la création de fichiers zip en listant les fichiers à zipper et le nom du fichier zip final dans un fichier XML. Voici une version très simplifiée de ce fichier privé de DTD :

<ZIP>
  <FICHIER SRC= "A.txt" DEST= "C.zip"/>
  <FICHIER SRC= "B.txt" DEST= "C.zip"/>
</ZIP>

La balise FICHIER possède deux attributs : le premier désigne le fichier à zipper, le second dans quel fichier zip on souhaite le placer.
On pourrait offrir d'autre type de service afin d'automatiser certaines tâches comme la copie ou le déplacement de fichier.
Les fichiers scripts pourront être passés comme argument lors de l'exécution du programme avec si besoin une vérification de validité du document en indiquant une définition de type de document (DTD).

L'utilitaire est une application Delphi utilisant le parseur d'ICOM, mais rien n'empêche d'exploiter le parseur XML d'Internet Explorer comme objet ActiveX.

Retour à la page d'accueil

XMLOleObject

(Mai 2002)

Description

XMLOleObject comprend un ActiveX permettant la sérialisation/désérialisation des propriétés de tout objet OLE automation en chaîne de caractères XML.
L'intérêt est de fournir un support de persistance des objets automation sans nécessiter la modification de l'implémentation de ces objets ; d'autre part l'utilisation d'XML pour décrire les noms des propriétés et leurs valeurs permet d'avoir un format lisible et portable.


Exemple

Admettons que vous aillez développé ou que vous utilisiez un objet automation supportant l'interface COM nommée ITest (héritée de IDispatch) possédant les propriétés " ID " et " Nom ".
On obtient la représentation XML de cet objet en appelant la méthode getObjectAsXML (voir Interface de programmation plus loin), par exemple :

<ITest>
  <ID>123</ID>
  <Nom>Goetzmann</Nom>
</ITest>

Bien sûr, il faut au préalable avoir créé une instance de l'activeX de XMLOleObject.
Inversement, l'appel à la méthode setObjectAsXML avec en arguments une instance supportant ITest et une chaîne de caractères fournissant des valeurs différentes pour les propriétés " ID " et " Nom ", permettra une affectation automatique de ces propriétés.


Ressources

Télécharger l'activeX XMLOleObject avec sa documentation, ainsi qu'un projet de test Delphi 6.
XMLOleObject.zip


Retour à la page d'accueil

XMLStorage

(Mai 2002)

XMLStorage est un outil freeware permettant la création et la gestion de bases de données (simples) XML pour la sauvegarde et la restitution de documents XML.

Techniquement, une base de données XMLStorage est un fichier composite OLE dont les éléments sont organisés comme dans un système de fichiers : les éléments conteneurs sont appelés stockages (l'équivalent des répertoires) et peuvent comprendre d'autres stockages et des flux (l'équivalent des fichiers). Chaque flux représente un document XML.
D'autre part XMLStorage permet un accès multi-utilisateurs sur une base de données.

Une particularité d'XMLStorage est que tout ou partie de la base de données peut être vue comme un document XML. A partir d'un stockage, XMLStorage peut créer un document XML construit avec les données de tous les éléments appartenant à ce stockage. Ce document est référencé par un pointeur d'interface IXMLDOMDocument, ce qui permet toutes les opérations liées à cette interface (sauvegarde par save, interrogation par selectSingleNode, etc.).

La capture d'écran ci-dessous présente l'application XMLStgApp, fourni avec XMLStorage, après avoir ouvert un fichier de test et sélectionné le stockage " Contacts " comprenant deux documents XML :



XMLStorage est fourni avec l'application XMLStgApp.exe qui permet la création et la modification des fichiers composites qui ont l'extension xst par défaut. Il est ainsi possible d'importer un document XML dans un flux par le menu d'importation, ou d'exporter (copier) dans un fichier, les données XML d'un flux par le menu exporter.
D'autre part le menu " XML/Requête " permet d'effectuer une interrogation de la base de données en utilisant une chaîne de requête XPath saisie par l'utilisateur. Le menu " Options " de la boîte de dialogue de requête permet de choisir la manière d'afficher le résultat. Par exemple, à partir du fichier Test.xst fourni, pour obtenir l'adresse e-mail du contact dont le nom est " Goetzmann ", vous pouvez saisir la chaîne de requête :

//CONTACT[NOM='Goetzmann']/EMAIL


Interface de programmation

L'interface de programmation repose sur des objets automation, de sorte que tout langage supportant les objets COM et tout langage de script peut utiliser XMLStorage.
On se reportera au document XMLStorageAPI.rtf pour une description complète de l'interface de programmation avec des exemples de code en Pascal Objet et JavaScript.


Ressources

Télécharger XMLStorage 0.9 (activeX et documentation)
XMLStorage.zip


Retour à la page d'accueil

XRegistry

(Juin 2001)

L'application XRegistry permet le recensement d'instances d'objets COM qui sont alors rendus accessibles pour d'autres modules, exécutables ou DLL, à l'aide d'un nom unique.
En particulier, XRegistry peut maintenir des pointeurs d'interface COM IUnkown ou IDispatch, que toute application peut réclamer pour ensuite les utiliser.
Une application a ainsi un moyen simple d'accéder à une instance d'objet COM qu'une autre application aurait créé et recensé préalablement.

XRegistry est une application autonome et un serveur automation, de progID "XRegistry.Registry", implémentant l'interface IRegistry, et dont nous détaillons les méthodes ci-dessous.


Accéder à XRegistry

Il n'est pas nécessaire que XRegistry soit déjà exécuté pour l'utiliser. Une application pouvant créer des objets automations pourra en obtenir une référence par une instruction du type :

Reg := CreateOleObject('XRegistry.Registry'); // Reg est un Variant

A la première exécution de XRegistry, sa fenêtre d'application est minimisée.
Un nouvel appel de ce type, quelle que soit l'application cliente, renverrait le même pointeur d'interface, parce qu'une seule instance du programme est autorisée.


Recenser un objet

Recenser une instance d'objet s'effectue par la méthode :

procedure AddObject(const Name: WideString; Ptr: OleVariant);

Le premier argument est le nom qui servira d'identificateur pour recenser l'objet Ptr qui a le type compatible OLE automation OleVariant ; Ptr peut ainsi être un pointeur d'interface ou une valeur d'un type de base.
Lorsqu'un objet est recencé, le nom passé ici en argument est affiché dans l'application XRegistry.
Une exception est lancée si il existe déjà un objet portant le même nom.


Obtenir un objet

La méthode pour obtenir un objet recensé est tout aussi simple :

function GetObject(const Name: WideString): OleVariant;

GetObject renvoie l'objet correspondant au nom passé en argument. Une exception se produit si le nom ne correspond à aucune entrée de XRegistry.


Retirer un objet

Comme son nom l'indique la méthode :

procedure RemoveObject(const Name: WideString);

permet de "dé-recenser" un objet inscrit dans XRegistry.
Une exception peut se produire si le nom passé en argument de la méthode ne correspond à aucune entrée.


Ressource

Téléchargez XRegistry 1.0
xregistry.zip


Retour à la page d'accueil