Lab

1

Middleware Platforms

CORBA Stock Quoter Service


Systems Architecture Group

Ablieferungstermin und erreichbare Punktzahl für diese Aufgabe, sowie Voraussetzungen für die Prüfungszulassung entnehmen Sie bitte http://sar.informatik.hu-berlin.de.

Aufgabe 1 – CORBA Stock Quoter Service

Zur Einführung soll eine einfache Börsenanwendung mit Hilfe von CORBA realisiert werden. Die Anwendung gliedert sich in einen Server, der Informationen zu Aktien und deren Kursen bereitstellt, und einen Klienten, der diese Informationen abfragt.

Teil A - Server

Der Server soll folgende Funktionalitäten bereitstellen:

  • Erzeugen eines CORBA Objekts, das die Schnittstelle Quoter_Factory besitzt, und Ablegen der zugehörigen IOR im Dateisystem (Datei quoter_factory.ior).
  • Mittels der Factory lassen sich unter Angabe eines Namens (z.B. "Dow Jones", "Reuters", …) neue Quoter Objekte erzeugen (Methode create_quoter).
  • Ein Quoter besitzt einen Namen (Attribut quoter_name) und liefert den aktuellen Kurs einer Aktie unter Angabe deren Namens (Methode get_quote).
  • Das von der Factory erzeugte Objekt unterstützt zusätzlich die Schnittstelle StockQuoter, die genauere Informationen zu einer Aktie in Form eines StockInfo Objekts liefert.

Verwenden Sie bitte folgende Schnittstellendefinitionen.

module stocks

{

  struct StockInfo {

    string name;

    string symbol;

    string ISIN;

    enum StockType {

      common_stock,

      preferred_stock,

      tresury_stock

    } type;

    struct StockQuote {

      long high;

      long low;

      long last;

    } quote;

  };

 

  exception InvalidStock {};

  exception InvalidQuoter {};

 

  interface Quoter {

    readonly attribute string quoter_name;

    long get_quote (in string stock_name)

      raises (InvalidStock);

  };

 

      interface StockQuoter : Quoter {

    StockInfo get_stock_info (in string stock_name)

      raises (InvalidStock);

      };

 

  interface QuoterFactory {

    Quoter create_quoter (in string name)

      raises (InvalidQuoter);

  };

};

Implementationssprache für den Server ist C++ unter Verwendung von MICO CORBA (http://www.mico.org, Installation siehe unten). Zur Vereinfachung liefern alle Quoter gleiche Daten, die fest programmiert sein können. Dabei sollen mindestens die folgenden Sätze abfragbar sein:

Name

Symbol

ISIN

Stock Type

High

Low

Last

3MMMMUS88579Y1010CS756971
BoeingBAUS0970231058CS686467
Hewlett-PackardHPQUS4282361033PS313131
IntelINTCUS4581401001TS292727

 Teil B – Client

Der Klient ist eine Konsolenanwendung, die dem Nutzer eine einfache Kommandozeile bietet. Er soll in der Sprache Java mit Hilfe des integrierten Java ORB realisiert werden.

Der Klient besteht konzeptuell aus 2 Teilen: einem "Bibliotheksteil" und der Nutzerschnittstelle. Der Bibliotheksteil implementiert die nachfolgende Java-Schnittstelle und interagiert mit dem Server über die in IDL definierte Schnittstelle. Die Aufgabe des Bibliotheksteils ist das Transformieren der eingehenden Aufrufe (auf der unten stehenden Java-Schnittstelle) in Aufrufe an den Server (über die IDL-Schnittstelle).

Die Nutzerschnittstelle stellt dem Benutzer eine Kommandozeile zur Verfügung und interagiert mit dem Bibliotheksteil über die nachfolgende Java-Schnittstelle. Bitte definieren Sie die Kommandosprache selbst. Die Implementierungsklasse für das Interface ClientQuoterFactory soll den Namen ClientQuoterFactoryImpl tragen und das ORB-Objekt als einzigen Parameter für den Konstruktor verwenden (siehe dazu die Methode setUp der Unittest-Klasse).

Diese Zweiteilung des Klienten ist nicht CORBA-typisch. Sie ist nötig, um sowohl Klient als auch Server mit einem Unittest unter Java testen zu können (siehe dazu die unten aufgeführte Testklasse und die Variablen _serverFactory und _clientFactory).

package stocks.client;

 

public class InvalidStockException extends Exception {}

public class InvalidQuoterException extends Exception {}

 

public interface ClientStock {

      public static final int common_stock = 0;

      public static final int preferred_stock = 1;

      public static final int tresury_stock = 2;

 

      String getName();

      String getSymbol();

      String getISIN();

      int getStockType();

      long getHigh();

      long getLow();

      long getLast();

}

 

public interface ClientStockQuoter {

        String getQuoterName();

       

        ClientStock getStock ( String stock_name)

          throws InvalidStockException;

}

 

public interface ClientQuoterFactory {

      ClientStockQuoter create_quoter (String name)

            throws InvalidQuoterException;

}

Abgabe und Bewertung

Begründen Sie die von Ihnen getroffenen Design-Entscheidungen und beschreiben Sie aufgetretene Besonderheiten und Probleme. Benutzen Sie dafür eine HTML Datei mit dem Namen index.html. Abzugeben sind weiterhin die Quelltexte der Lösung und ein Ant Skript mit dem Namen build.xml, das die Quellen mit den gängigen Werkzeugen automatisiert übersetzt (Bitte die Targets compile, test und clean definieren. Der Server wird jeweils separat von Hand gestartet.).

Der Server soll mit einem Shell-Script build.bat/build.sh übersetzt werden. Sie können davon ausgehen, dass die Umgebungsvariable MICO_HOME auf das Installtionsverzeichnis des MICO ORB gesetzt ist, dass das Verzeichnis MICO_HOME/bin im Suchpfad PATH und MICO_HOME/lib im Bibliothekspfad LD_LIBRARY_PATH ist und dass make/nmake verfügbar ist. Bitte schreiben sie ein weiteres Script server.sh/server.bat, dass den Server startet.Bitte reichen Sie die geforderten Dateien in ein ZIP Archiv gepackt ein.

Für Test und Bewertung kommt die Unit-Test-Bibliothek jUnit (www.junit.org) zum Einsatz. Die geforderte Funktionalität wird anhand von 10 Unit-Tests überprüft, von denen Ihnen vorab die folgenden 5 zur Verfügung stehen.

package stocks.test;

import java.io.BufferedReader;

import java.io.DataInputStream;

import java.io.FileInputStream;

import java.io.InputStreamReader;

import org.omg.CORBA.ORB;

 

import stocks.*;

import stocks.StockInfoPackage.StockType;

import stocks.client.*;

import junit.framework.TestCase;

 

 

public class StockQuoterTest extends TestCase {

      QuoterFactory _serverFactory = null;

      ClientQuoterFactory _clientFactory = null;

  ORB _orb = null;

 

  public static void main(String[] args) {

    junit.textui.TestRunner.run(StockQuoterTest.class);

  }

 

  public StockQuoterTest(String name) {

    super(name);

  }

 

  protected void setUp() throws Exception {

    super.setUp();

 

    String[] args = null;

    _orb = ORB.init(args,null);

   

    _clientFactory = new ClientQuoterFactoryImpl(_orb);

 

    String filename = "quoter_factory.ior";

    FileInputStream fis = new FileInputStream(filename);

    BufferedReader d = new BufferedReader(new InputStreamReader(fis));

    String ior = d.readLine();

   

    org.omg.CORBA.Object obj = _orb.string_to_object(ior);

    _serverFactory = QuoterFactoryHelper.narrow(obj);

  }

 

  protected void tearDown() throws Exception {

    super.tearDown();

   

    _clientFactory = null;

    _serverFactory = null;

    _orb = null;

  }

 

  public void test1() throws Exception {

    String name = "Dow Jones";

    Quoter dowjones = _serverFactory.create_quoter(name);

    assertEquals( name, dowjones.quoter_name() );

   

    int iQuote = dowjones.get_quote("Boeing");

    assertEquals( 67, iQuote );

  }

 

  public void test2() throws Exception {

    Quoter obj = _serverFactory.create_quoter("Dow Jones");

    StockQuoter dowjones = StockQuoterHelper.narrow(obj);

  }

 

  public void test3() throws Exception {

    Quoter obj = _serverFactory.create_quoter("Dow Jones");

    StockQuoter dowjones = StockQuoterHelper.narrow(obj);

   

    String name = "Intel";

    StockInfo intel = dowjones.get_stock_info(name);

    assertEquals( name, intel.name );

    assertEquals( "INTC", intel.symbol );

    assertEquals( "US4581401001", intel.ISIN );

    assertEquals( StockType._tresury_stock, intel.type.value() );

    assertEquals( 29, intel.quote.high );

    assertEquals( 27, intel.quote.low );

    assertEquals( 27, intel.quote.last );

  }

 

  public void test6() throws Exception {

    String name = "Dow Jones";

    ClientStockQuoter dowjones = _clientFactory.create_quoter(name);

    assertEquals( name, dowjones.getQuoterName() );

   

    ClientStock boeing = dowjones.getStock("Boeing");

    assertEquals( 67, boeing.getLast() );

  }

 

  public void test7() throws Exception {

    ClientStockQuoter dowjones = _clientFactory.create_quoter("Dow Jones");

 

    String name = "Intel";

    ClientStock intel = dowjones.getStock(name);

    assertEquals( name, intel.getName() );

    assertEquals( "INTC", intel.getSymbol() );

    assertEquals( "US4581401001", intel.getISIN() );

    assertEquals( ClientStock.tresury_stock, intel.getStockType() );

    assertEquals( 29, intel.getHigh() );

    assertEquals( 27, intel.getLow() );

    assertEquals( 27, intel.getLast() );

  }

}

Hinweise

Behandeln Sie auch Fehler- und Ausnahmesituationen entsprechend. Bedenken Sie, dass unter umständen auch mehrere Clients gleichzeitig auf den Server zugreifen können.

Da die IDL-Schnittstelle fest vorgegeben ist, können Sie Ihre Server bzw. Klienten auch mit denen anderer Praktikumsgruppen betreiben. Für die CORBA IDL existieren weitere Sprachabbildungen, beispielsweise für Python, Pascal, TCL, Perl, C, Ada, etc. (siehe http://en.wikipedia.org/wiki/Corba). Interessierte Praktikumsgruppen können zusätzlich Klienten oder Server in diesen Sprachen realisieren.

Benötigte Software

Java SDK 1.4 oder höher (Ist im Berlin-Pool installiert). Der IDL-Compiler für die Übersetzung nach Java heißt idlj.

MICO CORBA

MICO lässt sich mit GCC/Linux oder unter Windows mit GCC/Cygwin oder dem MS Visual C++ Compiler übersetzen.
Installation unter Linux:

  1. Quellen herunterladen (http://www.mico.org/mico-2.3.11.tar.gz)

  2. Auspacken: tar -xzf mico-2.3.11.tar.gz, in das erzeugte Verzeichnis wechseln

  3. Konfigurieren: ./configure --prefix=MICO_HOME --disable-coss --disable-shared --enable-minimum-corba --enable-thread --enable-pthreads
    Dabei ist MICO_HOME mit dem Pfad zu ersetzen, in dem MICO installiert werden soll!

  4. Übersetzen: make

  5. Installieren: make install
    Als letzte Meldung auf der Kommandozeile erhält man dabei den Fehler, dass ldconfig nicht auf /etc/ld.so.cache~ zugreifen kann. Dieser Fehler kann ignoriert werden.

  6. Ggf. Pfade anpassen (siehe dazu MICO_HOME/lib/mico-setup.sh)

Nach erfolgreicher Installation sind in MICO_HOME/bin Wrapper-Scripe für die Aufrufe von Compiler, Linker & Co. zu finden. Diese Scripte haben den Prefix "mico-", beispielsweise mico-c++ für den C++-Compiler. Für die Übersetzung sollten möglichst diese Scripte verwendet werden, da sie die benötigten Pfade, Bibliotheken usw. an die zugrunde liegenden Werkzeuge weitergeben.

Literatur

Michi Henning, Steve Vinoski: "Advanced CORBA(R) Programming with C++" [amazon]

Lösung

Eine mögliche Lösung ist hier zu finden.


Legal disclaimer. .  © 2024 Humboldt-Universität zu Berlin, Computer Science Department, Systems Architecture Group.Contact: sar@informatik.hu-berlin.de .