Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5 (Tiger-Release)
Buch: Java ist auch eine Insel
gp Kapitel 18 Verteilte Programmierung mit RMI und SOAP
  gp 18.1 Entfernte Methoden
    gp 18.1.1 Wie entfernte Methoden arbeiten
    gp 18.1.2 Stellvertreter (Proxy)
    gp 18.1.3 RMI
    gp 18.1.4 Wie die Stellvertreter die Daten übertragen
    gp 18.1.5 Probleme mit entfernten Methoden
  gp 18.2 Nutzen von RMI bei Middleware-Lösungen
  gp 18.3 Die Lösung für Java ist RMI
    gp 18.3.1 Entfernte Objekte programmieren
    gp 18.3.2 Entfernte und lokale Objekte im Vergleich
  gp 18.4 Definition einer entfernten Schnittstelle
  gp 18.5 Das entfernte Objekt
    gp 18.5.1 Der Bauplan für entfernte Objekte
    gp 18.5.2 Der Konstruktor
    gp 18.5.3 Implementierung der entfernten Methoden
  gp 18.6 Stellvertreterobjekte erzeugen
    gp 18.6.1 Das Dienstprogramm rmic
  gp 18.7 Der Namensdienst (Registry)
    gp 18.7.1 Der Port
  gp 18.8 Der Server
    gp 18.8.1 Entfernte Objekte beim Namensdienst anmelden
    gp 18.8.2 Automatisches Anmelden bei Bedarf
  gp 18.9 Einen Client programmieren
    gp 18.9.1 Einfaches Logging
  gp 18.10 Aufräumen mit dem DGC
  gp 18.11 Entfernte Objekte übergeben und laden
    gp 18.11.1 Klassen vom RMI-Klassenlader nachladen
    gp 18.11.2 Sicherheitsmanager
  gp 18.12 Registry wird vom Server gestartet
  gp 18.13 RMI über die Firewall
    gp 18.13.1 RMI über HTTP getunnelt
  gp 18.14 RMI und CORBA
  gp 18.15 UnicastRemoteObject, RemoteServer und RemoteObject
  gp 18.16 Daily Soap
    gp 18.16.1 SOAP-Implementierung der Apache-Gruppe
    gp 18.16.2 Einen Client mit der Apache-Bibliothek implementieren
    gp 18.16.3 Der Seifen-Server
  gp 18.17 Java-API für XML Messaging (JAXM)
  gp 18.18 Java Message Service (JMS)
    gp 18.18.1 OpenJMS
    gp 18.18.2 Beispiel mit Konsument und Produzent im Publish–Subscribe–Modell


Galileo Computing

18.5 Das entfernte Objekdowntop

Die Methoden des Servers werden letztendlich vom Client über die Stellvertreter genutzt. Der Server muss unterschiedliche Vorgaben erfüllen: Er muss eine spezielle Klasse erweitern, einen Konstruktor anbieten und die entfernte Schnittstelle implementieren. Dann kann ein Server-Objekt angemeldet werden. Das Server-Objekt implementiert daher die Geschäftslogik und sieht wie folgt aus:

Listing 18.2   AdderImpl.java


import java.rmi.*;
import java.rmi.server.*;

public class AdderImpl extends UnicastRemoteObject implements Adder
{
  public AdderImpl() throws RemoteException
  {
  }

  public int add( int x, int y ) throws RemoteException
  {
    return x + y;
  }
}

Da die Klasse eine Implementierung der Schnittstelle ist, geben wir ihr die Endung Impl. (Das ist eine bekannten Namensgebung aber keine Pflicht.)


Galileo Computing

18.5.1 Der Bauplan für entfernte Objekte  downtop

Zuerst fällt in der Implementierung auf, dass wir die Klasse UnicastRemoteObject erweitern. Sie liegt im Paket java.rmi.server und zeigt so die grobe Richtung für die Verwendung an.


public class AdderImpl extends UnicastRemoteObject implements Adder
{
   ...
}

Diese Klasse UnicastRemoteObject bietet Hilfe bei der Übertragung der Daten mittels Standard-TCP-Sockets an. Der Server kann so auf eingehende Anfragen reagieren und diese bearbeiten. Weiterhin zeigt UnicastRemoteObject an, dass ein Exemplar (nicht repliziert) unserer Klasse existieren soll.


