- Internetprogrammering 99/00 -

CORBA: Kylanläggning

Baserat på callbacks som i föregående exempel konstruerar vi en enkel kylanläggning. Servern är tänkt att motsvara en termometer. En klient kan ansluta och registrera ett objekt som skall anropas om temperaturen förändras.
I första versionen kan servern endast hantera en klient i taget. I version 2 kan servern hantera flera samtidiga klienter.

UML-diagram

Enhelt UML-diagram

IDL-Beskrivning

module Cooler  {

 // Följande gränssnitt implementeras av en klient som vill bli meddelat då förändringar i kylanläggningen sker.
 interface CoolerMonitorInterface {
  // Om temperaturen i kylanläggningen ändras skall denna metod anropas.
  void coolerChanged (in long anObject);
 };

 interface CoolerInterface {
  // Mha följande metod kan klienter ansätta call-back-interface-objekt.
  void monitor (in CoolerMonitorInterface anObject);

  // Metod för att avläsa aktuell temperatur.
  long getTemperature ();

  // Metod för att ändra temperatur.
  void setTemperature (in long aNumber);
 };
};

Server version 1

import Cooler.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

class CoolerServant extends _CoolerInterfaceImplBase {
 protected int temp = 0;
 Cooler.CoolerMonitorInterface monitor = null;

 public void monitor(Cooler.CoolerMonitorInterface aMonitor){
  monitor = aMonitor;
 }

 public int getTemperature() {
  return temp;
 }

 public void setTemperature(int newTemp){
  temp = newTemp;
  monitor.coolerChanged(temp);
 }
}

public class CoolerServer {

