Java IDL: Using Adapter Activators

# Using Adapter Activators

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.

An adapter activator is optional. You would use an adapter activator if POAs need to be created during request processing. If all needed POAs are created when the application is initialized, an adapter activator is not required.

An adapter activator supplies a POA with the ability to create child POAs on demand, as a side-effect of receiving a request that names the child POA (or one of its children), or when the `find_POA` method is called with an activate parameter value of TRUE. The ORB will invoke an operation on an adapter activator when a request is received for a child POA that does not currently exist. The adapter activator can then create the required POA on demand.

A request must be capable of conveying the Object Id of the target object as well as the identification of the POA that created the target object reference. When a client issues a request, the ORB first locates an appropriate server (perhaps starting one if needed) and then it locates the appropriate POA within that server.

If the POA does not exist in the server process, the application has the opportunity to re-create the required POA by using an adapter activator. An adapter activator is a user-implemented object that can be associated with a POA. It is invoked by the ORB when a request is received for a nonexistent child POA. The adapter activator has the opportunity to create the required POA. If it does not, the client receives the `ADAPTER_NONEXISTENT` exception.

Once the ORB has located the appropriate POA, it delivers the request to that POA. The further processing of that request depends both upon the policies associated with that POA as well as the object's current state of activation.

# An Example Using Adapter Activators

The following example code shows an application that uses Adapter Activators to enable the POA to be created during request processing. This application builds on the "Hello World" example. The following files are included in this example:

- `Client.java`
- `Server.java`
- `Hello.idl`
- `HelloServant.java`
- `Makefile`
- `run.bat`

For instructions on running this example, see Running the Example Adapter Activator Application.

## Client.java

