19.2.1 | Parameter und Rückgabewerte |
Generell gelten bei RMI für die Übergabe von Werten folgende Regeln:In beiden Fällen spielt es keine Rolle, ob es sich um Rückgabewerte von Methoden oder um Aufrufparameter handelt.
- Alle Exemplare, die Serializable implementieren, werden als Wert übertragen.
- Alle Exemplare, die UnicastRemoteObject implementieren, werden per Referenz übertragen.
Die Übergabe per Wert ist relativ unkompliziert. Prinzipiell können in RMI-Methoden alle Klassen als Parameter und auch als Rückgabewert benutzt werden, vorausgesetzt, sie sind serialisierbar. Die Serialisierbarkeit von Objekten wird in Java dadurch festgelegt, dass die Klassen das Interface java.io.Serializable implementieren. Viele Klassen, die Bestandteil der Java-Standard-Bibliotheken sind, implementieren dieses Interface bereits. Bei Serializable handelt es sich lediglich um ein Flag-Interface, das keine eigenen Methoden definiert. Das heißt, eine Klasse, die das Interface implemtentiert, muss keine bestimmten Methoden bereitstellen, sondern bekommt die Eigenschaft der Serialisierbarkeit bereits durch die Angabe in der implements-Klausel verliehen.
Wenn man bei einer Personalverwaltung z. B. pro Methoden-Aufruf die Basisdaten einer Person übertragen möchte, dann wäre es denkbar, zu diesem Zweck die Klasse Person zu definieren:import java.io.Serializable; public class Person implements Serializable { String name; String vorname; ... }Diese Klasse kann anschließend als Parameter oder Rückgabewert einer Methode eines Server-Objektes verwendet werden, wie folgende Definition einer Server-Schnittstelle zeigt:import java.rmi.Remote; import java.rmi.RemoteException; public interface StaffServer implements Remote { public Person getPerson(String id) throws RemoteException; public void storePerson(Person p) throws RemoteException; }Die Methode getPerson() hat die Aufgabe, eine Person mit einer bestimmten ID als Ergebnis vom Server zurückzuliefern. Die Methode storePerson() erwartet als Parameter ein Person-Exemplar, das auf den Server übertragen und dort gespeichert wird.
Bei der Übergabe von komplexen Objekten ist zu beachten, dass die Serialisierung rekursiv wirkt. Das heißt, wenn ein Objekt als Wert übertragen werden soll, muss nicht nur das Objekt selbst serialisierbar sein, sondern auch dessen Attribute. Als Alternative kann man ein Attribut als transient deklarieren. transient-Attribute werden bei der Übergabe als Wert nicht erfasst und werden auf dem Zielrechner mit einem neuen Default-Wert initialisiert (in der Regel null).
Objekte können nur dann als Referenz übergeben werden, wenn es sich dabei selbst um Server-Objekte handelt. Statt dem Wert wird hierbei lediglich das Proxy-Objekt (der Stub) übergeben, der alle Informationen darüber enthält, wie das Server-Objekt kontaktiert wird. Für Server-Objekte gilt wiederum:Wenn diese beiden Punkte zutreffen, ist eine Übergabe als Referenz möglich.
- Sie müssen das Interface java.rmi.Remote implementieren bzw. ein Interface, das davon abgeleitet ist.
- Sie müssen von der Klasse UnicastRemoteObject abgeleitet sein.
Je nachdem, ob eine Referenz-Übergabe bei RMI als Rückgabewert oder als Parameter erfolgt, unterscheidet man zwei Anwendungsfälle:
- Ein RMI-Server gibt ein Objekt in der Regel dann als Referenz zurück, wenn der Client ein Objekt benötigt, das auf Serverseite den Sitzungsstatus speichert, wie z. B. die Kaufhaus-Anwendung in Abschnitt 19.2.2. Jeder Client bekommt somit sein eigenes Client-Objekt zugewiesen.
- Ein Client gibt in der Regel dann ein Objekt per Referenz an ein RMI-Server-Objekt, wenn das Server-Objekt asynchrone Meldungen an den Client zurückgeben soll (Callback). Dieses Prinzip wird z. B. bei dem Chat-Server in Abschnitt 19.2.3 benutzt. Ein Chat-Client kann selbst Nachrichten an den Chat-Server schicken, sollte aber auch über das Eintreffen von Nachrichten von anderen Rechnern informiert werden, ohne dass der Client selbst beim Server anfragt, ob neue Nachrichten verfügbar sind.