    public static void main(String args[])
    {
 try{
     // skapa och initiera ORB
     ORB orb = ORB.init(args, null);

     // skapa serverobjekt och registrera det i ORBen
     CoolerServant callbackRef = new CoolerServant();
     orb.connect(callbackRef);

     // skapa referens till namnserver
     org.omg.CORBA.Object objRef =
  orb.resolve_initial_references("NameService");
     NamingContext ncRef = NamingContextHelper.narrow(objRef);

     // bind objektet till namnet "monogamousCooler"
     NameComponent nc = new NameComponent("monogamousCooler", "");
     NameComponent path[] = {nc};
     ncRef.rebind(path, callbackRef);

     // vänta på klienter
     java.lang.Object sync = new java.lang.Object();
     synchronized (sync) {
        sync.wait();
     }

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

Klient version 1

import Cooler.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;

class CallbackMonitor extends _CoolerMonitorInterfaceImplBase {
 public void coolerChanged(int newTemp) {
  System.out.println("Temp ändrad: " + newTemp);
 }
}

public class CoolerClient {

 public static void main(String args[])
 {
 try{
  // skapa och initiera ORB
  ORB orb = ORB.init(args, null);

  // skapa referens till namnserver
  org.omg.CORBA.Object objRef =
  orb.resolve_initial_references("NameService");
  NamingContext ncRef = NamingContextHelper.narrow(objRef);

  // bind objektet till namnet "monogamousCooler"
  NameComponent coolerName = new NameComponent("monogamousCooler", "");
  NameComponent path[] = {coolerName};

  CoolerInterface cooler =
       CoolerInterfaceHelper.narrow(ncRef.resolve(path));

  // skapa och registrera callbackobjekt
  CallbackMonitor monitor = new CallbackMonitor();
  orb.connect(monitor);

  cooler.monitor(monitor);

  System.out.println("Temp: " + cooler.getTemperature());
  for(int i = 10; i < 100; i = i + 24) cooler.setTemperature(i);
 } catch (Exception e) {
  System.err.println("ERROR: " + e);
  e.printStackTrace(System.out);
 }
}}

Klient version 2

Vi lägger till enkel interaktion.
import Cooler.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import java.io.*;

class CallbackMonitor extends _CoolerMonitorInterfaceImplBase {
 public void coolerChanged(int newTemp) {
  System.out.println("Temp ändrad: " + newTemp);
 }
}

public class CoolerClientVersionB {

 public static void main(String args[])
 {
 try{
  // skapa och initiera ORB
  ORB orb = ORB.init(args, null);

  // skapa referens till namnserver
  org.omg.CORBA.Object objRef =
  orb.resolve_initial_references("NameService");
  NamingContext ncRef = NamingContextHelper.narrow(objRef);

  // bind objektet till namnet "monogamousCooler"
  NameComponent coolerName = new NameComponent("monogamousCooler", "");
  NameComponent path[] = {coolerName};

  CoolerInterface cooler = CoolerInterfaceHelper.narrow(ncRef.resolve(path));

  // skapa och registrera callbackobjekt
  CallbackMonitor monitor = new CallbackMonitor();
  orb.connect(monitor);

  cooler.monitor(monitor);

  System.out.println("Temp: " + cooler.getTemperature());
  BufferedReader in = new BufferedReader(new
                                        InputStreamReader(System.in));
  for(;;) {
   System.out.print(">");
   String line = in.readLine();
   if((line == null) || line.equalsIgnoreCase("quit")) break;
   try {
    int temp = Integer.parseInt(line);
    cooler.setTemperature(temp);
   }
   catch(Exception e) {System.out.println("Felaktig inmatning (ge tal)");}
  }

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

Server version 2

Vi lägger till möjligheten för servern att hantera flera samtidiga klienter. Vi använder en instans av Vector för att hantera mängden av monitorer som skall meddelas vid förändring av temperaturen.
import Cooler.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import java.util.*;

class CoolerServant extends _CoolerInterfaceImplBase {
 protected int temp = 0;
 Vector monitors = new Vector();

 public void monitor(Cooler.CoolerMonitorInterface aMonitor){
  monitors.add(aMonitor);
 }

 public int getTemperature() {
  return temp;
 }

 public void setTemperature(int newTemp){
  temp = newTemp;
  for(Enumeration e = monitors.elements(); e.hasMoreElements(); )
   ((Cooler.CoolerMonitorInterface) e.nextElement()).coolerChanged(temp);
 }
}

public class CoolerServerWithMultipleMonitors {

    public static void main(String args[])
    {
 try{
     // skapa och initiera ORB
     ORB orb = ORB.init(args, null);

     // skapa serverobjekt och registrera det i ORBen
     CoolerServant callbackRef = new CoolerServant();
     orb.connect(callbackRef);

     // skapa referens till namnserver
     org.omg.CORBA.Object objRef =
  orb.resolve_initial_references("NameService");
     NamingContext ncRef = NamingContextHelper.narrow(objRef);

     // bind objektet till namnet "promiscuousCooler"
     NameComponent nc = new NameComponent("promiscuousCooler", "");
     NameComponent path[] = {nc};
     ncRef.rebind(path, callbackRef);

     // vänta på klienter
     java.lang.Object sync = new java.lang.Object();
     synchronized (sync) {
        sync.wait();
     }

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

Klient version 3

Vi behöver enbart göra om klienten så att den använder den senast konstruerade serverns namn på "kylanläggningen".
import Cooler.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import java.io.*;

class CallbackMonitor extends _CoolerMonitorInterfaceImplBase {
 public void coolerChanged(int newTemp) {
  System.out.println("Temp ändrad: " + newTemp);
 }
}

public class CoolerClientVersionC {

 public static void main(String args[])
 {
 try{
  // skapa och initiera ORB
  ORB orb = ORB.init(args, null);

  // skapa referens till namnserver
  org.omg.CORBA.Object objRef =
  orb.resolve_initial_references("NameService");
  NamingContext ncRef = NamingContextHelper.narrow(objRef);

  // bind objektet till namnet "promiscuousCooler"
  NameComponent coolerName = new NameComponent("promiscuousCooler", "");
  NameComponent path[] = {coolerName};

  CoolerInterface cooler =
    CoolerInterfaceHelper.narrow(ncRef.resolve(path));

  // skapa och registrera callbackobjekt
  CallbackMonitor monitor = new CallbackMonitor();
  orb.connect(monitor);

  cooler.monitor(monitor);

  System.out.println("Temp: " + cooler.getTemperature());
  BufferedReader in = new BufferedReader(new
                                           InputStreamReader(System.in));
  for(;;) {
   System.out.print(">");
   String line = in.readLine();
   if((line == null) || line.equalsIgnoreCase("quit")) break;
   try {
    int temp = Integer.parseInt(line);
    cooler.setTemperature(temp);
   }
   catch(Exception e) {System.out.println("Felaktig inmatning (ge tal)");}
  }

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


^ Upp till kursens hemsida.


Sidansvarig: <bjorne@nada.kth.se>
Senast ändrad 2 november 1999