The code for the example client initializes the ORB, resolves `HelloServant`, and invokes the `sayHello()` method.

    //Client.java
    import org.omg.CORBA.ORB;
    import org.omg.CosNaming.NamingContext;
    import org.omg.CosNaming.NamingContextHelper;
    import org.omg.CosNaming.NameComponent;

    public class Client {

        public void run(String[] args) {
            try {
                //initialize the orb
                ORB orb = ORB.init(args, null);
                System.out.println("ORB initialized");

                NamingContext namingContext = NamingContextHelper.narrow(
                    orb.resolve_initial_references("NameService"));
                NameComponent[] nc = { new NameComponent("HelloServer", "") };

                //resolve HelloServant and invoke sayHello()
                Hello helloRef = HelloHelper.narrow(namingContext.resolve(nc));
                System.out.println("Resolved HelloServant");

                System.out.println(helloRef.sayHello());

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public static void main(String[] args) {
            new Client().run(args);
        }
    }

## Server.java

The code for the server does the following:

- Initializes the ORB.
- Resolve `RootPOA`.
- Registers the adapter activator with `rootPOA` so that child POAs can be created on demand.
- Runs `find_POA` with an activate parameter of `TRUE` to cause the adapter activator associated with `rootPOA` to be invoked if 'HelloPOA' does not exist.
- Creates the object reference for `HelloServant` and registers it with the naming service.
- Destroys 'HelloPOA'. This POA will be transparently recreated when the ORB receives a request on `HelloPOA` using the adapter activator we registered with the `RootPOA`.
- Activates `rootPOA`.
- Waits for incoming requests.
- Creates `MyAdapterActivator` to create the POA with appropriate policies, associate the servant with the new POA, and activate the new POA.

    //Server.java
    import org.omg.CORBA.ORB;
    import org.omg.CORBA.LocalObject;
    import org.omg.CORBA.Policy;
    import org.omg.PortableServer.POA;
    import org.omg.PortableServer.POAHelper;
    import org.omg.PortableServer.AdapterActivator;
    import org.omg.PortableServer.IdAssignmentPolicyValue;
    import org.omg.PortableServer.LifespanPolicyValue;
    import org.omg.PortableServer.ImplicitActivationPolicyValue;
    import org.omg.CosNaming.NamingContext;
    import org.omg.CosNaming.NamingContextHelper;
    import org.omg.CosNaming.NameComponent;

    public class Server {

        public void run(String[] args) {
            try {
                //initialize the orb
                ORB orb = ORB.init(args, null);
                System.out.println("ORB initialized");

                //resolve RootPOA
                POA rootPOA = POAHelper.narrow(
                    orb.resolve_initial_references("RootPOA"));

                //register adapter activator with rootPOA so that child POAs can
                //be created on demand
                rootPOA.the_activator(new MyAdapterActivator());

                //find_POA with an activate parameter TRUE would cause the
                //adapter activator associated with rootPOA to be invoked if
                //'HelloPOA' does not exist
                POA childPOA = rootPOA.find_POA("HelloPOA", true);

                //Create the object reference for HelloServant
                //and register with naming service
                org.omg.CORBA.Object obj = childPOA.id_to_reference(
                    "abcd".getBytes());
                Hello helloRef = HelloHelper.narrow(obj);

                NamingContext namingContext = NamingContextHelper.narrow(
                    orb.resolve_initial_references("NameService"));
                NameComponent[] nc = { new NameComponent("HelloServer", "") };
                namingContext.rebind(nc, helloRef);

                //Destroy 'HelloPOA'. This POA will be transparently recreated when
                //ORB receives a request on HelloPOA using the adapter activator we
                //registered with the RootPOA
                childPOA.destroy(true, true);

                //activate rootPOA
                rootPOA.the_POAManager().activate();

                //wait for incoming requests
                System.out.println("Server ready and running....");
                orb.run();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public static void main(String[] args) {
            new Server().run(args);
        }
    }

    class MyAdapterActivator extends LocalObject implements AdapterActivator {

        public boolean unknown_adapter(POA parent, String name) {
            System.out.println("unknown_adapter() invoked for POA - " + name);
            try {
                // create the POA with appropriate policies
                // this sample uses PERSISTENT, NO_IMPLICIT_ACTIVATION
                // and USER_ID policies
                Policy[] policy = new Policy[3];
                policy[0] = parent.create_lifespan_policy(
                    LifespanPolicyValue.PERSISTENT);
                policy[1] = parent.create_id_assignment_policy(
                    IdAssignmentPolicyValue.USER_ID);
                policy[2] = parent.create_implicit_activation_policy(
                    ImplicitActivationPolicyValue.NO_IMPLICIT_ACTIVATION);

                POA child = parent.create_POA(name, null, policy);

                //Associate the servant with the new POA
                HelloServant hello = new HelloServant();
                child.activate_object_with_id("abcd".getBytes(), hello);

                //activate the new POA
                child.the_POAManager().activate();

                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    }

## Hello.idl

This Interface Definition Language (IDL) file is used in all of the "Hello World" example variations on this site. This IDL file describes a CORBA object whose `sayHello()` operation returns a string.

    interface Hello {
       string sayHello();
    };

## HelloServant.java

The servant is the implementation of the Hello IDL interface; each `Hello` instance is implemented by a `HelloServant` instance. The servant is a subclass of `HelloPOA`, which is generated by the `idlj` compiler from the example IDL. The servant contains one method for each IDL operation, in this example, the `sayHello()` method. Servant methods are just like ordinary Java methods; the extra code to deal with the ORB, with marshaling arguments and results, and so on, is provided by the skeleton.

    //HelloServant.java
    public class HelloServant extends HelloPOA {

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

## Makefile

The make program generates a sequence of commands for execution by the Unix shell.

    JAVA_HOME=<path_to_your_Java_installation_bin_directory>

    #setup tools
    JAVA=$(JAVA_HOME)/bin/java
    JAVAC=$(JAVA_HOME)/bin/javac
    IDLJ=$(JAVA_HOME)/bin/idlj
    ORBD=$(JAVA_HOME)/bin/orbd

    all	: clean build run

    clean	:
    	- rm -rf classes orb.db

    build	:
    	mkdir -p classes
    	$(IDLJ) -fall -td classes Hello.idl
    	$(JAVAC) -classpath classes -d classes HelloServant.java Server.java Client.java

    run	: runorbd register runclient

    runorbd :
    	$(ORBD) -ORBInitialPort 10001 &
    	sleep 20

    register:
    	#servertool does not support script based register due to a bug
    	#using class instead
    	$(JAVA) com.sun.corba.se.internal.Activation.ServerTool \
    	-ORBInitialPort 10001 -cmd \
    	register -server Server -classpath classes

    runclient :
    	$(JAVA) -classpath classes Client -ORBInitialPort 10001

## run.bat

The bat utility generates a sequence of commands for execution by the Microsoft Windows command shell.

    SET JAVA_HOME=<path_to_your_Java_installation_build_directory>

    mkdir classes

    %JAVA_HOME%\bin\idlj -fall -td classes Hello.idl
    %JAVA_HOME%\bin\javac -classpath classes -d classes HelloServant.java Server.java Client.java

    REM - Start the ORB daemon

    start %JAVA_HOME%\bin\orbd -ORBInitialPort 10001 -ORBDebug orbd
    @echo Wait 10-15 seconds for the orbd to start
    @pause

    REM - Register the persistent server with orbd using servertool

    %JAVA_HOME%\bin\java com.sun.corba.se.internal.Activation.ServerTool -ORBInitialPort 10001 -cmd register -server Server -classpath classes

    %JAVA_HOME%\bin\java -classpath classes Client -ORBInitialPort 10001

## Running the Example Adapter Activator Application

To run this example,

- Create the files using the code shown above.
- Run the example using either of these methods:

  - If you have the Make utility, run the application using the `Makefile`:

    `make all`

  - If you have the batch utility, run the application using `run.bat`. From the application directory, enter:

    `run`

You will see output generated to the terminal window similar to that below when you run the Makefile:

    rm -rf classes orb.db
    mkdir -p classes
    /j2se1.4/bin/idlj -fall -td classes Hello.idl
    /j2se1.4/bin/javac -classpath classes -d classes HelloServant.java Server.java Client.java
    /j2se1.4/bin/orbd -ORBInitialPort 10001 &
    sleep 20
    #servertool does not support script based register due to a bug
    #using class instead
    /j2se1.4/bin/java com.sun.corba.se.internal.Activation.ServerTool \
    -ORBInitialPort 10001 -cmd \
    register -server Server -classpath classes

            server registered (serverid = 257).

    /j2se1.4/bin/java -classpath classes Client -ORBInitialPort 10001
    ORB initialized
    Resolved HelloServant
    Hello :)

Shut down ORBD when you have completed this example.

- If using the Unix operating system, type `pkill orbd` in the terminal window.
- If using Microsoft Windows, enter `Ctrl+C` in the command prompt window.

# Further Information

For more information on Adapter Activators, please refer to section 11.3.3 of the CORBA 2.3.1 Specification or the AdapterActivatorOperations API documentation.

Java IDL Home
Last updated: July 23, 2002