Skip to content

10. Bouwen van gedistribueerde applicaties CORBA

10.1. Inleiding

In het vorige hoofdstuk hebben we gezien hoe we gedistribueerde applicaties in Java kunnen maken met het pakket RMI. Hier behandelen we hetzelfde probleem, maar ditmaal met de CORBA-architectuur. CORBA (Common Object Request Broker Architecture) is een specificatie die is gedefinieerd door de OMG (Object Management Group), een organisatie waarin talrijke bedrijven uit de IT-wereld zijn verenigd. CORBA definieert een „softwarebus“ die toegankelijk is voor applicaties die in verschillende talen zijn geschreven:

Image

We zullen zien dat het bouwen van een gedistribueerde applicatie met CORBA sterk lijkt op de methode die wordt gebruikt met Java RMI: de concepten zijn vergelijkbaar. CORBA biedt het voordeel van interoperabiliteit met applicaties die in andere talen zijn geschreven.

10.2. Ontwikkelingsproces van een CORBA-applicatie

10.2.1. Inleiding

Om een CORBA-client-server-applicatie te ontwikkelen, volgen we de volgende stappen:

  1. het schrijven van de serverinterface met IDL (Interface Definition Language)
  2. het genereren van de „skelet“- en „stub“-klassen van de server
  3. het schrijven van de server
  4. het schrijven van de client
  5. alle klassen compileren
  6. het opstarten van een CORBA-servicekatalogus
  7. het starten van de server
  8. de client starten

Als eerste voorbeeld nemen we de echo-server die al in de context RMI is gebruikt. Zo kan de lezer de verschillen tussen de twee methoden zien.

De toepassing is getest met jdk1.2.

10.2.2. Het schrijven van de serverinterface

Net als bij Java RMI wordt de server, vanuit het oogpunt van de client, bepaald door zijn interface. Als de klassen die de server implementeren niet nodig zijn voor de client, zijn de klassen van de interface dat wel. Waar Java RMI gebruikmaakte van een Java-interface die aanleiding gaf tot de ‘skelet’- en ‘stub’-klassen van de server, vereist de architectuur van Java CORBA dat de interface wordt beschreven in een andere taal dan Java. Deze interface zal leiden tot verschillende klassen, waarvan sommige door de client worden gebruikt en andere door de server.

De beschrijving van de echo-interface luidt als volgt:

module echo{
    interface iSrvEcho{
        string echo(in string msg);
    };
};

De beschrijving van de interface wordt opgeslagen in een bestand met de naam echo.idl. Deze is geschreven in de taal IDL (Interface Definition Language) van het OMG. Om bruikbaar te zijn, moet deze worden geanalyseerd door een programma dat bronbestanden aanmaakt in de taal die wordt gebruikt voor het ontwikkelen van de applicatie CORBA. Hier gebruiken we het programma idltojava.exe, dat op basis van de voorgaande interface de .java-bronbestanden aanmaakt die nodig zijn voor de applicatie. Het programma idltojava.exe wordt niet meegeleverd met JDK. Het is te downloaden op de website van Sun: http://java.sun.com.

Laten we de paar regels van de vorige idl-interface eens bekijken:

module echo

is gelijk aan het Java-pakket echo. Het compileren van de interface leidt tot het Java-pakket echo c.a.d, een map met Java-klassen.

interface iSrvEcho

komt overeen met de Java-interface iSrvEcho. Dit zal een Java-interface opleveren.

string echo(in string msg)

is gelijk aan de Java-instructie String echo(String msg). De typen van de taal IDL komen niet exact overeen met die van de taal Java. De overeenkomsten worden verderop in dit hoofdstuk beschreven. In de taal IDL kunnen de parameters van een functie invoerparameters (in), uitvoerparameters (out) of invoer-uitvoerparameters (inout) zijn. Hier ontvangt de methode echo een invoerparameter msg, die een tekenreeks is, en retourneert een tekenreeks als resultaat.

De vorige interface is die van onze echo-server. Ter herinnering: een externe interface beschrijft de methoden van het serverobject die toegankelijk zijn voor clients. Hier zal alleen de methode echo beschikbaar zijn voor clients.

10.2.3. Compileren van de serverinterface IDL

Zodra de serverinterface is gedefinieerd, worden de bijbehorende Java-bestanden gegenereerd.

E:\data\java\corba\ECHO>dir *.idl

ECHO     IDL            78  15/03/99  13:56 ECHO.IDL

E:\data\java\corba\ECHO>d:\javaidl\idltojava.exe -fno-cpp echo.idl

De optie -fno-cpp wordt gebruikt om aan te geven dat er geen preprocessor moet worden gebruikt (meestal gebruikt bij C/C++). Het compileren van het bestand echo.idl levert een submap echo op met daarin de volgende bestanden:

E:\data\java\corba\ECHO>dir echo

_ISRVE~1 JAV         1 095  17/03/99  17:19 _iSrvEchoStub.java
ISRVEC~1 JAV           311  17/03/99  17:19 iSrvEcho.java
ISRVEC~2 JAV           825  17/03/99  17:19 iSrvEchoHolder.java
ISRVEC~3 JAV         1 827  17/03/99  17:19 iSrvEchoHelper.java
_ISRVE~2 JAV         1 803  17/03/99  17:19 _iSrvEchoImplBase.java

Het bestand iSrvEcho.java is het Java-bestand waarin de serverinterface wordt beschreven:

/*  * Bestand: ./ECHO/ISRVECHO.JAVA  * Van: ECHO.IDL  * Datum: ma 15 mrt 13:56:08 1999  *   Door: D:\JAVAIDL\IDLTOJ~1.EXE Java IDL 1.2 18 aug. 1998 16:25:34  */

package echo;
public interface iSrvEcho
    extends org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity {
    String echo(String msg)
;
}

We zien dat dit vrijwel een woord-voor-woordvertaling is van de interface IDL. Als we uit nieuwsgierigheid de inhoud van de andere bestanden, zoals .java, bekijken, vinden we complexere zaken. Dit is wat de documentatie zegt over de rol van deze verschillende bestanden:

iSrvEcho.java

de serverinterface

_iSrvEchoImplbase.java

implementeert de voorgaande interface iSrvEcho. Het is een abstracte klasse, het ‘skelet’ van de server, die de server de CORBA-functionaliteiten verschaft die nodig zijn voor de gedistribueerde applicatie.

_iSrvEchoStub.java

Dit is de ‘stub’ van de server die door de client zal worden gebruikt. Deze biedt de client de CORBA-functionaliteiten om verbinding te maken met de server.

iSrvEchoHelper.java

Biedt de methoden die nodig zijn voor het beheer van objectverwijzingen CORBA

iSrvEchoHolder.java

Biedt de methoden die nodig zijn voor het beheer van de invoer- en uitvoerparameters van de methoden van de interface.

10.2.4. Compileren van de klassen die zijn gegenereerd op basis van de interface IDL

Het is een goed idee om de bovenstaande klassen te compileren. In een ander voorbeeld zullen we zien dat hier fouten aan het licht kunnen komen als gevolg van een onjuiste werking van de generator idltojava. Hier verloopt alles goed, en na het compileren bevinden zich in de map van het pakket echo de volgende bestanden:

E:\data\java\corba\ECHO\echo>dir

_ISRVE~1 JAV         1 095  17/03/99  17:19 _iSrvEchoStub.java
ISRVEC~1 JAV           311  17/03/99  17:19 iSrvEcho.java
ISRVEC~2 JAV           825  17/03/99  17:19 iSrvEchoHolder.java
ISRVEC~3 JAV         1 827  17/03/99  17:19 iSrvEchoHelper.java
_ISRVE~2 JAV         1 803  17/03/99  17:19 _iSrvEchoImplBase.java
_ISRVE~1 CLA         2 275  18/03/99  11:25 _iSrvEchoImplBase.class
_ISRVE~2 CLA         1 383  18/03/99  11:25 _iSrvEchoStub.class
ISRVEC~1 CLA           251  18/03/99  11:25 iSrvEcho.class
ISRVEC~2 CLA         2 078  18/03/99  11:25 iSrvEchoHelper.class
ISRVEC~3 CLA           858  18/03/99  11:25 iSrvEchoHolder.class

10.2.5. Serverboekingen

10.2.5.1. Implementatie van de interface iSrvEcho

We hebben hierboven de interface iSrvEcho gedefinieerd. We schrijven nu de klasse die deze interface implementeert. Deze zal afgeleid zijn van de klasse _iSrvEchoImplbase.java, die zoals hierboven aangegeven de interface iSrvEcho al implementeert.

// geïmporteerde pakketten
import echo.*;

// klasse die de remote-echo implementeert
public class srvEcho extends _iSrvEchoImplBase{
    // methode die de echo uitvoert
    public String echo(String msg){
        return  "["  + msg + "]";
    }// einde echo
}// einde klasse

De code spreekt voor zich. Deze klasse wordt opgeslagen in het bestand srvEcho.java in de bovenliggende map van het pakket van de interface iSrvEcho.

Je kunt het compileren om te controleren:

E:\data\java\corba\ECHO>j:\jdk12\bin\javac srvEcho.java

E:\data\java\corba\ECHO>dir

ECHO     IDL            78  15/03/99  13:56 ECHO.IDL
SRVECH~1 CLA           488  18/03/99  11:30 srvEcho.class
SRVECH~1 JAV           252  15/03/99  14:02 srvEcho.java
ECHO           <REP>        17/03/99  17:19 echo

10.2.5.2. De aanmaakklasse van de server vastleggen

Net als bij een client-servertoepassing RMI moet een server CORBA in een directory worden geregistreerd om voor clients toegankelijk te zijn. Het is deze registratieprocedure die, op ontwikkelingsniveau, verschilt naargelang het gaat om een CORBA- of een RMI-toepassing. Hieronder volgt de registratie van de CORBA-echo-server, vastgelegd in het bestand serveurEcho.java:

// geïmporteerde pakketten
import echo.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

//----------- klasse serveurEcho
public class serveurEcho{
    // ------- main: start de echo-server
    // pg-syntaxis machineAnnuaire portAnnuaire nomService
    // machine: machine die de directory ondersteunt CORBA
    // poort: poort van de directory CORBA
    // nomService: naam van de te registreren dienst

  public static void main(String arg[]){
    // zijn de argumenten aanwezig?
    if(arg.length!=3){
        System.err.println("Syntaxe : pg machineAnnuaire portAnnuaire nomService");
        System.exit(1);
    }
    // we halen de argumenten op
    String machine=arg[0];
    String port=arg[1];
    String nomService=arg[2];

    try{

    // we hebben een object CORBA nodig om te kunnen werken
    String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
      ORB orb=ORB.init(initORB,null);
    // we voegen de service toe aan de servicelijst
    // de naam wordt srvEcho
      org.omg.CORBA.Object objRef=
        orb.resolve_initial_references("NameService");
      NamingContext ncRef=NamingContextHelper.narrow(objRef);
      NameComponent nc= new NameComponent(nomService,"");
      NameComponent path[]={nc};
    // we maken de server aan en koppelen deze aan de dienst srvEcho
    srvEcho serveurEcho=new srvEcho();
      ncRef.rebind(path,serveurEcho);
    orb.connect(serveurEcho);
    // opvolging
    System.out.println("Serveur d'écho prêt");
    // wachten op verzoeken van klanten
      java.lang.Object sync=new java.lang.Object();
      synchronized(sync){
        sync.wait();
      }
    } catch(Exception e){
    // er is een fout opgetreden
      System.err.println("Erreur " + e);
      e.printStackTrace(System.err);
    }
  }// hoofd
}// serveurEcho

Hieronder leggen we de hoofdlijnen van het opstarten van de server uit, zonder in te gaan op de details die op het eerste gezicht complex lijken. Onthoud de hoofdlijnen uit het vorige voorbeeld, want die komen in elke CORBA-server terug.

10.2.5.2.1. De serverinstellingen

Een CORBA-server moet zich registreren bij een directorydienst die op een bepaalde machine en poort draait. Onze applicatie ontvangt deze twee gegevens als parameters. De geregistreerde dienst moet een naam hebben; dit is de derde parameter.

10.2.5.2.2. Het object voor toegang tot de directorydienst CORBA aanmaken

Om de directorydienst te bereiken en onze echo-server te registreren, hebben we een object nodig met de naam ORB (Object Request Broker), dat wordt verkregen met de volgende klassemethode:

ORB ORB.init(String [] args, Properties prop)

Args :     tableau de paires de chaînes de caractères, chaque paire étant de la forme (paramètre,valeur)

Prop :     propriétés de l’application

In het voorbeeld wordt de volgende reeks gebruikt om het object ORB op te halen:


    String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
       ORB orb=ORB.init(initORB,null);

De gebruikte (parameter, waarde)-paren zijn de volgende:


("-ORBInitialHost",machine) : ce couple précise la machine ou opère l’annuaire des services CORBA, ici la machine passée en paramètre au serveur.

("-ORBInitialPort",port ) : ce couple précise le port ou opère l’annuaire des services CORBA, ici le port passé en paramètre au serveur.

De tweede parameter van de methode init wordt ingesteld op null. Als de eerste parameter ook op null was ingesteld, zou het gebruikte (machine,poort)-paar standaard (localhost,900) zijn geweest.

10.2.5.2.3. De server registreren in de dienstenlijst CORBA

De server wordt als volgt in de directory geregistreerd:

    // de dienst wordt in de dienstenlijst opgenomen
    // de naam wordt srvEcho
      org.omg.CORBA.Object objRef=
        orb.resolve_initial_references("NameService");
      NamingContext ncRef=NamingContextHelper.narrow(objRef);
      NameComponent nc= new NameComponent(nomService,"");
      NameComponent path[]={nc};
    // we maken de server aan en koppelen deze aan de dienst srvEcho
    srvEcho serveurEcho=new srvEcho();
          ncRef.rebind(path,serveurEcho);
            orb.connect(serveurEcho);

Het eerste deel van de code bestaat uit het voorbereiden van de naam van de dienst. Deze naam wordt in de code aangeduid met de variabele path. De naam van een dienst bestaat uit verschillende onderdelen:

  • een initiële component objRef, een generiek object dat moet worden omgezet naar het type NamingContext, in dit geval ncRef.
  • de naam van de dienst, hier nomService, die als parameter aan de server is doorgegeven

Deze onderdelen van de naam (NameComponent) worden verzameld in een array, hier path. Het is deze array die de aangemaakte service precies ‘benoemt’. Zodra de naam is aangemaakt, moet deze nog

  • moet deze worden gekoppeld aan een exemplaar van de server (de eerder geconstrueerde klasse srvEcho)

srvEcho serveurEcho=new srvEcho();
  • en deze op te nemen in de directory
    ncRef.rebind(path,serveurEcho);
    orb.connect(serveurEcho);

10.2.5.3. Compileren van de server-startklasse

We compileren de vorige klasse:

E:\data\java\corba\ECHO>j:\jdk12\bin\javac serveurEcho.java

E:\data\java\corba\ECHO>dir

ECHO     IDL            78  15/03/99  13:56 ECHO.IDL
SERVEU~1 CLA         1 793  18/03/99  13:18 serveurEcho.class
SERVEU~1 JAV         1 806  16/03/99  15:38 serveurEcho.java
SRVECH~1 CLA           488  18/03/99  11:30 srvEcho.class
SRVECH~1 JAV           252  15/03/99  14:02 srvEcho.java
ECHO           <REP>        17/03/99  17:19 echo

10.2.6. Tekst van de klant

10.2.6.1. De code

We schrijven een client om onze echo-service te testen. We geven de client dezelfde drie parameters door als aan de server:

Machine: machine waarop de dienstenlijst zich bevindt CORBA

Poort: de poort waarop deze directory actief is

nomService: naam van de echo-service

De client maakt verbinding met de echo-service en vraagt de gebruiker vervolgens om berichten via het toetsenbord in te voeren. Deze worden naar de echo-server verzonden, die ze terugstuurt. Deze dialoog wordt op het scherm weergegeven.

De echo-dienstclient CORBA lijkt sterk op de reeds geschreven client RMI. Ook hier moet de client verbinding maken met een directorydienst om een referentie te verkrijgen van het serverobject waarmee hij verbinding wil maken. Het verschil tussen de twee clients ligt hierin en uitsluitend hierin. Hieronder volgt de code van de echo-client CORBA:


    

10.2.6.2. De verbinding van de client met de server

De hierboven genoemde client CORBA maakt verbinding met de server via de instructie:

        // we maken de verbinding met de echo-server
        iSrvEcho serveurEcho=getServeurEcho(machine,port,nomService);

Na afloop van deze bewerking beschikt de client over een referentie van de echo-server. Vervolgens verschilt een client CORBA niet van een client RMI. De privémethode die de verbinding met de server tot stand brengt, is de volgende:

// geïmporteerde pakketten
import java.io.*;
import echo.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;

// ---------- klasse cltEcho
public class cltEcho {

    public static void main(String arg[]){
         // syntaxis: cltEcho machineAnnuaire portAnnuaire servicenaam
         // machine: machine waarop de dienstenlijst draait CORBA
         // poort: poort waarop de servicelijst actief is
         // nomService: naam van de echo-service

         // controle van de argumenten
        if(arg.length!=3){
            System.err.println("Syntaxe : pg machineAnnuaire portAnnuaire nomservice");
            System.exit(1);
        }

         // de parameters worden opgehaald
        String machine=arg[0];
        String port=arg[1];
        String nomService=arg[2];

         // verbinding maken met de echo-server
        iSrvEcho serveurEcho=getServeurEcho(machine,port,nomService);

         // client-servercommunicatie
        BufferedReader in=null;
        String msg=null;
        String reponse=null;
        iSrvEcho serveur=null;

        try{
             // toetsenbordstream openen
            in=new BufferedReader(new InputStreamReader(System.in));
             // lus voor het lezen van berichten die naar de echo-server moeten worden verzonden
            System.out.print("Message : ");
            msg=in.readLine().toLowerCase().trim();
            while(! msg.equals("fin")){
                 // verzending van het bericht naar de server en ontvangst van het antwoord
                reponse=serveurEcho.echo(msg);
                 // vervolging
                System.out.println("Réponse serveur : " + reponse);
                 // volgend bericht
                System.out.print("Message : ");                
                msg=in.readLine().toLowerCase().trim();
            }// while
             // klaar
            System.exit(0);
         // foutafhandeling         
        } catch (Exception e){
            System.err.println("Erreur : " + e);
            System.exit(2);
        }// try
    }// main

     // ---------------------- getServeurEcho
    private static iSrvEcho getServeurEcho(String machine, String port, 
            String nomService){

         // vraagt een referentie aan bij de echo-server
         // tracking
        System.out.println("--> Connexion au serveur CORBA en cours...");
         // de referentie van de echo-server
        iSrvEcho serveurEcho=null;
        try{
             // er wordt een object CORBA aangevraagd om te kunnen werken
            String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};    
          ORB orb=ORB.init(initORB,null);
             // de directorydienst wordt gebruikt om de echo-server te lokaliseren
          org.omg.CORBA.Object objRef=
                orb.resolve_initial_references("NameService");
          NamingContext ncRef=NamingContextHelper.narrow(objRef);
             // de gezochte dienst heet srvEcho – deze wordt aangevraagd
          NameComponent nc= new NameComponent(nomService,"");
          NameComponent path[]={nc};
          serveurEcho=iSrvEchoHelper.narrow(ncRef.resolve(path));
        } catch (Exception e){
            System.err.println("Erreur lors de la localisation du serveur d'écho ("
                + e + ")");
            System.exit(10);
        }// try-catch
         // de verwijzing naar de server wordt teruggegeven
        return serveurEcho;
    }// getServeurEcho

}// klasse

We zien hier dezelfde codereeksen als op de server:

  • we maken een object ORB aan waarmee we verbinding kunnen maken met de CORBA-servicedirectory
String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};    
      ORB orb=ORB.init(initORB,null);
  • we definiëren de verschillende onderdelen van de naam van de echo-dienst
        org.omg.CORBA.Object objRef=orb.resolve_initial_references("NameService");
      NamingContext ncRef=NamingContextHelper.narrow(objRef);
      NameComponent nc= new NameComponent(nomService,"");
      NameComponent path[]={nc};
  • we vragen de directorydienst om een referentie van de echo-dienst (hierin verschillen we van de server)
serveurEcho=iSrvEchoHelper.narrow(ncRef.resolve(path));

10.2.6.3. Compilation

E:\data\java\corba\ECHO>j:\jdk12\bin\javac cltEcho.java

E:\data\java\corba\ECHO>dir

CLTECH~1 CLA         2 599  18/03/99  13:51 cltEcho.class
CLTECH~1 JAV         2 907  16/03/99  16:15 cltEcho.java
ECHO     IDL            78  15/03/99  13:56 ECHO.IDL
SERVEU~1 CLA         1 793  18/03/99  13:18 serveurEcho.class
SERVEU~1 JAV         1 806  16/03/99  15:38 serveurEcho.java
SRVECH~1 CLA           488  18/03/99  11:30 srvEcho.class
SRVECH~1 JAV           252  15/03/99  14:02 srvEcho.java
ECHO           <REP>        17/03/99  17:19 echo

10.2.7. Tests

10.2.7.1. De directorydienst starten

Op een Windows-computer starten we de directorydienst als volgt:

E:\data\java\corba\ECHO>start j:\jdk12\bin\tnameserv -ORBInitialPort 1000

waardoor de directory-service op poort 1000 van de computer wordt gestart.

De directorydienst tnameserv genereert een schermweergave die er als volgt uitziet:

Initial Naming Context:
IOR:000000000000002849444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f
6e746578743a312e3000000000010000000000000030000100000000000a69737469612d30303900
044700000018afabcafe000000027620dd9a000000080000000000000000
TransientNameServer: setting port for initial object references to: 1000

Het is wat moeilijk te lezen, maar onthoud vooral de laatste regel: de service is actief op poort 1000.

10.2.7.2. Start van de echo-server

De echo-service wordt gestart met drie parameters:


E:\data\java\corba\ECHO>start j:\jdk12\bin\java serveurEcho localhost 1000 srvEcho

De server geeft het volgende weer:

    Serveur d’écho prêt

10.2.7.3. De client wordt gestart op dezelfde computer als de server


E:\data\java\corba\ECHO>j:\jdk12\bin\java cltEcho localhost 1000 srvEcho
--> Connexion au serveur CORBA en cours...
Message : msg1
Réponse serveur : [msg1]
Message : msg2
Réponse serveur : [msg2]
Message : fin

10.2.7.4. De client starten op een Windows-computer die niet dezelfde is als de server

E:\data\java\corba\ECHO>j:\jdk12\bin\java cltEcho tahe.istia.univ-angers.fr 1000 srvEcho
--> Connexion au serveur CORBA en cours...
Message : abcd
Réponse serveur : [abcd]
Message : efgh
Réponse serveur : [efgh]
Message : fin

10.3. Voorbeeld 2: een server SQL

10.3.1. Inleiding

We behandelen hier nogmaals de implementatie van de SQL-server, die we al hebben besproken in de context van Java RMI, opnieuw om de overeenkomsten en verschillen tussen beide methoden te benadrukken. We herinneren aan de rol van deze server SQL: hij staat op een Windows-computer en stelt externe clients in staat om de openbare databases ODBC van deze Windows-computer te gebruiken.

Image

De client CORBA kan drie bewerkingen uitvoeren:

  • verbinding maken met een database naar keuze
  • SQL-verzoeken verzenden
  • de verbinding verbreken

De server voert de verzoeken SQL van de client uit en stuurt de resultaten terug. Dit is zijn belangrijkste taak en daarom noemen we hem een SQL-server. We passen de verschillende stappen toe die we eerder bij de echo-server hebben gezien.

10.3.2. Het schrijven van de interface IDL van de server

Ter herinnering: dit is de RMI-interface die we voor de server hadden gebruikt:

import java.rmi.*;

// de externe interface
public interface interSQL extends Remote{
    public String connect(String pilote, String url, String id, String mdp)
        throws java.rmi.RemoteException;
    public String[] executeSQL(String requete, String separateur) 
        throws java.rmi.RemoteException;
    public String close()
        throws java.rmi.RemoteException;
}

De verschillende methoden hadden de volgende functies:

Connect: de client maakt verbinding met een externe database en geeft daarbij de driver, de URL JDBC, evenals zijn gebruikersnaam (id) en wachtwoord (mdp) op om toegang te krijgen tot deze database. De server retourneert een tekenreeks die het resultaat van de verbinding aangeeft:

    200 - Connexion réussie
    500 - Echec de la connexion

executeSQL: de client vraagt om het uitvoeren van een query SQL op de database waarmee hij is verbonden. Hij geeft het teken aan dat de velden moet scheiden in de resultaten die naar hem worden teruggestuurd. De server stuurt een array met tekenreeksen terug:

    100 n

voor een query om de database bij te werken, waarbij n het aantal bijgewerkte rijen is

    500 msg d’erreur

als de aanvraag een fout heeft gegenereerd

    501 Pas de résultats

als de aanvraag geen resultaat heeft opgeleverd

    101 ligne1
    101 ligne2
    101 ...

als de zoekopdracht resultaten heeft opgeleverd. De regels die de server op deze manier terugstuurt, zijn de resultaten van de zoekopdracht.

Close: de client verbreekt de verbinding met de externe database. De server stuurt een tekenreeks terug die het resultaat van deze verbreking aangeeft:

    200 Base fermée
    500 Erreur lors de la fermeture de la base (msg d’erreur)

De interface IDL van de server ziet er als volgt uit:

module srvSQL{

    typedef sequence<string> resultats;

    interface interSQL{
        string connect(in string pilote, in string urlBase, in string id, in string mdp);
        resultats executeSQL(in string requete, in string separateur);
        string close();
    };// interface
};// module

Het enige verschil ten opzichte van wat we hebben gezien bij de interface IDL van de echo-server is het gebruik van het sleutelwoord sequence. Met dit sleutelwoord kan een eendimensionale array worden gedefinieerd. De definitie verloopt in twee stappen:

  • het definiëren van een type om de array aan te duiden, in dit geval ‘resultats’:
typedef sequence<string> resultats;

Het sleutelwoord typedef is bij C/C++-programmeurs welbekend: hiermee kan een nieuw type worden gedefinieerd. Hier wordt het type resultats gedefinieerd als equivalent aan het type sequence<string>, c.a.d: een dynamische (ongedimensioneerde) array van tekenreeksen.

  • Gebruik het nieuwe type waar het nodig is
resultats executeSQL(in string requete, in string separateur);

De methode executeSQL retourneert dus een array van tekenreeksen.

10.3.3. Compileren van de serverinterface IDL

De vorige interface IDL wordt in het bestand srvSQL.idl geplaatst. Dit bestand wordt gecompileerd:

E:\data\java\corba\sql>d:\javaidl\idltojava -fno-cpp srvSQL.idl

E:\data\java\corba\sql>dir

SRVSQL   IDL           275  19/03/99   9:59 srvSQL.idl
SRVSQL         <REP>        19/03/99   9:41 srvSQL

We zien dat de compilatie een map heeft aangemaakt met de naam van de interface-module IDL (srvSQL). Laten we eens kijken naar de inhoud van deze map:

E:\data\java\corba\sql>dir srvSQl

RESULT~1 JAV           833  19/03/99  10:00 resultatsHolder.java
RESULT~2 JAV         1 883  19/03/99  10:00 resultatsHelper.java
_INTER~1 JAV         2 474  19/03/99  10:00 _interSQLStub.java
INTERS~1 JAV           448  19/03/99  10:00 interSQL.java
INTERS~2 JAV           841  19/03/99  10:00 interSQLHolder.java
INTERS~3 JAV         1 855  19/03/99  10:00 interSQLHelper.java
_INTER~2 JAV         4 535  19/03/99  10:00 _interSQLImplBase.java

Ter herinnering: de bestanden Helper en Holder zijn klassen die verband houden met de invoer- en uitvoerparameters en de resultaten van de methoden van de externe interface. De map srvSQL bevat alle .java-bestanden die verband houden met de interface interSQL die in het .idl-bestand is gedefinieerd. Het bevat ook bestanden die verband houden met het type resultats dat is aangemaakt in de interface IDL.

Het bestand interSQL.java is het Java-bestand van de interface van onze server. Het is belangrijk om te controleren of wat automatisch is gegenereerd, overeenkomt met onze verwachtingen. Het gegenereerde bestand interSQL.java ziet er als volgt uit:

/*  * Bestand: ./SRVSQL/INTERSQL.JAVA  * Van: SRVSQL.IDL  * Datum: vr 19 mrt 09:59:48 1999  *   Door: D:\JAVAIDL\IDLTOJ~1.EXE Java IDL 1.2 18 aug. 1998 16:25:34  */

package srvSQL;
public interface interSQL
    extends org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity {
    String connect(String pilote, String urlBase, String id, String mdp)
;
    String[] executeSQL(String requete, String separateur)
;
    String close()
;
}

We zien dat we dezelfde interface hebben als die welke wordt gebruikt voor de client-server RMI. We kunnen dus doorgaan. Laten we al deze .java-bestanden compileren:

E:\data\java\corba\sql\srvSQL>j:\jdk12\bin\javac *.java

Note: _interSQLImplBase.java uses or overrides a deprecated API.  Recompile with
 "-deprecation" for details.
1 warning

E:\data\java\corba\sql\srvSQL>dir *.class

_INTER~1 CLA         3 094  19/03/99  10:01 _interSQLImplBase.class
_INTER~2 CLA         1 953  19/03/99  10:01 _interSQLStub.class
INTERS~1 CLA           430  19/03/99  10:01 interSQL.class
INTERS~2 CLA         2 096  19/03/99  10:01 interSQLHelper.class
INTERS~3 CLA           870  19/03/99  10:01 interSQLHolder.class
RESULT~1 CLA         2 047  19/03/99  10:01 resultatsHelper.class
RESULT~2 CLA           881  19/03/99  10:01 resultatsHolder.class

10.3.4. Servercode SQL

We schrijven nu de code van de server SQL. Ter herinnering: deze klasse moet afleiden van de abstracte klasse _nomInterfaceImplBase, die wordt gegenereerd door de compilatie van het bestand IDL. Afgezien van dit specifieke kenmerk en met uitzondering van de codereeksen die betrekking hebben op de registratie van de dienst in een directory, is de code van de server CORBA identiek aan die van de server RMI:

// geïmporteerde pakketten
import java.sql.*;
import java.util.*;
import srvSQL.*;

// klasse SQLServant
public class SQLServant extends _interSQLImplBase{

    // globale gegevens van de klasse
    private Connection DB;

    // --------------- verbinding
    public String connect(String pilote, String url, String id,
        String mdp){

        // verbinding met de database-URL via de driver
        // authenticatie met gebruikersnaam id en wachtwoord mdp

        String resultat=null;            // resultaat van de methode
        try{
            // het laden van de driver
            Class.forName(pilote);
            // verbindingsverzoek
            DB=DriverManager.getConnection(url,id,mdp);
            // ok
            resultat="200 Connexion réussie";
        } catch (Exception e){
            // fout
            resultat="500 Echec de la connexion (" + e + ")";
        }
        // einde
        return resultat;
    }            

    // ------------- executeSQL
    public String[] executeSQL(String requete, String separateur){

        // voert een query SQL uit op de database DB
        // en plaatst de resultaten in een array van strings

        // gegevens die nodig zijn voor het uitvoeren van de query
        Statement S=null;
        ResultSet RS=null;
        String[] lignes=null;
        Vector resultats=new Vector();
        String ligne=null;

        try{
            // aanmaken van de querycontainer
            S=DB.createStatement();
            // uitvoering van de query
            if (! S.execute(requete)){
                // updatequery
                // het aantal bijgewerkte rijen wordt teruggestuurd
                lignes=new String[1];
                lignes[0]="100 "+S.getUpdateCount();
                return lignes;
            }
            // dit was een opvraagquery
            // de resultaten worden opgehaald
            RS=S.getResultSet();
            // aantal velden in de Resultset
            int nbChamps=RS.getMetaData().getColumnCount();
            // deze worden verwerkt
            while(RS.next()){
                // de resultatenrij wordt aangemaakt
                ligne="101 ";
                for (int i=1;i<nbChamps;i++)
                    ligne+=RS.getString(i)+separateur;
                ligne+=RS.getString(nbChamps);
                // toevoeging aan de resultatenvector
                resultats.addElement(ligne);
            }// while
            // einde van de verwerking van de resultaten
            // de bronnen worden vrijgegeven
            RS.close();
            S.close();
            // de resultaten worden teruggestuurd
            int nbLignes=resultats.size();
            if (nbLignes==0){
                lignes=new String[1];
                lignes[0]="501 Pas de résultats";
            } else {
                lignes=new String[resultats.size()];
                for(int i=0;i<lignes.length;i++)
                    lignes[i]=(String) resultats.elementAt(i);
            }//if
            return lignes;
        } catch (Exception e){
            // fout
            lignes=new String[1];
            lignes[0]="500 " + e;
            return lignes;
        }// try-catch
    }// executeSQL

    // --------------- sluiten
    public String close(){
        // sluit de verbinding met de database
        String resultat=null;
        try{
            DB.close();
            resultat="200 Base fermée";
        } catch (Exception e){
            resultat="500 Erreur à la fermeture de la base ("+e+")";
        }
        // het resultaat teruggeven
        return resultat;
    }
}// klasse SQLServant

Deze klasse staat in het bestand SQLServant.java dat we compileren:

E:\data\java\corba\sql>dir

SRVSQL   IDL           275  19/03/99   9:59 srvSQL.idl
SRVSQL         <REP>        19/03/99   9:41 srvSQL
SQLSER~1 JAV         2 941  15/03/99   9:09 SQLServant.java

E:\data\java\corba\sql>j:\jdk12\bin\javac SQLServant.java

E:\data\java\corba\sql>dir *.class

SQLSER~1 CLA         2 568  19/03/99  10:19 SQLServant.class

10.3.5. Het schrijfprogramma voor het opstarten van de server SQL

De vorige klasse vertegenwoordigt de server SQL zodra deze is gestart. Vooraf moet deze worden geregistreerd in een dienstenmap CORBA. Net als bij de echo-dienst doen we dit met een speciale klasse waaraan we tijdens de uitvoering drie parameters doorgeven:

Machine: de machine waarop de servicelijst CORBA zich bevindt

Poort: de poort waarop deze directory actief is

nomService: naam van de dienst SQL

De code van deze klasse is vrijwel identiek aan die van de klasse die hetzelfde deed voor de echo-service. We hebben de regel die tussen beide klassen verschilt vetgedrukt weergegeven: deze maakt niet hetzelfde serverobject aan. We zien dus dat we nog steeds dezelfde mechanica hebben voor het opstarten van de server. Als we deze mechanica in een klasse isoleren, zoals hier is gedaan, wordt deze vrijwel transparant voor de ontwikkelaar.

// geïmporteerde pakketten
import srvSQL.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

//----------- klasse serveurSQL
public class serveurSQL{
    // ------- main: start de server SQL
  public static void main(String arg[]){
        // serveurSQL machine-poort-service

        //is het aantal argumenten correct
        if(arg.length!=3){
            System.err.println("Syntaxe : pg machineAnnuaireCorba portAnnuaireCorba nomService");
            System.exit(1);
        }
        // we halen de argumenten op
        String machine=arg[0];
        String port=arg[1];
        String nomService=arg[2];
        String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
    try{
            // we hebben een object CORBA nodig om te kunnen werken
      ORB orb=ORB.init(initORB,null);
            // we voegen de service toe aan de serviceslijst
      org.omg.CORBA.Object objRef=
        orb.resolve_initial_references("NameService");
      NamingContext ncRef=NamingContextHelper.narrow(objRef);
      NameComponent nc= new NameComponent(nomService,"");
      NameComponent path[]={nc};
        // we maken de server aan en koppelen deze aan de dienst srvSQL
        SQLServant serveurSQL=new SQLServant();
      ncRef.rebind(path,serveurSQL);
        orb.connect(serveurSQL);
        // opvolging
        System.out.println("Serveur SQL prêt");
        // wachten op verzoeken van klanten
      java.lang.Object sync=new java.lang.Object();
      synchronized(sync){
        sync.wait();
      }
    } catch(Exception e){
            // er is een fout opgetreden
      System.err.println("Erreur " + e);
      e.printStackTrace(System.err);
    }
  }// hoofd
}// srvSQL

We compileren deze nieuwe klasse:

E:\data\java\corba\sql>j:\jdk12\bin\javac serveurSQL.java

E:\data\java\corba\sql>dir *.class

SQLSER~1 CLA         2 568  19/03/99  10:19 SQLServant.class
SERVEU~1 CLA         1 800  19/03/99  10:33 serveurSQL.class

10.3.6. Client-opdracht

De client van de server CORBA wordt aangeroepen met de volgende parameters:

    machine port nomServiceAnnuaire pilote urlBase id mdp separateur

machine: machine waarop de CORBA-servicelijst zich bevindt

poort: de poort waarop deze directory actief is

nomService: naam van de dienst SQL

driver: driver die de server SQL moet gebruiken om de gewenste database te beheren

urlBase: URL JDBC van de te beheren database

id: identiteit van de klant of null indien geen identiteit

mdp: wachtwoord van de klant of null indien er geen wachtwoord is

scheidingsteken: teken dat de server SQL moet gebruiken om de velden in de resultatenregels van een query van elkaar te scheiden

Hier volgt een voorbeeld van mogelijke parameters:

    localhost 1000 srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null ,

waarbij:

machine: de machine waarop de CORBA-servicelijst zich bevindt

poort: de poort waarop deze directory actief is

srvSQL: srvSQL, naam CORBA van de server SQL

stuurprogramma: sun.jdbc.odbc.JdbcOdbcDriver, de standaarddriver voor databases met een ODBC-interface

urlBase: jdbc:odbc:articles, om een database ‘articles’ te gebruiken die is opgegeven in de lijst met openbare databases ODBC van de Windows-machine

id: null, geen identiteit

wachtwoord: null, geen wachtwoord

scheidingsteken: , de velden in de resultaten worden gescheiden door een komma

Zodra de client met de bovenstaande parameters is gestart, doorloopt deze de volgende stappen:

  • hij maakt verbinding met de machine machine op poort port om de service CORBA srvSQL aan te roepen
  • hij vraagt om verbinding met de artikel-database
connect(‘’sun.jdbc.odbc.JdbcOdbcDriver’’, ‘‘jdbc:odbc:articles’’, ’’’’, ’’’’)
  • hij vraagt de gebruiker om een zoekopdracht SQL via het toetsenbord in te voeren
  • deze wordt naar de server verzonden SQL
executeSQL(requete, ’’,’’);
  • het toont de door de server teruggestuurde resultaten op het scherm
  • het vraagt de gebruiker opnieuw om een zoekopdracht SQL via het toetsenbord in te voeren. Het stopt wanneer de zoekopdracht is voltooid.

Hieronder volgt de Java-code van de client. De opmerkingen zouden voldoende moeten zijn om deze te begrijpen. We zien dat:

  • de code identiek is aan die van de reeds besproken client RMI. Het verschil zit hem in het proces voor het aanvragen van de service bij de directory, een proces dat is ondergebracht in de methode getServeurSQL.
  • de methode getServeurSQL is identiek aan die welke voor de echo-client is geschreven

We zien dus dat:

  • een client CORBA alleen verschilt van een client RMI door de manier waarop hij contact maakt met de server
  • deze manier is identiek voor alle CORBA-clients
import srvSQL.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import java.io.*;

public class clientSQL {

    // algemene gegevens van de klasse
    private static String syntaxe =
        "syntaxe : cltSQL machine port service pilote urlBase id mdp separateur";
    private static BufferedReader in=null;
    private static interSQL serveurSQL=null;

    public static void main(String arg[]){
        // syntaxis: cltSQL machine poort scheidingsteken stuurprogramma url id wachtwoord
        // machine poort: machine en poort van de te contacteren CORBA-servicedirectory
        // service: naam van de service
        // driver: te gebruiken driver voor de te gebruiken database
        // urlBase: JDBC-URL van de te gebruiken database
        // id: gebruikers-ID
        // mdp: het wachtwoord
        // scheidingsteken: teken dat de velden in de resultaten van een query van elkaar scheidt

        // controle van het aantal argumenten
        if(arg.length!=8)
            erreur(syntaxe,1);

        // initieer parameters voor de verbinding met de database
        String machine=arg[0];
        String port=arg[1];
        String service=arg[2];        
        String pilote=arg[3];
        String urlBase=arg[4];
        String id, mdp, separateur;
        if(arg[5].equals("null")) id=""; else id=arg[5];
        if(arg[6].equals("null")) mdp=""; else mdp=arg[6];        
        if(arg[7].equals("null")) separateur=" "; else separateur=arg[7];        

        // parameters van de directorydienst CORBA
        String[] initORB={"-ORBInitialHost",arg[0],"-ORBInitialPort",arg[1]};
        // client CORBA - er wordt een serverreferentie aangevraagd SQL
        interSQL serveurSQL=getServeurSQL(machine,port,service);

        // dialoog tussen client en server
        String requete=null;
        String reponse=null;
        String[] lignes=null;
        String codeErreur=null;

        try{
            // het openen van de toetsenbordstream
            in=new BufferedReader(new InputStreamReader(System.in));
            // opvolging
            System.out.println("--> Connexion à la base de données en cours");
            // eerste verbindingsverzoek met de database
            reponse=serveurSQL.connect(pilote,urlBase,id,mdp);
            // vervolg
            System.out.println("<-- "+reponse);
            // analyse van het antwoord
            codeErreur=reponse.substring(0,3);
            if(codeErreur.equals("500")) 
                erreur("Abandon sur erreur de connexion à la base",3);
            // lus voor het lezen van de verzoeken die naar de server SQL moeten worden verzonden
            System.out.print("--> Requête : ");
            requete=in.readLine().toLowerCase().trim();
            while(! requete.equals("fin")){
                // het verzoek naar de server verzenden en het antwoord ontvangen
                lignes=serveurSQL.executeSQL(requete,separateur);
                // opvolging
                afficheLignes(lignes);
                // volgend verzoek
                System.out.print("--> Requête : ");                
                requete=in.readLine().toLowerCase().trim();
            }// while
            // vervolging
            System.out.println("--> Fermeture de la connexion à la base de données distante");
            // de verbinding wordt verbroken
            reponse=serveurSQL.close();
            // vervolg
            System.out.println("<-- " + reponse);
            // einde
            System.exit(0);
        // foutafhandeling        
        } catch (Exception e){
            erreur("Abandon sur erreur : " + e,2);
        }// try
    }// main

    // ----------- AfficheLignes
    private static void afficheLignes(String[] lignes){
        for (int i=0;i<lignes.length;i++)
            System.out.println("<-- " + lignes[i]);
    }// afficheLignes

    // ------------ fout
    private static void erreur(String msg, int exitCode){
        // foutmelding weergeven
        System.err.println(msg);
        // eventuele vrijgave van bronnen
        try{
            in.close();
            serveurSQL.close();
        } catch(Exception e){}
        // afsluiten
        System.exit(exitCode);
    }// fout

    // ---------------------- getServeurSQL
    private static interSQL getServeurSQL(String machine, String port, String service){
        // vraagt om een referentie van de server SQL
        // machine: machine uit de dienstenlijst CORBA
        // poort: poort van de servicelijst CORBA
        // service: naam van de aan te vragen service CORBA

        // tracking
        System.out.println("--> Connexion au serveur CORBA en cours...");
        // de serverreferentie SQL
        interSQL serveurSQL=null;
        // parameters van de directorydienst CORBA
        String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
                try{
            // er wordt een object CORBA aangevraagd om te kunnen werken – hiervoor wordt de poort 
            // luisterpoort van de servicesdirectory CORBA
      ORB orb=ORB.init(initORB,null);
            // we gebruiken de directorydienst om de server SQL te lokaliseren
      org.omg.CORBA.Object objRef=
        orb.resolve_initial_references("NameService");
      NamingContext ncRef=NamingContextHelper.narrow(objRef);
            // de gezochte dienst heet srvSQL – we vragen deze op
      NameComponent nc= new NameComponent(service,"");
      NameComponent path[]={nc};
      serveurSQL=interSQLHelper.narrow(ncRef.resolve(path));
        } catch (Exception e){
            System.err.println("Erreur lors de la localisation du serveur SQL ("
                + e + ")");
            System.exit(10);
        }// try-catch
        // de verwijzing naar de server wordt vrijgegeven
        return serveurSQL;
    }// getServeurSQL

}// klasse

Laten we de clientklasse compileren:

E:\data\java\corba\sql>j:\jdk12\bin\javac clientSQL.java

E:\data\java\corba\sql>dir *.class

SQLSER~1 CLA         2 568  19/03/99  10:19 SQLServant.class
SERVEU~1 CLA         1 800  19/03/99  10:33 serveurSQL.class
CLIENT~1 CLA         3 774  19/03/99  10:45 clientSQL.class

We zijn klaar voor de tests.

10.3.7. Tests

10.3.7.1. Pré-requis

We gaan ervan uit dat een database met de naam 'Artikelen' openbaar beschikbaar is op de Windows-server ACCESS:

Image

Deze database heeft de volgende structuur:

naam
type
code
4-cijferige artikelcode
nom
de naam (tekenreeks)
prix
de prijs (werkelijke)
stock_actu
de huidige voorraad (geheel getal)
stock_mini
de minimumvoorraad (geheel getal) waaronder het artikel moet worden bijgevuld

10.3.7.2. Lancering van de telefoongidsdienst

E:\data\java\corba\sql>start j:\jdk12\bin\tnameserv -ORBInitialPort 1000

Le service d’annuaire est lancé sur le port 1000. Il affiche dans une fenêtre DOS quelque chose du genre :

Initial Naming Context:
IOR:000000000000002849444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f
6e746578743a312e3000000000010000000000000030000100000000000a69737469612d30303900
052800000018afabcafe000000027693d3fd000000080000000000000000
TransientNameServer: setting port for initial object references to: 1000

10.3.7.3. De server SQL wordt gestart

We starten de SQL-server:

E:\data\java\corba\sql>start j:\jdk12\bin\java serveurSQL localhost 1000 srvSQL

Er verschijnt een venster met de tekst DOS:

    Serveur SQL prêt

10.3.7.4. Een client starten op dezelfde machine als de server

Dit zijn de resultaten die worden verkregen met een client op dezelfde machine als de server:

E:\data\java\corba\sql>j:\jdk12\bin\java clientSQL localhost 1000 srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null ,
--> Connexion au serveur CORBA en cours...
--> Connexion à la base de données en cours
<-- 200 Connexion réussie
--> Query: select naam, stock_actu, stock_mini from artikelen
<-- 101 vélo,31,8
<-- 101 arc,9,8
<-- 101 canoé,7,7
<-- 101 fusil,9,8
<-- 101 skis nautiques,13,8
<-- 101 essai3,13,9
<-- 101 cachalot,6,6
<-- 101 léopard,7,7
<-- 101 panthère,7,7
--> Query: delete from artikelen where stock_mini<7
<-- 100 1
--> Query: select naam, stock_actu, stock_mini from artikelen
<-- 101 vélo,31,8
<-- 101 arc,9,8
<-- 101 canoé,7,7
<-- 101 fusil,9,8
<-- 101 skis nautiques,13,8
<-- 101 essai3,13,9
<-- 101 léopard,7,7
<-- 101 panthère,7,7
--> Requête : fin
--> Fermeture de la connexion à la base de données distante
<-- 200 Base fermée

10.3.7.5. Een client starten op een andere machine dan die van de server

Dit zijn de resultaten die zijn verkregen met een client op een andere machine dan die van de server:

E:\data\java\corba\sql>j:\jdk12\bin\java clientSQL tahe.istia.univ-angers.fr 1000 srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null ,
--> Connexion au serveur CORBA en cours...
--> Connexion à la base de données en cours
<-- 200 Connexion réussie
--> Query: select * from artikelen
<-- 101 a300,v_lo,1202,31,8
<-- 101 d600,arc,5000,9,8
<-- 101 d800,canoé,1502,7,7
<-- 101 x123,fusil,3000,9,8
<-- 101 s345,skis nautiques,1800,13,8
<-- 101 f450,essai3,3,13,9
<-- 101 z400,léopard,500000,7,7
<-- 101 g457,panthère,800000,7,7
--> Requête : fin
--> Fermeture de la connexion à la base de données distante
<-- 200 Base fermée

10.4. Overeenkomsten tussen IDL en JAVA

Hier geven we de overeenkomsten weer tussen de eenvoudige typen IDL en JAVA:

type IDL
Java-type
boolean
boolean
char
char
wchar
char
byte
byte
string
java.lang.String
wstring
java.lang.String
short
short
unsigned short
short
long
int
unsigned long
int
long long
long
unsigned long long
long
float
float
double
double

Ter herinnering: om een array van elementen van het type T te definiëren in de interface IDL, gebruikt men de instructie:

    typedef   sequence<T> nomType;

en dat vervolgens nomType wordt gebruikt om naar het type van de array te verwijzen. Zo is in de serverinterface SQL de volgende declaratie gebruikt:

    typedef sequence<string> resultats;

zodat resultats verwijst naar een array String[] in Java.