If you downloaded this document as part of the J2SE TM documentation bundle, check the Web site at http://java.sun.com/j2se/1.4/docs/guide/idl/PI.html for updates.
NOTICE: This document is intended for advanced CORBA developers.
The JavaTM CORBA Object Request Broker (ORB) provides hooks, or interception points, through which ORB services can intercept the normal flow of execution of the ORB. These Portable Interceptors provide a mechanism for plugging in additional ORB behavior, or, by modifying the communications between client and server, for modifying the behavior of the ORB. The example that follows shows different ways of using Portable Interceptors.
Support for Portable Interceptors is a major recent addition to the CORBA specification. Using RequestInterceptors, one can easily write and attach portable ORB hooks that will intercept any ORB-mediated invocation. Using IORInterceptors, one can write code to annotate CORBA object references.
IORInterceptor
In some cases, a portable ORB service implementation may need to add information describing the server's or object's ORB service-related capabilities to object references in order to enable the ORB service implementation in the client to function properly. This is supported through the IORInterceptor and IORInfo interfaces. The IOR Interceptor is used to establish tagged components in the profiles within an Interoperable Object Reference (IOR).
An example of an IOR Interceptor is shown in the file AServiceIORInterceptor.java in the example that follows.
ClientRequestInterceptor
A request Interceptor is designed to intercept the flow of a request/reply sequence through the ORB at specific points so that services can query the request information and manipulate the service contexts which are propagated between clients and servers. The primary use of request Interceptors is to enable ORB services to transfer context information between clients and servers.
A
ClientRequestInterceptor
intercepts the flow of a request/reply
sequence through the ORB on
the client side.
An example of a ClientRequestInterceptor is shown in the file LoggingServiceClientInterceptor.java in the example that follows.
ServerRequestInterceptor
A
ServerRequestInterceptor
intercepts the flow of a request/reply
sequence through the ORB on
the server side.
An example of a ServerRequestInterceptor is shown in the file LoggingServiceServerInterceptor.java in the example that follows.
The class
ORBInitializer
facilitates interceptor registration and ORB initialization.
Interceptors are intended to be a means by which ORB services gain
access to ORB processing, effectively becoming part of the ORB.
Since interceptors are part of the ORB, when ORB.init
returns an ORB, the interceptors shall have been registered.
Interceptors cannot be registered on an ORB after it has been
returned by a call to ORB.init
.
ORBInitializers
are registered via Java ORB properties.
An interceptor is registered by registering an associated
ORBInitializer
object which implements the
ORBInitializer
interface. When an ORB is initializing,
it shall call each registered ORBInitializer
, passing it
an ORBInitInfo
object which is used to register its
interceptor.
The property names are of the form:
org.omg.PortableInterceptor.ORBInitializerClass.<Service>
where <Service>
is the string name of a class
which implements
org.omg.PortableInterceptor.ORBInitializer
To avoid name collisions, the reverse DNS name convention should be
used. For example, if company X has three initializers, it could define
the following properties:
org.omg.PortableInterceptor.ORBInitializerClass.com.x.Init1
org.omg.PortableInterceptor.ORBInitializerClass.com.x.Init2
org.omg.PortableInterceptor.ORBInitializerClass.com.x.Init3
org.omg.PortableInterceptor.ORBInitializerClass
shall be
collected, the <Service>
portion of each property
shall be extracted, an object shall be instantiated with the
<Service>
string as its class name, and the
pre_init
and post_init
methods shall be
called on that object. If there are any exceptions, the ORB shall
ignore them and proceed.
ORB.init
with the provided orb_id
). Since
registration occurs during ORB initialization, results of invocations
on this ORB while it is in this state are undefined.
The PortableInterceptor::Current object (hereafter referred to as PICurrent) is a Current object that is used specifically by portable Interceptors to transfer thread context information to a request context. Portable Interceptors are not required to use PICurrent, but if information from a client's thread context is required at an Interceptor's interception points, then PICurrent can be used to propagate that information. PICurrent allows portable service code to be written regardless of an ORB's threading model.
On the client side, this information includes, but is not limited to, thread context information that shall be propagated to the server via a service context.
On the server side, this information includes, but is not limited to, service context information received from the client which is propagated to the target's thread context.
Before an invocation is made, PICurrent is obtained via a call to ORB::resolve_initial_references ( PICurrent ). From within the interception points, the data on PICurrent that has moved from the thread scope to the request scope is available via the get_slot operation on the RequestInfo object. A PICurrent can still be obtained via resolve_initial_references, but that is the Interceptor's thread scope PICurrent.
The thread scope PICurrent (TSC) is the PICurrent that exists within a thread's context. A request scope PICurrent (RSC) is the PICurrent associated with the request. On the client-side, the thread scope PICurrent is logically copied to the request scope PICurrent from the thread s context when a request begins and is attached to the ClientRequestInfo object. On the server-side, the request scope PICurrent is attached to the ServerRequestInfo and follows the request processing. It is logically copied to the thread scope PICurrent after the list of receive_request_service_contexts interception points are processed. See the Updated Interceptors specification, Section, 21.4.4.5, Flow of PICurrent between Scopes for a detailed discussion of the scope of PICurrent.
This section contains an example logging service application. The sample code for this application is quite complicated because it covers even subtle "corner cases". The following scenarios are covered in this sample application:
Note: These examples explicitly register ORBInitializers
to make the
code easier to experiment with and setup. Typically this would not be
done. Instead, this information would be passed as -D properties to
the Java virtual machine when the applications are started. That way the applications are
not coupled to the fact that either the service exists (e.g., the
logging service) or that a service that they explicitly use (e.g., the
AService interface) is implemented as an interceptor. For example,
to run a program called MyApp
using this logging
service, the user could type:
java -Dorg.omg.PortableInterceptor.ORBInitializerClass.com.x.Logging.LoggingService MyApp
The example application shows how to use interceptors to create a logging service application, as follows:
The following diagram shows the flow of information in the logging service:
The following diagram shows the flow of information in the colocated logging service:
The following diagram shows the flow of information in AService:
If you would like to create and run this application, enter the code as shown in the following sections, then follow the instructions in Compiling and Running the Application.
serviceexample.idl
This is the Interface Definition Language (IDL) file that contains definitions of an arbitrary object on which to make invocations and two services which will service calls to the arbitrary object.
// serviceexample.idl // Copyright and License module pi { module serviceexample { // Create some arbitrary object to call. Those calls // will be serviced by the service implemented using interceptors. exception ArbitraryObjectException { string reason; }; interface ArbitraryObject { string arbitraryOperation1 ( in string a1 ); oneway void arbitraryOperation2 ( in long a1 ); void arbitraryOperation3 ( in string a1 ) raises (ArbitraryObjectException); }; // This would typically be in a file separate from the "ArbitraryObject" // and probably unknown to it. interface LoggingService { void log ( in string a1 ); }; // This would also typically be in a file of its own. // IMPORTANT: the interface should be a local object to avoid // unnecessary overhead. /*local*/ interface AService { void begin(); void end(); void verify(); }; // Tagged component for adding to an IOR to indicate that // the AService must be in effect when invocations are made // on the object containing this tagged component. // Note: we explicitly declare the tag type rather than using // the IOP typedef (commented out) to simplify compiling this // example (i.e., to avoid includes and make include path directives). //const IOP::ComponentId TAG_ASERVICE_COMPONENT = 2345; const unsigned long TAG_ASERVICE_COMPONENT = 2345; struct ASERVICE_COMPONENT { boolean requiresAService; }; }; // module serviceexample }; // module pi
LoggingServiceClientORBInitializer.java
This file creates and registers the logging service interceptor used by object clients.
// LoggingServiceClientORBInitializer.java // Copyright and License package pi.serviceexample; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.PortableInterceptor.Current; import org.omg.PortableInterceptor.CurrentHelper; import org.omg.PortableInterceptor.ORBInitInfo; public class LoggingServiceClientORBInitializer extends org.omg.CORBA.LocalObject implements org.omg.PortableInterceptor.ORBInitializer { public void pre_init(ORBInitInfo info) { } public void post_init(ORBInitInfo info) { try { // Get a reference to the LoggingService object. NamingContext nameService = NamingContextHelper.narrow( info.resolve_initial_references("NameService")); NameComponent path[] = { new NameComponent("LoggingService", "") }; LoggingService loggingService = LoggingServiceHelper.narrow(nameService.resolve(path)); // Get a reference to TSC PICurrent. Current piCurrent = CurrentHelper.narrow( info.resolve_initial_references("PICurrent")); // Allocate a slot id to use for the interceptor to indicate // that it is making an outcall. This is used to avoid // infinite recursion. int outCallIndicatorSlotId = info.allocate_slot_id(); // Create (with the above data) and register the client // side interceptor. LoggingServiceClientInterceptor interceptor = new LoggingServiceClientInterceptor(loggingService, piCurrent, outCallIndicatorSlotId); info.add_client_request_interceptor(interceptor); } catch (Throwable t) { System.out.println("Exception handling not shown."); } } }
LoggingServiceClientInterceptor.java
This interceptor logs client side interception points. It illustrates how to make invocations on other objects from within an interceptor and how to avoid infinite recursion during those "outcall" invocations.
// LoggingServiceClientInterceptor.java // Copyright and License package pi.serviceexample; import org.omg.CORBA.Any; import org.omg.CORBA.ORB; import org.omg.CORBA.TCKind; import org.omg.IOP.ServiceContext; import org.omg.PortableInterceptor.ClientRequestInterceptor; import org.omg.PortableInterceptor.ClientRequestInfo; import org.omg.PortableInterceptor.Current; import org.omg.PortableInterceptor.InvalidSlot; public class LoggingServiceClientInterceptor extends org.omg.CORBA.LocalObject implements ClientRequestInterceptor { private LoggingService loggingService; private Current piCurrent; private int outCallIndicatorSlotId; public LoggingServiceClientInterceptor(LoggingService loggingService, Current piCurrent, int outCallIndicatorSlotId) { this.loggingService = loggingService; this.piCurrent = piCurrent; this.outCallIndicatorSlotId = outCallIndicatorSlotId; } // // Interceptor operations // public String name() { return "LoggingServiceClientInterceptor"; } public void destroy() { } // // ClientRequestInterceptor operations // public void send_request(ClientRequestInfo ri) { log(ri, "send_request"); } public void send_poll(ClientRequestInfo ri) { log(ri, "send_poll"); } public void receive_reply(ClientRequestInfo ri) { log(ri, "receive_reply"); } public void receive_exception(ClientRequestInfo ri) { log(ri, "receive_exception"); } public void receive_other(ClientRequestInfo ri) { log(ri, "receive_other"); } // // Utilities. // public void log(ClientRequestInfo ri, String point) { // IMPORTANT: Always set the TSC out call indicator in case // other interceptors make outcalls for this request. // Otherwise the outcall will not be set for the other interceptor's // outcall resulting in infinite recursion. Any indicator = ORB.init().create_any(); indicator.insert_boolean(true); try { piCurrent.set_slot(outCallIndicatorSlotId, indicator); } catch (InvalidSlot e) { } try { indicator = ri.get_slot(outCallIndicatorSlotId); // If the RSC out call slot is not set then log this invocation. // If it is set that indicates the interceptor is servicing the // invocation of loggingService itself. In that case do // nothing (to avoid infinite recursion). if (indicator.type().kind().equals(TCKind.tk_null)) { loggingService.log(ri.operation() + " " + point); } } catch (InvalidSlot e) { System.out.println("Exception handling not shown."); } } }
LoggingServiceServerORBInitializer.java
// LoggingServiceServerORBInitializer.java // Copyright and License package pi.serviceexample; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.PortableInterceptor.Current; import org.omg.PortableInterceptor.CurrentHelper; import org.omg.PortableInterceptor.ORBInitInfo; public class LoggingServiceServerORBInitializer extends org.omg.CORBA.LocalObject implements org.omg.PortableInterceptor.ORBInitializer { public void pre_init(ORBInitInfo info) { } public void post_init(ORBInitInfo info) { try { // Create and register the logging service interceptor. // Give that interceptor references to the NameService and // PICurrent to avoid further lookups (i.e., optimization). // More importantly, allocate and give the interceptor // a slot id which is will use to tell itself not to // log calls that the interceptor makes to the logging process. NamingContext nameService = NamingContextHelper.narrow( info.resolve_initial_references("NameService")); Current piCurrent = CurrentHelper.narrow( info.resolve_initial_references("PICurrent")); int outCallIndicatorSlotId = info.allocate_slot_id(); LoggingServiceServerInterceptor interceptor = new LoggingServiceServerInterceptor(nameService, piCurrent, outCallIndicatorSlotId); info.add_client_request_interceptor(interceptor); info.add_server_request_interceptor(interceptor); } catch (Throwable t) { System.out.println("Exception handling not shown."); } } }
LoggingServiceServerInterceptor.java
This interceptor logs server side interception points, and is implemented as both a ClientRequestInterceptor and a ServerRequestInterceptor to illustrate the need to set some "out call" service context data (in addition to setting an out call slot) to avoid infinite recursion for the case noted in the description of LoggingServiceServerORBInitializer.java.
// LoggingServiceServerInterceptor.java // Copyright and License package pi.serviceexample; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.Any; import org.omg.CORBA.BAD_PARAM; import org.omg.CORBA.ORB; import org.omg.CORBA.TCKind; import org.omg.IOP.ServiceContext; import org.omg.PortableInterceptor.ClientRequestInterceptor; import org.omg.PortableInterceptor.ClientRequestInfo; import org.omg.PortableInterceptor.Current; import org.omg.PortableInterceptor.InvalidSlot; import org.omg.PortableInterceptor.ServerRequestInterceptor; import org.omg.PortableInterceptor.ServerRequestInfo; public class LoggingServiceServerInterceptor extends org.omg.CORBA.LocalObject implements ClientRequestInterceptor, ServerRequestInterceptor { private NamingContext nameService; private LoggingService loggingService; private Current piCurrent; private int outCallIndicatorSlotId; private static final int serviceContextId = 100001; private static final byte[] serviceContextData = {1}; // Returns a reference to the logging process. private LoggingService loggingService() { if (loggingService == null) { NameComponent path[] = { new NameComponent("LoggingService", "") }; try { loggingService = LoggingServiceHelper.narrow(nameService.resolve(path)); } catch (Throwable t) { System.out.println("Exception handling not shown."); } } return loggingService; } public LoggingServiceServerInterceptor(NamingContext nameService, Current piCurrent, int outCallIndicatorSlotId) { this.nameService = nameService; this.piCurrent = piCurrent; this.outCallIndicatorSlotId = outCallIndicatorSlotId; } // // Interceptor operations // public String name() { return "LoggingServiceServerInterceptor"; } public void destroy() { } // // ClientRequestInterceptor operations // public void send_request(ClientRequestInfo ri) { // If the server interceptor sets the recursion slot then // put in the service context so the server doesn't make // the call again in the case where the server side interceptor // is colocated in the same ORB as the object being invoked. try { Any indicator = ri.get_slot(outCallIndicatorSlotId); if (indicator.type().kind().equals(TCKind.tk_boolean)) { ServiceContext serviceContext = new ServiceContext(serviceContextId, serviceContextData); ri.add_request_service_context(serviceContext, false); } } catch (InvalidSlot e) { System.out.println("Exception handling not shown."); } } public void send_poll(ClientRequestInfo ri) { } public void receive_reply(ClientRequestInfo ri) { } public void receive_exception(ClientRequestInfo ri) { } public void receive_other(ClientRequestInfo ri) { } // // ServerRequestInterceptor operations // public void receive_request_service_contexts(ServerRequestInfo ri) { log(ri, "receive_request_service_contexts"); } public void receive_request(ServerRequestInfo ri) { log(ri, "receive_request"); } public void send_reply(ServerRequestInfo ri) { log(ri, "send_reply"); } public void send_exception(ServerRequestInfo ri) { log(ri, "send_exception"); } public void send_other(ServerRequestInfo ri) { log(ri, "send_other"); } // // Utilities. // public void log(ServerRequestInfo ri, String point) { // This is only relevant for the colocated example. // Do not attempt to log until the logging service object // has been bound in naming. Otherwise the attempt to call // rebind on naming will call log which will fail. if (! ColocatedServers.colocatedBootstrapDone) { return; } // IMPORTANT: // The conditional logging of the invocation is only necessary // if there is a chance that the object being invoked is colocated // in the same ORB as this interceptor. Otherwise the outcall to // the logging service can be made unconditionally. // Always set the recursion slot. Any indicator = ORB.init().create_any(); indicator.insert_boolean(true); try { piCurrent.set_slot(outCallIndicatorSlotId, indicator); } catch (InvalidSlot e) { System.out.println("Exception handling not shown."); } // Make the out call if you have not already done so. try { // Only the presence of the service context counts. // The data is ignored. ri.get_request_service_context(serviceContextId); } catch (BAD_PARAM e) { // Recursion indicator not set so make the call. loggingService().log(ri.operation() + " " + point); } } }
LoggingServiceImpl.java
// // Copyright and License package pi.serviceexample; import org.omg.CORBA.ORB; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.PortableServer.POA; import java.util.Properties; class LoggingServiceImpl extends LoggingServicePOA { public static ORB orb; // // The IDL operations. // public void log(String a1) { System.out.println(a1); } // // The server. // public static void main(String[] av) { try { if (orb == null) { orb = ORB.init(av, null); } POA rootPOA = POAHelper.narrow( orb.resolve_initial_references("RootPOA")); rootPOA.the_POAManager().activate(); byte[] objectId = rootPOA.activate_object(new LoggingServiceImpl()); org.omg.CORBA.Object ref = rootPOA.id_to_reference(objectId); NamingContext nameService = NamingContextHelper.narrow( orb.resolve_initial_references("NameService")); NameComponent path[] = { new NameComponent("LoggingService", "") }; nameService.rebind(path, ref); // Only relevant for colocated example. ColocatedServers.colocatedBootstrapDone = true; System.out.println("LoggingService ready."); orb.run(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } System.exit(0); } }
AServiceORBInitializer.java
// AServiceORBInitializer.java // Copyright and License package pi.serviceexample; import org.omg.IOP.Codec; import org.omg.IOP.CodecFactory; import org.omg.IOP.CodecFactoryHelper; import org.omg.IOP.Encoding; import org.omg.PortableInterceptor.Current; import org.omg.PortableInterceptor.CurrentHelper; import org.omg.PortableInterceptor.ORBInitInfo; public class AServiceORBInitializer extends org.omg.CORBA.LocalObject implements org.omg.PortableInterceptor.ORBInitializer { private AServiceImpl aServiceImpl; private AServiceInterceptor aServiceInterceptor; public void pre_init(ORBInitInfo info) { try { int id = info.allocate_slot_id(); aServiceInterceptor = new AServiceInterceptor(id); info.add_client_request_interceptor(aServiceInterceptor); info.add_server_request_interceptor(aServiceInterceptor); // Create and register a reference to the service to be // used by client code. aServiceImpl = new AServiceImpl(id); info.register_initial_reference("AService", aServiceImpl); } catch (Throwable t) { System.out.println("Exception handling not shown."); } } public void post_init(ORBInitInfo info) { try { Current piCurrent = CurrentHelper.narrow( info.resolve_initial_references("PICurrent")); aServiceImpl.setPICurrent(piCurrent); CodecFactory codecFactory = CodecFactoryHelper.narrow( info.resolve_initial_references("CodecFactory")); Encoding encoding = new Encoding((short)0, (byte)1, (byte)2); Codec codec = codecFactory.create_codec(encoding); aServiceInterceptor.setCodec(codec); AServiceIORInterceptor aServiceIORInterceptor = new AServiceIORInterceptor(codec); info.add_ior_interceptor(aServiceIORInterceptor); } catch (Throwable t) { System.out.println("Exception handling not shown."); } } }
AServiceImpl.java
// // Copyright and License package pi.serviceexample; import org.omg.CORBA.Any; import org.omg.CORBA.TCKind; import org.omg.CORBA.LocalObject; import org.omg.CORBA.ORB; import org.omg.PortableInterceptor.Current; import org.omg.PortableInterceptor.InvalidSlot; class AServiceImpl extends LocalObject implements AService { private int slotId; private int currentServiceId = 0; private Current piCurrent; private Any NOT_IN_EFFECT; public AServiceImpl(int slotId) { this.slotId = slotId; NOT_IN_EFFECT = ORB.init().create_any(); } // Package protected so the AService ORBInitializer can access this // non-IDL defined method. void setPICurrent(Current piCurrent) { this.piCurrent = piCurrent; } public void begin() { Any any = ORB.init().create_any(); any.insert_long(++currentServiceId); setSlot(any); } public void end() { setSlot(NOT_IN_EFFECT); } public void verify() { try { Any any = piCurrent.get_slot(slotId); if (any.type().kind().equals(TCKind.tk_long)) { System.out.println("Service present: " + any.extract_long()); } else { System.out.println("Service not present"); } } catch (InvalidSlot e) { System.out.println("Exception handling not shown."); } } // Synchronized because two threads in the same ORB could be // sharing this object. synchronized private void setSlot(Any any) { try { piCurrent.set_slot(slotId, any); } catch (InvalidSlot e) { System.out.println("Exception handling not shown."); } } }
AServiceInterceptor.java
This interceptor is responsible for arranging to pass the client side AService information to the service side.
On the client side, if AService.begin() has been called, the send_request(ri) point will see the service id in the RSC slot. In this case, it inserts the value of that service id into an org.omg.CORBA.ServiceContext and adds that service context to the data to be passed along with the invocation.
On the server side, receive_request_service_context(ri) looks for the presence of that service context. When present, it extracts the service id value from the ServiceContext and sets the RSC slot to that value. When the servant is executing, the value of that RSC slot is available in the TSC slot.
// AServiceInterceptor.java // Copyright and License package pi.serviceexample; import org.omg.CORBA.Any; import org.omg.CORBA.BAD_PARAM; import org.omg.CORBA.ORB; import org.omg.CORBA.TCKind; import org.omg.IOP.Codec; import org.omg.IOP.CodecPackage.FormatMismatch; import org.omg.IOP.CodecPackage.TypeMismatch; import org.omg.IOP.ServiceContext; import org.omg.IOP.TaggedComponent; import org.omg.PortableInterceptor.ClientRequestInterceptor; import org.omg.PortableInterceptor.ClientRequestInfo; import org.omg.PortableInterceptor.InvalidSlot; import org.omg.PortableInterceptor.ServerRequestInterceptor; import org.omg.PortableInterceptor.ServerRequestInfo; public class AServiceInterceptor extends org.omg.CORBA.LocalObject implements ClientRequestInterceptor, ServerRequestInterceptor { private int slotId; private Codec codec; private static final int serviceContextId = 1234; public AServiceInterceptor(int slotId) { this.slotId = slotId; } void setCodec(Codec codec) { this.codec = codec; } // // Interceptor operations // public String name() { return "AServiceInterceptor"; } public void destroy() { } // // ClientRequestInterceptor operations // public void send_request(ClientRequestInfo ri) { // // See if the target object contains an ASERVICE_COMPONENT. // try { TaggedComponent taggedComponent = ri.get_effective_component(TAG_ASERVICE_COMPONENT.value); Any sAny = null; try { sAny = codec.decode_value(taggedComponent.component_data, ASERVICE_COMPONENTHelper.type()); } catch (TypeMismatch e) { System.out.println("Exception handling not shown."); } catch (FormatMismatch e) { System.out.println("Exception handling not shown."); } ASERVICE_COMPONENT aServiceComponent = ASERVICE_COMPONENTHelper.extract(sAny); // // Only send the service context if the target object requires it. // if (aServiceComponent.requiresAService) { try { Any any = ri.get_slot(slotId); if (any.type().kind().equals(TCKind.tk_long)) { int serviceId = any.extract_long(); byte[] serviceContextData = { // Little endian to make it // easier to see in debugger. (byte)((serviceId >>> 0) & 0xFF), (byte)((serviceId >>> 8) & 0xFF), (byte)((serviceId >>> 16) & 0xFF), (byte)((serviceId >>> 24) & 0xFF) }; ri.add_request_service_context( new ServiceContext(serviceContextId, serviceContextData), false); } } catch (InvalidSlot e) { System.out.println("Exception handling not shown."); } } } catch (BAD_PARAM e) { // If it is not present, do nothing. ; } } public void send_poll(ClientRequestInfo ri) { } public void receive_reply(ClientRequestInfo ri) { } public void receive_exception(ClientRequestInfo ri) { } public void receive_other(ClientRequestInfo ri) { } // // ServerRequestInterceptor operations // public void receive_request_service_contexts(ServerRequestInfo ri) { try { ServiceContext serviceContext = ri.get_request_service_context(serviceContextId); byte[] data = serviceContext.context_data; int b1, b2, b3, b4; b4 = (data[0] << 0) & 0x000000FF; b3 = (data[1] << 8) & 0x0000FF00; b2 = (data[2] << 16) & 0x00FF0000; b1 = (data[3] << 24) & 0xFF000000; int serviceId = (b1 | b2 | b3 | b4); Any any = ORB.init().create_any(); any.insert_long(serviceId); ri.set_slot(slotId, any); } catch (BAD_PARAM e) { // Not present means service is not in effect. // Do nothing. ; } catch (InvalidSlot e) { System.out.println("Exception handling not shown."); } } public void receive_request(ServerRequestInfo ri) { } public void send_reply(ServerRequestInfo ri) { } public void send_exception(ServerRequestInfo ri) { } public void send_other(ServerRequestInfo ri) { } }
AServiceIORInterceptor.java
// AServiceIORInterceptor.java // Copyright and License package pi.serviceexample; import org.omg.CORBA.Any; import org.omg.CORBA.LocalObject; import org.omg.CORBA.ORB; import org.omg.IOP.TaggedComponent; import org.omg.IOP.Codec; import org.omg.IOP.CodecPackage.InvalidTypeForEncoding; import org.omg.PortableInterceptor.IORInfo; import org.omg.PortableInterceptor.IORInterceptor; public class AServiceIORInterceptor extends org.omg.CORBA.LocalObject implements IORInterceptor { private Codec codec; public AServiceIORInterceptor(Codec codec) { this.codec = codec; } // // Interceptor operations // public String name() { return "AServiceInterceptor"; } public void destroy() { } // // IOR Interceptor operations // public void establish_components(IORInfo info) { // // Note: typically, rather than just inserting a tagged component // this interceptor would check info.get_effective_policy(int) // to determine if a tagged component reflecting that policy // should be added to the IOR. That is not shown in this example. // ASERVICE_COMPONENT aServiceComponent = new ASERVICE_COMPONENT(true); Any any = ORB.init().create_any(); ASERVICE_COMPONENTHelper.insert(any, aServiceComponent); byte[] value = null; try { value = codec.encode_value(any); } catch (InvalidTypeForEncoding e) { System.out.println("Exception handling not shown."); } TaggedComponent taggedComponent = new TaggedComponent(TAG_ASERVICE_COMPONENT.value, value); info.add_ior_component(taggedComponent); } }
ArbitaryObjectImpl.java
This file is an implementation and server for the ArbitraryObject IDL interface. The implementations of the IDL interface operations explicitly call the AServiceImpl.verify() method to illustrate the end-to-end passing of data from the client (via AService.begin()) to the servant.
// ArbitaryObjectImpl.java // Copyright and License package pi.serviceexample; import org.omg.CORBA.ORB; import org.omg.CORBA.ORBPackage.InvalidName; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.PortableServer.POA; import java.util.Properties; class ArbitraryObjectImpl extends ArbitraryObjectPOA { public static ORB orb; private AService aService; // // The IDL operations. // public String arbitraryOperation1(String a1) { verifyService(); return "I got this from the client: " + a1; } public void arbitraryOperation2 (int a1) { verifyService(); } public void arbitraryOperation3(String a1) throws ArbitraryObjectException { verifyService(); if (a1.equals("throw exception")) { throw new ArbitraryObjectException("because you told me to"); } } private void verifyService() { getAService().verify(); } private AService getAService() { // Only look up the service once, then cache it. if (aService == null) { try { aService = AServiceHelper.narrow( orb.resolve_initial_references("AService")); } catch (InvalidName e) { System.out.println("Exception handling not shown."); } } return aService; } // // The server. // public static void main(String[] av) { try { if (orb == null) { Properties props = new Properties(); props.put("org.omg.PortableInterceptor.ORBInitializerClass." + "pi.serviceexample.AServiceORBInitializer", ""); props.put("org.omg.PortableInterceptor.ORBInitializerClass." + "pi.serviceexample.LoggingServiceServerORBInitializer", ""); orb = ORB.init(av, props); } POA rootPOA = POAHelper.narrow( orb.resolve_initial_references("RootPOA")); // Create a POA so the IOR interceptor executes. POA childPOA = rootPOA.create_POA("childPOA", null, null); childPOA.the_POAManager().activate(); byte[] objectId = childPOA.activate_object(new ArbitraryObjectImpl()); org.omg.CORBA.Object ref = childPOA.id_to_reference(objectId); NamingContext nameService = NamingContextHelper.narrow( orb.resolve_initial_references("NameService")); NameComponent path[] = { new NameComponent("ArbitraryObject", "") }; nameService.rebind(path, ref); System.out.println("ArbitaryObject ready."); orb.run(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } System.exit(0); } }
Client.java
This is a client that calls methods on ArbitraryObject. It makes some of those calls within the context of AService and some outside of its context. It is unaware of the existence of the logging interceptor (except that it explicitly registers the LoggingServerClientORBInitializer as noted above).
// Client.java // Copyright and License package pi.serviceexample; import org.omg.CORBA.ORB; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import java.util.Properties; public class Client { public static void main(String av[]) { try { Properties props = new Properties(); props.put("org.omg.PortableInterceptor.ORBInitializerClass." + "pi.serviceexample.AServiceORBInitializer", ""); props.put("org.omg.PortableInterceptor.ORBInitializerClass." + "pi.serviceexample.LoggingServiceClientORBInitializer", ""); ORB orb = ORB.init(av, props); // // The client obtains a reference to a service. // The client does not know the service is implemented // using interceptors. // AService aService = AServiceHelper.narrow( orb.resolve_initial_references("AService")); // // The client obtains a reference to some object that // it will invoke. // NamingContext nameService = NamingContextHelper.narrow( orb.resolve_initial_references("NameService")); NameComponent arbitraryObjectPath[] = { new NameComponent("ArbitraryObject", "") }; ArbitraryObject arbitraryObject = ArbitraryObjectHelper.narrow(nameService.resolve(arbitraryObjectPath)); // // The client begins the service so that invocations of // any object will be done with that service in effect. // aService.begin(); arbitraryObject.arbitraryOperation1("one"); arbitraryObject.arbitraryOperation2(2); // // The client ends the service so that further invocations // of any object will not be done with that service in effect. // aService.end(); // This invocation is not serviced by aService since // it is outside the begin/end. arbitraryObject.arbitraryOperation3("just return"); aService.begin(); try { arbitraryObject.arbitraryOperation3("throw exception"); throw new RuntimeException("should not see this"); } catch (ArbitraryObjectException e) { // Expected in this example, so do nothing. } aService.end(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } System.out.println("Client done."); System.exit(0); } }
ColocatedServers.java
This is a server which runs both ArbitraryObject and LoggingService in the same ORB. This means that these objects are colocated.
The server is created this way in order to exercise the code in LoggingServiceServerInterceptor that illustrates when interceptors make out calls to objects colocated in the same ORB extra steps must be taken to avoid infinite recursion.
// ColocatedServers.java // Copyright and License package pi.serviceexample; import org.omg.CORBA.ORB; import java.util.Properties; public class ColocatedServers { public static ORB orb; public static boolean colocatedBootstrapDone = false; public static void main (String[] av) { try { // // Share an ORB between objects servers. // Properties props = new Properties(); props.put("org.omg.PortableInterceptor.ORBInitializerClass." + "pi.serviceexample.AServiceORBInitializer", ""); props.put("org.omg.PortableInterceptor.ORBInitializerClass." + "pi.serviceexample.LoggingServiceServerORBInitializer", ""); ORB orb = ORB.init(av, props); ArbitraryObjectImpl.orb = orb; LoggingServiceImpl.orb = orb; // // Start both object servers. // ServerThread ServerThread = new ServerThread(av); ServerThread.start(); ArbitraryObjectImpl.main(av); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } } class ServerThread extends Thread { String[] av; ServerThread (String[] av) { this.av = av; } public void run () { LoggingServiceImpl.main(av); } }
Compiling and running the application
To compile and run this application,
.
.
.
.
.
.
ORBInitInfo
Send questions or comments to: JavaIDL@eng.sun.com. |