Common Object Request Broker Architecture (CORBA)

Wikipedia: Common Object Request Broker Architecture (CORBA)

Standard zur Programmiersprachen übergreifende Kommunikation, wird von der Object Management Group (OMG) verwaltet.

Die Kommunikationschnittstellen werden über die Interface Definition Language (IDL) definiert. Syntax IDL:

Kleines CORBA Beispiel / CORBA Tutorial Siehe auch

Man erzeugt als erstes eine IDL Datei, z.B. in eine Datei MyInterface.IDL

// package de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent
module de
{
module tgunkel
{
  module JAVA
  {
   module CorbaDemo
   {
    module CorbaGeneratedContent
    {
     interface MyCorbaInterface
     {
       // Method which returns a String which says hello to your name
      string  sayHelloTo(in string name);

      // Method which returns the sum of two numbers
      long    calculateAdd(in long number1, in long number2);

      /*
       * interface to store and retrieve strings
       *
       */


      // Our own exception with two attributes
      exception NoMoreSpaceLeftError
      {
       unsigned long position;
       string        notStoredString;
      };

      // constant to define how many values we are allowed to store
      const long MAX_ITEMS_TO_BE_STORED = 9;

      // our own type to have sequence of Strings
      typedef sequence<string> MyStringArrayType;

      // store a new string, may throw an exception
      void    storeString(in string text) raises (NoMoreSpaceLeftError);

      // get all stored values
      MyStringArrayType restoreStrings();

     };
    };
   };
  };
};
};

Aus dieser kann man jetzt z.B. mit idlj (Bestandteil des Java JDK) Java Code erzeugen:

idlj -fclient MyInterface.IDL
idlj -fserver MyInterface.IDL

Oder beides gleichzeitig:

idlj -fall MyInterface.IDL

Jetzt implementiert man die Methoden aus der IDL und füllt sie mit dem gewünschten Verhalten:

package de.tgunkel.JAVA.CorbaDemo.Server;
import java.util.ArrayList;
import java.util.List;
import de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent.MyCorbaInterface;
import de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent.MyCorbaInterfacePOA;
import de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent.MyCorbaInterfacePackage.NoMoreSpaceLeftError;
public class MyCorbaInterfaceImpl extends MyCorbaInterfacePOA
{
    private List<String> memory;

    public MyCorbaInterfaceImpl()
    {
        memory=new ArrayList<String>();
    }

    @Override
    public String sayHelloTo(String name)
    {
        return "Hello World dear '"+name+"'.";
    }
    @Override
    public int calculateAdd(int number1, int number2)
    {
        return number1+number2;
    }
    @Override
    public String[] restoreStrings()
    {
        String []strArray = new String[memory.size()];
        memory.toArray(strArray);
        return strArray;
    }
    @Override
    public void storeString(String text) throws NoMoreSpaceLeftError
    {
        int newPosition=memory.size()+1;
        if(newPosition>=MyCorbaInterface.MAX_ITEMS_TO_BE_STORED)
        {
            throw new NoMoreSpaceLeftError(newPosition, text);
        }
        memory.add(text);
    }
}

Man braucht eine Klasse, die die Server Seite repräsentiert

package de.tgunkel.JAVA.CorbaDemo.Server;
import org.omg.CORBA.*;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
import de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent.MyCorbaInterface;
import de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent.MyCorbaInterfaceHelper;
public class MyCorbaServerClass
{
    public static String CORBA_PROJECT_NAME="HelloWorld";

    public static void main(String[] args) throws InvalidName, AdapterInactive
    {
        try
        {
            // init ORB, pass arguments from the command line (if there are any)
            ORB orb = ORB.init(args, null);
            // this is the class which implements the methods defined in the IDL
            MyCorbaInterfaceImpl myCorbaInterfaceImplRef = new MyCorbaInterfaceImpl();
            // get the root PAO of the CORBA server
            POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
            rootpoa.the_POAManager().activate();
            // Registriere Servant und erzeuge (CORBA) Objektreferenz
            org.omg.CORBA.Object ref = rootpoa.servant_to_reference(myCorbaInterfaceImplRef);
            // convert it into Java objects
            MyCorbaInterface href = MyCorbaInterfaceHelper.narrow(ref);
            // register at CORBA nameservice
            org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
            NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
            NameComponent path[] = ncRef.to_name(CORBA_PROJECT_NAME);
            ncRef.rebind(path, href);
            // start orb
            System.out.println("Server is now running...");
            orb.run();

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

Jetzt startet man als erstes ordb (auch Bestandteil des JDK)

orbd -ORBInitialPort 900

Und dann kann man die MyCorbaServerClass Klasse schon starten.

Jetzt noch eine Client Klasse

package de.tgunkel.JAVA.CorbaDemo.Client;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent.MyCorbaInterface;
import de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent.MyCorbaInterfaceHelper;
import de.tgunkel.JAVA.CorbaDemo.CorbaGeneratedContent.MyCorbaInterfacePackage.NoMoreSpaceLeftError;
public class MyCorbaClientClass
{
    public static String CORBA_PROJECT_NAME="HelloWorld";
    public static void main(String[] args)
    {
        try
        {
            // init ORB
            ORB orb = ORB.init(args, null);
            // get the Java object via the CORBA nameservice
            org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
            NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
            NameComponent path[] = ncRef.to_name(CORBA_PROJECT_NAME);
            MyCorbaInterface helloRef = MyCorbaInterfaceHelper.narrow(ncRef.resolve(path));
            /*
             * Play with it, call the remote CORBA methods:
             */

            // let the CORBA server say hello to John
            System.out.println(helloRef.sayHelloTo("John"));
            // let the CORBA server calculate
            System.out.println(helloRef.calculateAdd(42, 8));        
            // store some strings in the CORBA server
            try
            {
                helloRef.storeString("First string");
                helloRef.storeString("Another string");
                String[] restoredStrings=helloRef.restoreStrings();
                for(String s : restoredStrings)
                {
                    System.out.println("Restored: "+s);
                }
            }
            catch(NoMoreSpaceLeftError e)
            {
                System.err.println("Failed to store string '"+e.notStoredString+"' at position '"+e.position+"'");            
            }
        } catch(Exception e)
        {
            System.out.println("ERROR : " + e);
            e.printStackTrace(System.out);
        }
    }
}

Nachdem man über Corba eine Methode aufgerufen hat, ist die Frage, ob man überhaupt warten muss, bis die Methode von der Gegenseite abgearbeitet wurde. Sofern die Methode einen Rückgabewert liefert, muss der Aufrufer natürlich warten. Ansonsten läuft nach meiner Beobachtung der Aufrufer auch einfach so weiter. Laut Dokumentation ist dafür aber eigentlich das oneway Schlüsselwort notwendig:

oneway void foo()