Galileo Computing

18.5.2 Der Konstruktor  downtop

Für den Konstruktor eines entfernten Objekts gelten zwei Eigenschaften: Wir müssen einen Standard-Konstruktor anbieten, und dieser muss ebenso wie die Methoden RemoteException anzeigen.


public AdderImpl() throws RemoteException
{
}

Der Standard-Konstruktor ist notwendig, da eine Unterklasse genau diesen aufrufen möchte. Unser Konstruktor muss nichts machen. Er ruft aber automatisch den Konstruktor der Oberklasse auf, also den von UnicastRemoteObject. Wir haben schon beschrieben, dass UnicastRemoteObject bei der Übertragung hilft; wenn ein entferntes Objekt konstruiert wird, dann bindet er diesen Dienst an einen anonymen Port und horcht auf einkommende Aufrufe. Wollten wir einen speziellen Port nutzen, müssten wir im Konstruktor unserer Unterklasse einen parametrisierten Konstruktor von UnicastRemoteObject aufrufen, der einen Port annimmt.

Vererbung nicht möglich – was dann?

Es kann passieren, dass eine entfernte Klasse schon von einer anderen Klasse erbt und wir wegen der fehlenden Mehrfachvererbung ein Problem bekommen. Wenn wir uns dafür entscheiden, keine Objekte über UnicastRemoteObject anzubieten, aber eine existierende Klasse trotzdem Anbieter sein möchte, so muss das Objekt im Konstruktor ein entferntes Objekt, welches Remote implementiert, mit UnicastRemoteObject.exportObject(Remote) anmelden.


Beispiel   Der Server implementiert die Schnittstelle Adder und registriert sich selbst über exportObject() beim Namensdienst. (Was das ist, erfahren wir gleich etwas genauer.)

Listing 18.3   AdderImpl2.java

import java.rmi.*;
import java.rmi.server.*;
class AdderImpl2 implements Adder
{


  public AdderImpl2() throws RemoteException
  {
  }

  public int add( int x, int y ) throws RemoteException
  {
    return x + y;
  }

  public static void main( String args[] ) throws Exception
  {
    AdderImpl2 server = new AdderImpl2();
    UnicastRemoteObject.exportObject( server );
    Naming.rebind( "adder", server );
  }
}



class java.rmi.server.  UnicastRemoteObject  
extends RemoteServer

gp  static RemoteStub exportObject( Remote obj )
Exportiert das entfernte Objekt und macht es empfänglich für hereinkommende Aufrufe. Es wird ein willkürlicher Port verwendet.
gp  static Remote exportObject( Remote obj, int port )
Verhält sich wie exportObject(Remote), nur wird der angegebene Port und nicht der Standard-Port 1099 verwendet.

Hinweis   Die Erweiterung von UnicastRemoteObject ist nur eine Abkürzung für den Weg über exportObject(). Die Methode wird aber ohnehin genommen, wie der Ausschnitt aus dem Quellcode für den Konstruktor zeigt.

protected UnicastRemoteObject() throws RemoteException
{
  this( 0 );
}

protected UnicastRemoteObject(int port) throws RemoteException
{
  this.port = port;
  exportObject( (Remote)this, port );
}


Galileo Computing

18.5.3 Implementierung der entfernten Methoden  toptop

Im nächsten Schritt müssen die Methoden der Schnittstelle implementiert werden. Es steht frei, andere Methoden anzugeben, die nicht in der Schnittstelle vorgegeben sind, doch diese sind dann natürlich nicht nach außen sichtbar.


public int add( int x, int y ) throws RemoteException
{
  return x + y;
}

Die Argumente und Rückgabewerte können von jedem beliebigen Datentyp sein. Bei primitiven Datentypen werden spezielle read()- und write()-Folgen generiert. Objekte müssen die Schnittstelle Serializable implementieren (oder Remote sein). Dann werden die lokalen Objekte als Kopie übertragen. Über die Serialisierung werden alle nicht statischen und nicht transienten Attribute übermittelt. Ist das Argument wiederum instanceof Remote, dann wird dieser Verweis als einfache Referenz übergeben. In Wirklichkeit ist die Referenz ein Verweis auf den Stellvertreter.





Copyright © Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de