Building a CORBA Application – Part 2
Contd… from Part 1
Implementing the Server Interfaces
· The IDL compiler generates a number of files; for each IDL interface, the compiler will generate a source file and header file for the client stub and a source file and header file for the server skeleton, resulting in four files per interface. (This is for an IDL compiler targeting C++; an IDL compiler targeting Java will not generate header files.)
· Additionally, the IDL compiler can create separate directories for IDL modules; it can also create additional files for helper classes. Also, most IDL compilers allow to specify the suffix to use for client stubs and server skeletons. For example, the client stub files can be named StockMarket_c.h and StockMarket_c.cpp, or StockMarket_st.h and StockMarket_st.cpp.
Using Server Skeletons
· The server skeleton provides a framework upon which to build the server implementation.
· In the case of C++, a server skeleton is a set of classes that provides pure virtual methods (methods with no implementations) or methods that delegate to methods in another class (tie class).
· The developer has to provide the implementations for these methods. In the case of Java, a server skeleton combines a set of helper classes with an interface, for which you, again, provide the implementation.
· The compiler produced a directory called StockMarket (corresponding to the name of the IDL module defined in StockMarket.idl). Within this directory are a number of files containing client stub and server skeleton definitions:
StockSymbolHelper.java
StockSymbolListHolder.java
StockSymbolListHelper.java
StockServer.java
StockServerHolder.java
StockServerHelper.java
_StockServerStub.java
_StockServerImplBase.java
· Note that the Java interface describing the StockServer services is contained in the StockServer.java file. Its contents appear in Listing 1.2.
· The StockServerImplBase.java file contains a helper class from which the implementation classes are derived.
Listing 1.2. StockServer.java.
/*
* File: ./StockMarket/StockServer.java
*/
package StockMarket;
public interface StockServer extends org.omg.CORBA.Object {
float getStockValue(String symbol);
String[] getStockSymbols();
}
· Examining Listing 1.2, the StockServer interface is placed in the StockMarket package. Furthermore, this interface extends the org.omg.CORBA.Object interface.
· All CORBA object interfaces extend this interface.
· Finally, the StockServer interface contains two methods that correspond to the IDL methods in StockServer.idl. Note, however, that the IDL types have been mapped to their Java counterparts: StockSymbol, which was typedef‘ed as an IDL string, maps to a Java String; StockSymbolList, which was a sequence of StockSymbols, is mapped to a Java array of Strings. The IDL float is mapped to a Java float.
Writing the Implementation
The implementation for the StockServer is straightforward.
Listing 1.3. StockServerImpl.java.
// StockServerImpl.java
package StockMarket;
import java.util.Vector;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;
// StockServerImpl implements the StockServer IDL interface.
public class StockServerImpl extends _StockServerImplBase implements StockServer {
// Stock symbols and their respective values.
private Vector myStockSymbols;
private Vector myStockValues;
// Characters from which StockSymbol names are built.
private static char ourCharacters[] = { `A’, `B’, `C’, `D’, `E’, `F’, `G’, `H’, `I’, `J’, `K’, `L’, `M’, `N’, `O’, `P’, `Q’, `R’, `S’, `T’, `U’, `V’, `W’, `X’, `Y’, `Z’ };
// Path name for StockServer objects.
private static String ourPathName = “StockServer”;
// Create a new StockServerImpl.
public StockServerImpl() {
myStockSymbols = new Vector();
myStockValues = new Vector();
// Initialize the symbols and values with some random values.
for (int i = 0; i < 10; i++) {
// Generate a string of four random characters.
StringBuffer stockSymbol = new StringBuffer(” “);
for (int j = 0; j < 4; j++) {
stockSymbol.setCharAt(j, ourCharacters[(int)(Math.random()* 26f)]);
}
myStockSymbols.addElement(stockSymbol.toString());
// Give the stock a value between 0 and 100. In this example,
// the stock will retain this value for the duration of the application.
myStockValues.addElement(new Float(Math.random() * 100f));
}
// Print out the stock symbols generated above.
System.out.println(”Generated stock symbols:”);
for (int i = 0; i < 10; i++) {
System.out.println(” ” + myStockSymbols.elementAt(i) + ” ” + myStockValues.elementAt(i));
}
System.out.println();
}
// Return the current value for the given StockSymbol.
public float getStockValue(String symbol) {
// Try to find the given symbol.
int stockIndex = myStockSymbols.indexOf(symbol);
if (stockIndex != -1) {
// Symbol found; return its value.
return ((Float)myStockValues.elementAt(stockIndex)). floatValue();
}
else {
// Symbol was not found.
return 0f;
}
}
// Return a sequence of all StockSymbols known by this StockServer.
public String[] getStockSymbols() {
String[] symbols = new String[myStockSymbols.size()];
myStockSymbols.copyInto(symbols);
return symbols;
}
// Create and initialize a StockServer object.
public static void main(String args[]) {
try {
// Initialize the ORB.
ORB orb = ORB.init(args, null);
// Create a StockServerImpl object and register it with the ORB.
StockServerImpl stockServer = new StockServerImpl();
orb.connect(stockServer);
// Get the root naming context.
org.omg.CORBA.Object obj = orb.resolve_initial_references(”NameService”);
NamingContext namingContext = NamingContextHelper.narrow(obj);
// Bind the StockServer object reference in the naming context.
NameComponent nameComponent = new NameComponent(ourPathName,”");
NameComponent path[] = { nameComponent };
namingContext.rebind(path, stockServer);
// Wait for invocations from clients.
java.lang.Object waitOnMe = new java.lang.Object();
synchronized (waitOnMe) {
waitOnMe.wait();
}
}
catch (Exception ex) {
System.err.println(”Couldn’t bind StockServer: ” + ex. getMessage());
}
}
}