The Portable Object Adapter (POA) provides more control on the request processing than it is possible when connecting objects directly to the ORB. The POA model defines a tree structure of POAs, the root POA being connected directly to the ORB. Any branch of this tree can be temporary or permanently inactivated using {@link org.omg.PortableServer.POAManager}. The same manager can control several branches in the POA tree. Also, any branch in this tree can have different processing options (policies).
The newly created POA is in holding state, just queuing requests. To start processing requests, it must be turned into the active state by its {@link org.omg.PortableServer.POAManagerOperations#activate}.
The previously monolite object implementation is now divided into object (that implements {@link org.omg.CORBA.Object}) and servant (that implements either {@link org.omg.CORBA.portable.InvokeHandler} or {@link org.omg.PortableServer.DynamicImplementation}). Frequently each object has its own servant, but it can also be a single servant per multiple objects and also default servant for POA (see {@link org.omg.PortableServer.POAOperations#set_servant}). Each object has its own Object Id, unique in the scope of the POA, where the object is connected. These Ids need not be different for objects belonging to different POAs, even if these POAs are connected to the same ORB. Under the USER_ID is assignment policy this Id can be a specified by user in {@link org.omg.PortableServer.POAOperations#activate_object_with_id}, encapsulating some meaningful information about the object. The Id of the object being currently served can be identified with {@link org.omg.PortableServer.Servant#_object_id}. This approach is used in cases when it is possible to encapsulate all object-related data into the Object Id. Such system only needs one servant, one server socket and one socket port per POA that can handle thounsands of objects.
Instead of being connected directly to the ORB, objects are now connected
to one of the ORBs POAs. Since JDK 1.4 the application specific implementation
base is derived from the {@link org.omg.PortableServer.Servant}, having a
different name pattern (*POA.java
instead of the previous
_*ImplBase.java
). This *POA
suffix does not
mean that these servants implement or are derived from POA. They are different
classes that can be connected to one of the POAs, by instance, using
{@link org.omg.PortableServer.POAOperations#servant_to_reference}.
The implementation base also inherits an *Operations interface, containing
definitions of the application specific methods. The application programmer
writes a descendent of the implementation base, implementing these methods
for the application - specific functionality.
The POA objects support the method invocation by name, using {@link org.omg.CORBA.Request}. This alternative method works without the service-specific classes that may not be available at run time.
The objects in POA can also be activated and inactivated independently. It is possible to set a listener ({@link org.omg.PortableServer.ServantActivator}) that would register the object activations ("incarnations") and deactivations ("etherializations"). The servant need not be specifyed when creating an object. Under the IMPLICIT_ACTIVATION {@link org.omg.PortableServer.ImplicitActivationPolicy} the {@link org.omg.PortableServer.ServantActivator} can provide the servant in response to the first (local or remote) call of any method on the previously incative object.
The root POA is obtained by resolving the initial reference "RootPOA" for the orb. In the simpliest case the objects can be connected directly to that root POA without creating the POA tree. The policies, used by the root POA, are defined by OMG as following:
Policy type | Accepted policy |
---|---|
{@link org.omg.PortableServer.IdAssignmentPolicy} | SYSTEM_ID (Ids are created by POA) |
{@link org.omg.PortableServer.IdUniquenessPolicy} | UNIQUE_ID (single object (and Id) per servant) |
{@link org.omg.PortableServer.ImplicitActivationPolicy} | IMPLICIT_ACTIVATION (if inactive, activate) |
{@link org.omg.PortableServer.LifespanPolicy} | TRANSIENT (the POA objects cannot outlive POA) |
{@link org.omg.PortableServer.RequestProcessingPolicy} | USE_ACTIVE_OBJECT_MAP_ONLY (the servant is provided during activation) |
{@link org.omg.PortableServer.ServantRetentionPolicy} | RETAIN (retain servants for subsequent invocations) |
{@link org.omg.PortableServer.ThreadPolicy} | ORB_CTRL_MODEL (single thread per request and single server socket per object) |
This set of policies means that each object will have a separate serving thread, separate network socket port and usually a separate servant. It is appropriate when the expected number of objects is not too large. If the expected number of objects is larger than the supportable number of threads and socket ports, the SINGLE_THREAD_MODEL {@link org.omg.PortableServer.ThreadPolicy} is used. Then all objects in POA with this policy are served in a single thread, using the same server socket, connected to a single port. If the request processing policy is additionally set to USE_DEFAULT_SERVANT, all objects of this POA share the same (default) servant.
The operations, supported by POA are defined separately in {@link org.omg.PortableServer.POAOperations}.
_this(ORB)
metod for servants for getting the object reference
that is already narrowed to the exact object type.
preinvoke
will be followed by the call of the postinvoke
; in
multithreaded environment these calls are not serialized in this way. If
the preinvoke
has to tell something this-call-specific to
the postinvoke
, it must use the provided cookie holder.
The preinvoke/postinoke
are also called to provide a servant
during each local invocation on the objects, belonging to the described POA.
All these scenarios must work with the current GNU Classpath release. @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)