- Internetprogrammering 99/00 -

RMI: Callback i RMI

Nu skall vi visa hur man kan konstruera en klass på klientsidan, instansiera den, skicka en referens till denna instans till servern samt från servern skicka ett meddelande till instansen (dvs en metod som utförs hos klienten).

Gränssnittsbeskrivning

Vi konstruerar ett API med tre metoder som kan anropas av klienter på andra plattformar. För att objekten som implementerar detta interface skall vara anropbara från "främmande" JVM:s så utvidgar vi Remote och deklarerar att metoder som skall gå att anropa över nätet kan kasta RemoteException.
Observera att i första version av klient och server används endast metoden say(...) dom andra två används i en efterföljande enkel utvidgning.
import java.rmi.*;

interface HelloCallback extends Remote {
     public void value(Object o) throws java.rmi.RemoteException;
     public Object value() throws java.rmi.RemoteException;
     public void say(String saying) throws java.rmi.RemoteException;
}

Objekt med distribuerbar referens

Vi konstruerar ett objekt som implmenterar HelloCallback-gränssnittet. För att referenser snarare än hela objektet skall vara migrerbara implementerar vi ett Remote-interface (dvs HelloCallback) och subklassar UnicastRemoteObject.
import java.rmi.*;
import java.rmi.server.*;

public class MyRemoteObject extends UnicastRemoteObject implements HelloCallback{
 Object value;

 public MyRemoteObject()  throws java.rmi.RemoteException {
  super();
 }

 public void value(Object v) throws java.rmi.RemoteException{
  value = v;
 }

 public Object value() throws java.rmi.RemoteException{
  return value;
 }

 public void say(String saying) throws java.rmi.RemoteException{
  System.out.println("From the client in MyRemoteObject: " + saying);
 }
}

Servern

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

public class HelloServerWithCallback extends UnicastRemoteObject implements HelloWithCallback {
 public HelloServerWithCallback() throws RemoteException
 {
  super();
 }

 public void sayHelloVia(HelloCallback callbackObject) throws RemoteException {

  callbackObject.say("Hello Internetprogrammers (via callback)!");
 }

 public static void main(String [] args) {
  // System.setSecurityManager(new RMISecurityManager());
  try {
   HelloServerWithCallback h = new HelloServerWithCallback();
   Naming.rebind("hellowithcallback", h);
   System.out.println("Hello with Callback Server ready.");
  }
  catch(RemoteException re) {
   System.out.println("RemoteException in HelloImpl.main: " + re);
  }
  catch(Exception e) {
   System.out.println("Exception in HelloImpl.main: " + e);
  }
 }
}

Klienten

import java.rmi.*;
import java.io.*;

public class HelloClientWithCallback {
 public static void main(String [] args) {
  System.out.println("Client started");
  // System.setSecurityManager(new RMISecurityManager());
  try {
   HelloWithCallback h =
                (HelloWithCallback) Naming.lookup("hellowithcallback");

   MyRemoteObject remote = new MyRemoteObject();
   h.sayHelloVia(remote);
  }
  catch(Exception e) {
   System.out.println("Exception in HelloWithCallback.main: " + e);
  }
 }
}

Kompilera och kör

Kompilera

  1. Kompilera båda interfacen, servern och klienten med javac, dvs

  2. >javac HelloCallback.java
    >javac MyRemoteObject.java
    >javac HelloServerWithCallback.java
    >javac HelloClientWithCallback.java
  3. Kör också rmic på objektet som skall distribueras och på servern, dvs

  4. >rmic MyRemoteObject
    >rmic HelloServerTransport

Kör

  1. Starta namnserver

  2. >rmiregistry
  3. Starta server

  4. >java HelloServerWithCallback
  5. Starta klient

  6. >java HelloClientWithCallback

Utvidgning av server och klient

I ovanstående exempel unyttjar vi bara metoden say(...) i det distibuerade objektet (MyRemoteObject). Men vi kan enkelt även lagra data (instansvaribalen value) och uppdatera detta värde via metoderna value() och value(...). En uppdatering av (dvs meddelandesändning till) det distribuerade objektet kan göras både på klient och server.
För att illusterra meddelandesändning och ändring av lagrat värde utvigar vi klient och server. För att lättare se vad som händer ändrar vi lite i metoden say(...) också, så att den skriver ut aktuellt värde på klientens terminal varje gång den anropas.
Ändringarna i förhållande till ovanstående exempel är få. För att dom skall bli extra tydliga så är dom markerade med fetstil.

MyRemoteObject-version 2

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

public class MyRemoteObject extends UnicastRemoteObject implements HelloCallback{
 Object value;
 public MyRemoteObject()  throws java.rmi.RemoteException {
  super();
 }

 public void value(Object v) throws java.rmi.RemoteException{
  value = v;
 }

 public Object value() throws java.rmi.RemoteException{
  return value;
 }

 public void say(String saying) throws java.rmi.RemoteException{
  System.out.println("From the client in MyRemoteObject: " + saying);
  System.out.println("My value is: " + this.value());
 }
}

Server-version 2

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

public class HelloServerWithCallback extends UnicastRemoteObject implements HelloWithCallback {
 public HelloServerWithCallback() throws RemoteException
 {
  super();
 }

 public void sayHelloVia(HelloCallback callbackObject) throws RemoteException {
  System.out.println("The callbacks value: " + callbackObject.value());
  callbackObject.value("The server was here!");
  callbackObject.say("Hello Internetprogrammers (via callback)!");
 }

 public static void main(String [] args) {
  // System.setSecurityManager(new RMISecurityManager());
  try {
   HelloServerWithCallback h = new HelloServerWithCallback();
   Naming.rebind("hellowithcallback", h);
   System.out.println("Hello with Callback Server ready.");
  }
  catch(RemoteException re) {
   System.out.println("RemoteException in HelloImpl.main: " + re);
  }
  catch(Exception e) {
   System.out.println("Exception in HelloImpl.main: " + e);
  }
 }
}

Klient-version 2

import java.rmi.*;
import java.io.*;

public class HelloClientWithCallback {

 public static void main(String [] args) {
  System.out.println("Client started");
  // System.setSecurityManager(new RMISecurityManager());
  try {
   HelloWithCallback h = (HelloWithCallback) Naming.lookup("hellowithcallback");

   MyRemoteObject  remote = new MyRemoteObject();
   remote.value(new java.util.Date());
   h.sayHelloVia(remote);
  }
  catch(Exception e) {
   System.out.println("Exception in HelloWithCallback.main: " + e);
  }
 }
}

Kompilera om och kör

Kompilera om klasserna och kör rmicMyRemoteObject och HelloServerWithCallback.
Starta server och klient.

^ Upp till kursens hemsida.


Sidansvarig: <bjorne@nada.kth.se>
Senast ändrad 21 oktober 1999