Thursday, October 7, 2010

Programming the Object Adapter in CORBA

Programming with the POA

In order to create and use a POA, several steps are required. These steps may vary, however depending on the type of application being developed. The POA life cycle contains the following steps:

1. Get the Root POA

The first step is to get the root POA, which is managed by the ORB and provided to the application using the initial object name RootPOA. This is done as follows:

ORB orb = ORB.init(argv, null);
POA rootPOA = POAHelper.narrow(
orb.resolve_initial_references("RootPOA"));

2. Define the POA Policies

As I mentioned earlier, the POA is an object adapter that can be used with multiple ORB products without the need for rewriting code. It is also designed to allow persistent objects (objects that are always alive even though the server that is hosting them may have been restarted). As a result, the developer is given control over the object's identity, state, storage, and life cycle. This is done through the use of policies related to threads, lifespan, object uniqueness, activation, and others.

There are seven policies that you have control over. These are:

  • Thread Policy

    The appropriate thread usage technique for an application depends on several factors, including the number of objects the application will have, multi-threading support by the operating system, and the expect load on the system. In the BOA, multi-threading issues weren't addressed. The POA, however, has addressed this problem by providing a threading policy that can be used to specify the threading model to be used with the created POA. You can use:

    • ORB_CTRL_MODEL: This model allows multiple requests to be processed concurrently by multiple threads, and the ORB is responsible for assigning requests to threads (this is the default threading model).
    • SINGLE_THREAD_MODEL: In this model applications don't need to be thread-aware, and therefore all requests are processed sequentially (this however is not supported in J2SE 1.4).


    Here is how you create a policy:
    Policy p[] = new Policy[7];
    p[0] = rootPOA.createt_thread_policy(
    ThreadPolicyValue.ORB_CTRL_MODEL)
    In this example, we create an array of seven policy items. In the first item we have created a thread policy. Note however that the thread policy we created is the default anyway. This is a hypothetical example just to show you how to create policies.

  • Lifespan Policy

    The POA supports two types of CORBA objects: the persistent object that was originally specified by CORBA, and a new object called a transient. A transient object cannot live beyond the process in which it is created; it can be used in situations where temporary objects are required (as in callbacks). A persistent object, on the other hand, can live beyond the process that created it. For example, if a client sends a request to a target object that isn't active (not running), the ORB will activate a server process for the object (if necessary) and then activate the object itself. It is important to note that (as you will see in the programming examples later in the article) the activation process is transparent to the client.

    The lifespan policy can be used to specify the type of objects implemented in the created POA. You can make an object:

    • TRANSIENT: The objects cannot outlive the POA instance in which they are created (this is the default policy).
    • PERSISTENT: The objects can outlive the process in which they are created.


    As an example, the following snippet of code shows how to create a lifespan policy where the objects are persistent:
    p[1] = rootPOA.create_lifespan_policy(
    LifespanPolicyValue.PERSISTENT);
    As you can see from the above two example policies, to create a policy use the create_nameOf_policy(policNameValue.value) syntax.

  • Object ID Uniqueness Policy

    This policy can be used to specify whether the servants must have unique object identities. The value for this policy can be:

    • UNIQUE_ID: Servants support exactly one object ID (this is the default).
    • MULTIPLE_ID: A servant may support one or more object IDs.


    The following snippet of code shows an example of a policy that allows a servant to have one or more object IDs:
    p[2] = rootPOA.create_id_uniqueness_policy(
    IdUniquenessPolicyValue.MULTIPLE_ID);
  • ID Assignment Policy

    This policy can be used to specify whether object IDs are generated by the application or by the ORB. The options are:

    • USER_ID: Objects are assigned unique IDs only by the application.
    • SYSTEM_ID: Objects are assigned unique IDs by the POA (this is the default). Note that if the lifespan policy is set to PERSISTENT then assigned object IDs must be unique across all instantiations of the same POA.


    As an example, the following snippet of code shows how to create an assignment policy where object IDs are generated by the application:
    p[3] = rootPOA.create_id_assignment_policy(
    IdAssignmentPolicyValue.USER_ID);
  • Servant Retention Policy

    This policy specifies whether the created POA retains active servants in an object map. The options are:

    • RETAIN: Indicates the POA will retain active object in a map (this is the default).
    • NON_RETAIN: Active objects are not retained.


    The following snippet of code shows an example of a servant retention policy specifying that active objects are not retained by the POA in an object map:
    p[4] = rootPOA.create_servant_retention_policy(
    ServantRetentionPolicyValue.NON_RETAIN);
  • Request Processing Policy

    Use this policy to specify how you wish requests to be processed by the created POA. The options are:

    • USE_ACTIVE_OBJECT_MAP_ONLY: An OBJECT_NOT_EXIST exception is thrown if the object ID is not found in the active object map (this is the default). Note however, in order to use this you must set the ServantRetentionPolicyValue to RETAIN.
    • USE_DEFAULT_SERVANT: If the object ID is not found in the active object map or the servant retention policy is set to NON_RETAIN then the request is dispatched to the default servant.
    • USE_SERVANT_MANAGER: If the object ID is not found in the active object map or the NON_RETAIN server retention policy is present, the servant manager is given the opportunity to locate or activate a servant or raise an exception.


    The following snippet of code shows how to create a request processing policy where requests are dispatched to the default servant:
    p[5] = create_request_processing_policy(
    RequestProcessingPolicyValue.USE_DEFAULT_SERVANT);
  • Implicit Activation Policy:

    This policy specifies whether implicit activation of servants is supported in the created POA. The options are (the default is none):

    • IMPLICIT_ACTIVATION: Implicit activation of servants. Note however that this requires SYSTEM_ID and RETAIN policies to be present.
    • NO_IMPLICIT_ACTIVATION: No implicit servant activation.


