Java Corba
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
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 -fserver MyInterface.IDL
Oder beides gleichzeitig:
Jetzt implementiert man die Methoden aus der IDL und füllt sie mit dem gewünschten Verhalten:
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
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)
Und dann kann man die MyCorbaServerClass Klasse schon starten.
Jetzt noch eine Client Klasse
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: