Using Servant Locators

What is a Servant Locator?

When creating a new POA, the application developer may declare specific policy choices for the new POA and provide a different adapter activator and servant manager (these are callback objects used by the POA to activate POAs on demand and activate servants). Creating new POAs also allows the application developer to partition the name space of objects, as Object Ids are interpreted relative to a POA. Finally, by creating new POAs, the developer can independently control request processing for multiple sets of objects.

A Servant Activator is a type of Servant Manager. Servant Managers are optional. You would use a servant manager to allow the POA to activate servants on demand when a request for an inactive object is received. If your server loads all objects when it starts up, you do not need a servant manager.

A servant manager is a callback object that the application developer can associate with a POA. The ORB will invoke operations on servant managers to activate servants on demand, and to deactivate servants. Servant managers are responsible for managing the association of an object reference (as characterized by its Object Id value) with a particular servant, and for determining whether an object reference exists or not. Each servant manager type contains two operations, the first called to find and return a servant and the second to deactivate a servant. The operations differ according to the amount of information usable for their situation.

To use servant managers, the USE_SERVANT_MANAGER policy must be set. Once set, the type of servant manager used in a particular situation depends on other policies in the POA. The two types of servant managers are:

An Example Using Servant Locators

The following example code shows an application that uses Servant Locators to enable the POA to activate transient objects. This application builds on the "Hello World" example. The following files are included for your information:

Client.java

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

public class Client {
    public Client(String[] args) {
        try {
            ORB orb = ORB.init(args, System.getProperties());
            NamingContext rootContext = NamingContextHelper.narrow(
                orb.resolve_initial_references("NameService"));

            // Resolves for remote object reference of HelloServer
            NameComponent name[] = {new NameComponent("HelloServer", "")};
            Hello helloRef = HelloHelper.narrow(rootContext.resolve(name));
            System.out.println("\nClient: Obtained the remote object " +
                               "reference");

            // Invokes the remote sayHello() method
            System.out.println("Client: Invoking the remote operation ...");
            System.out.println(helloRef.sayHello());
        } catch (Exception e) {
            System.err.println("\nClient: Caught exception - " + e);
            e.printStackTrace();
        }
    }

    public static void main(String [] args) {
        Client servantLocatorClient = new Client(args);
    }
}

Server.java

import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.ServantLocatorPackage.*;
import org.omg.CosNaming.*;

public class Server {
    public Server(String[] args) {
        try {
            ORB orb = ORB.init(args, System.getProperties());
            POA rootPoa = (POA) orb.resolve_initial_references("RootPOA");
            rootPoa.the_POAManager().activate();
            System.out.println("\nServer: Obtained from ORB and activated " +
                               "the " + rootPoa.the_name());

            Policy poaPolicy[] = new Policy[2];
            poaPolicy[0] = rootPoa.create_servant_retention_policy(
                ServantRetentionPolicyValue.NON_RETAIN);
            poaPolicy[1] = rootPoa.create_request_processing_policy(
                RequestProcessingPolicyValue.USE_SERVANT_MANAGER);
            System.out.println("Server: Set POA policy as NON_RETAIN and " +
                               "USE_SERVANT_MANAGER");

            POA poa1 = rootPoa.create_POA("HelloPoa", null, poaPolicy);
            poa1.the_POAManager().activate();
            System.out.println("Server: Created and activated child POA " +
                               "\"" + poa1.the_name() + "\"");

            poa1.set_servant_manager(new PoaServantLocator());
            System.out.println("Server: Associated the servant manager of " +
                               "type servant locator with \"" + 
                               poa1.the_name() + "\"");

            // This create_reference operation does not cause an activation, 
            // the resulting object reference will be exported and passed to 
            // client, so that subsequent requests on the reference will cause
            // the appropriate servant manager to be invoked
            org.omg.CORBA.Object objectRef = poa1.create_reference(
                HelloHelper.id());
            System.out.println("Server: Created a CORBA object reference " +
                               "from id \"" + HelloHelper.id() + "\""); 

            NamingContext rootContext = NamingContextHelper.narrow(
                orb.resolve_initial_references("NameService"));
            NameComponent name[] = {new NameComponent("HelloServer", "")};
            rootContext.rebind(name, objectRef);
            System.out.println("Server: Exported the CORBA object reference " +
                               "to NameService");

            System.out.println("Server: Ready and waiting for requests ...");
            orb.run();
        } catch (Exception e) {
            System.err.println("\nServer: Caught exception - " + e);
            e.printStackTrace();
        }
    }

    public static void main(String [] args) {
        Server serverServantLocator = new Server(args) ;
    }
}

class PoaServantLocator extends LocalObject implements ServantLocator {
    public Servant preinvoke(byte[] oid, POA adapter,
                             String operation,
                             CookieHolder the_cookie) throws ForwardRequest {
        try {
            HelloImpl servantObj = new HelloImpl();
            System.out.println("PoaServantLocator.preinvoke(): Created \"" +
                               servantObj.getClass().getName() + "\" " +
                               "servant object for \"" + adapter.the_name() +
                               "\"");
            return servantObj;
        } catch (Exception e) {
            System.err.println("preinvoke: Caught exception - " + e);
        }
        return null;
    }

    public void postinvoke(byte[] oid, POA adapter,
                           String operation,
                           java.lang.Object the_cookie,
                           Servant the_servant) {
        try {
            System.out.println("PoaServantLocator.postinvoke(): For \"" +
                               adapter.the_name() + "\" adapter of servant " +
                               "object type \"" +
                               the_servant.getClass().getName() + "\"");
        } catch (Exception e) {
            System.err.println("postinvoke: Caught exception - " + e);
        }
    }
}

Hello.idl

interface Hello {
    string sayHello();
};

HelloImpl.java

public class HelloImpl extends HelloPOA {

    public String sayHello() {
        return "Hello :)";
    }

}

Makefile

IDLJ=${JAVA_HOME}/bin/idlj
JAVAC=${JAVA_HOME}/bin/javac
JAVA=${JAVA_HOME}/bin/java

CLASSFILES=./classes_dir
IDLJFLAGS=-fall -verbose -td ${CLASSFILES}
JFLAGS=-g -d $(CLASSFILES) -classpath $(CLASSFILES)
JAVAFLAGS=-cp $(CLASSFILES) -Dorg.omg.CORBA.ORBInitialHost=localhost \
          -Dorg.omg.CORBA.ORBInitialPort=1950
ORBD_FLAGS=-port 1949 -ORBInitialHost ${SERVER_HOSTNAME} \
           -ORBInitialPort 1950 -ORBDebug
ORBD=${JAVA_HOME}/bin/orbd $(ORBD_FLAGS) orbd

client = Client.java

server = HelloImpl.java \
         Server.java

all: clean build run

clean:
        @echo ""
        @echo "*** Clean up old files and directories ***"
        -$(RM) $(CLASSFILES)
        -$(RM) ./orb.db
        -$(RM) ./kill_started_processes.sh

build: stubs client_server

stubs: Hello.idl
        @echo ""
        @echo "*** Generate stubs and helpers ***"
        @-$(MKDIR) $(CLASSFILES)
        $(IDLJ) $(IDLJFLAGS) Hello.idl

client_server: $(client) $(server)
        @echo ""
        @echo "*** Compile client, server and implementation ***"
        $(JAVAC) $(JFLAGS) $(client) $(server)

run: run_orbd run_server run_client terminate_servers

run_orbd:
        @echo ""
        @echo "*** Start the orbd ***"
        $(ORBD) & \
        echo "kill -9 $$!" > ./kill_started_processes.sh; \
        if [ $(OS) = "WinNT" ] ; then \
            tpid=`ps -o pid,ppid,comm | grep $$! | grep -v "sh" | cut -c1-6` ; \
            echo "kill -9 $$tpid" >> ./kill_started_processes.sh ; \
        fi ; \
        $(SLEEP) $(SLEEP_LONG)
        
run_server: run_orbd
        @echo ""
        @echo "*** Start the Server ***"
        $(JAVA) $(JAVAFLAGS) Server & \
        echo "kill -9 $$!" >> ./kill_started_processes.sh; \
        if [ $(OS) = "WinNT" ] ; then \
        tpid=`ps -o pid,ppid,comm | grep $$! | grep -v "sh" | cut -c1-6` ; \
        echo "kill -9 $$tpid" >> ./kill_started_processes.sh ; \
        fi ; \
        $(SLEEP) $(SLEEP_NORMAL)

run_client:
        @echo ""
        @echo "*** Start the Client ***"
        $(JAVA) $(JAVAFLAGS) Client

terminate_servers:
        @echo ""
        @echo "*** Terminate the Server and orbd ***"
        @$(SLEEP) $(SLEEP_SHORT)
        @if [ -f ./kill_started_processes.sh ]; then \
                $(CHMOD) u+x ./kill_started_processes.sh; \
                ./kill_started_processes.sh; \
                $(SLEEP) $(SLEEP_SHORT) ; \
        fi

runSample

#!/bin/ksh

if [ `uname` = "OpenOS" ] ; then
    OS="Solaris_sparc"
    JAVA_HOME=/path_to_your_java_installation
    SEP=:
    SLEEP=/bin/sleep
    RM="/bin/rm -rf"
    CHMOD=/bin/chmod
    MKDIR=/bin/mkdir
    SLEEP_SHORT=2
    SLEEP_NORMAL=5
    SLEEP_LONG=7
elif [ `uname` = "Windows_NT" ] ; then
    OS="WinNT"
    if [ ! -d "y:/path_to_your_java_installation" ] ; then
        echo; echo "Please map drive y: to \\\\\path_to_your_java_installation before 
runSample"
        exit 1
    fi
    JAVA_HOME="y:/path_to_your_java_installation"
    SEP=";"
    SLEEP=sleep
    RM="rm -rf"
    CHMOD=chmod
    MKDIR="mkdir -p"
    SLEEP_SHORT=5
    SLEEP_NORMAL=10
    SLEEP_LONG=15
fi

while [ $# -gt 0 ] ; do
   case $1 in
   -host ) SERVER_HOSTNAME=$2 ;
           shift;;
   * ) TARGET=$* ;
       break ;;
   esac
   shift
done

DEFAULT_HOSTNAME=localhost
SERVER_HOSTNAME=${HOSTNAME-$DEFAULT_HOSTNAME}

make ${TARGET} \
   "OS=${OS}" \
   "JAVA_HOME=${JAVA_HOME}" \
   "SERVER_HOSTNAME=${SERVER_HOSTNAME}" \
   "SLEEP=${SLEEP}" \
   "RM=${RM}" \
   "CHMOD=${CHMOD}" \
   "MKDIR=${MKDIR}" \
   "SLEEP_SHORT=${SLEEP_SHORT}" \
   "SLEEP_NORMAL=${SLEEP_NORMAL}" \
   "SLEEP_LONG=${SLEEP_LONG}"

Running the Example Servant Activator Example

To run this example,

  1. Create the files using the code shown above.
  2. Run the example as shown in runSample.

You will see output generated to the terminal window similar to that below:


*** Clean up old files and directories ***
/bin/rm -rf ./classes_dir
/bin/rm -rf ./orb.db
/bin/rm -rf ./kill_started_processes.sh

*** Generate stubs and helpers ***
/path_to_your_java_installation/bin/idlj -fall -verbose -td ./classes_dir Hello.idl
Parsing Hello.idl
done  - Hello.idl

Generating Hello
done   -   Hello

*** Compile client, server and implementation ***
/path_to_your_java_installation/bin/javac -g -d ./classes_dir -classpath ./classes_dir 
Client.java HelloImpl.java Server.java

*** Start the orbd ***
/path_to_your_java_installation/bin/orbd -port 1949 -ORBInitialHost localhost -ORBInitialPort 
1950 -ORBDebug orbd & \
echo "kill -9 $!" > ./kill_started_processes.sh; \
if [ Solaris_sparc = "WinNT" ] ; then \
    tpid=`ps -o pid,ppid,comm | grep $! | grep -v "sh" | cut -c1-6` ; \
    echo "kill -9 $tpid" >> ./kill_started_processes.sh ; \
fi ; \
/bin/sleep 7
ORBD begins initialization.
ORBD is ready.
ORBD serverid: 1
activation dbdir: /home/dcarson1/samples/POA_samples/ServantLocator/./orb.db
activation port: 1949
activation Server Polling Time: 1000 milli-seconds 
activation Server Startup Delay: 1000 milli-seconds 

*** Start the Server ***
/path_to_your_java_installation/bin/java -cp ./classes_dir 
-Dorg.omg.CORBA.ORBInitialHost=localhost -Dorg.omg.CORBA.ORBInitialPort=1950 Server & \
echo "kill -9 $!" >> ./kill_started_processes.sh; \
if [ Solaris_sparc = "WinNT" ] ; then \
tpid=`ps -o pid,ppid,comm | grep $! | grep -v "sh" | cut -c1-6` ; \
echo "kill -9 $tpid" >> ./kill_started_processes.sh ; \
fi ; \
/bin/sleep 5

Server: Obtained from ORB and activated the RootPOA
Server: Set POA policy as NON_RETAIN and USE_SERVANT_MANAGER
Server: Created and activated child POA "HelloPoa"
Server: Associated the servant manager of type servant locator with "HelloPoa"
Server: Created a CORBA object reference from id "IDL:Hello:1.0"
Server: Exported the CORBA object reference to NameService
Server: Ready and waiting for requests ...

*** Start the Client ***
/path_to_your_java_installation/bin/java -cp ./classes_dir 
-Dorg.omg.CORBA.ORBInitialHost=localhost -Dorg.omg.CORBA.ORBInitialPort=1950 Client

Client: Obtained the remote object reference
Client: Invoking the remote operation ...
PoaServantLocator.preinvoke(): Created "HelloImpl" servant object for "HelloPoa"
PoaServantLocator.postinvoke(): For "HelloPoa" adapter of servant object type "HelloImpl"
Hello :)

*** Terminate the Server and orbd ***

Further Information

For more information on Servant Locators, see the section on Servant Managers in section 11.3.4 of the CORBA 2.3.1 Specification.


Copyright © 1993, 2014, Oracle and/or its affiliates. All rights reserved.