Note that the root POA always has the following policies:

  • Thread policy: ORB_CTRL_MODEL.
  • Lifespan policy: TRANSIENT.
  • Object ID uniqueness: UNIQUE_ID.
  • ID assignment policy: SYSTEM_ID.
  • Servant retention policy: RETAIN.
  • Request processing policy: USE_ACTIVE_OBJECT_MAP_ONLY.
  • Implicit activation policy: IMPLICIT_ACTIVATION.

3. Create the POA

Create a new POA to allow you to define specific policies. A new POA is created as a child of an existing POA using the create_POA on the parent POA. When creating a new POA, you need to pass the following information:

  1. Name of the POA, which must be unique with respect to all other POAs with the same parent.
  2. POA Manager to be associated with the new POA. If null is passed then a new POA manager will be created.
  3. A policy list to be associated with the new POA.

The following snippet of code shows how a POA is created:

POA poa = rootPOA.create_POA(
"childPOA", null, policy);

4. Activate the POAManager

A POAManager is associated with one or more POA objects. It is responsible for controlling the processing state of the POAs. The POAManager may have one of the following states:

  • Holding: Associated POAs queue incoming requests (this is the default).
  • Active: Associated POAs start processing requests.
  • Inactive: Associated POAs rejects new requests as well as requests that haven't begun executing.
  • Discarding: Associated POAs will discard incoming requests.

When a POAManager object is created, it is in a HOLD state by default. In other words, it is not automatically activated. It is activated as follows:

poa.the_POAManager().activate();

Without this statement, all calls to a servant will hang in a queue because the POAManager is in a HOLD state.

5. Activate the Servants

If the USE_DEFAULT_SERVANT policy is set, the server application requests the POA to activate unknown objects by having the POA invoke a single servant no matter what the object ID is. The server application registers this servant with set_servant.

If, on the other hand, the RETAIN policy is in effect, the servant and its associated object ID are entered into the active object map of the appropriate POA. This activation can be accomplished in one of the following three ways:

  1. The server application explicitly activates individual objects through the activate_object or activate_object_with_id operations.
  2. The server application instructs the POA to activate objects on demand by having the POA invoke a user-supplied servant manager. The server manager is registered using the set_servant_manager operation.
  3. If the IMPLICIT_ACTIVATION policy is also set, the POA may implicitly activate an object when the server application attempts to obtain a reference for a servant that is not already active.

If, however, the NON_RETAIN policy is in effect, the POA may use either a default servant or a servant manager to locate an active servant. Note, however, that from the POA's point of view, the servant is active only for the duration of that one request. The POA doesn't enter the servant-object association into the active object map.

6. Create the Object Reference

Once an object reference is created in a server, it can be exported to clients. An object reference contains information related to object identity and others required by the ORB to identify and locate the server and the POA with which the object is associated. Object references can be created in three ways:

  1. Explicitly activate a servant and associate it with an object reference: the following snippet of code shows how this can be done using the servant_to_reference operation to map an activated servant to its corresponding object reference:
    org.omg.CORBA.Object obj =
    orb.resolve_initial_references("NameService");
    NamingContextExt rootctx =
    NamingContextExtHelper.narrow(obj);
    NameComponent nc[] = rootctx.to_name(
    "PersistentMathServer");
    rootctx.rebind(nc,
    poa.servant_to_reference(servant));

  2. Server application directly creates a reference: this can be done as shown in the following snippet of code:
    Context ctx = new InitialContext();
    ctx.rebind("MathServer",
    poa.create_reference_with_id(
    id, tie._all_interfaces(poa, id)[0]));
  3. Server application causes a servant to implicitly activate itself: this is possible when the POA has been created with the IMPLICIT_ACTIVATION policy set.

1 comment: