J2SE 1.4
breathes new life into the CORBA community, Part
4
Tutorial Details:
J2SE 1.4 breathes new life into the CORBA community, Part 4
J2SE 1.4 breathes new life into the CORBA community, Part 4
By: By Tarak Modi
Portable interceptors and the Interoperable Naming Service
n my series on enterprise CORBA development using J2SE (Java 2 Platform, Standard Edition) 1.4, Part 1 served as a gentle introduction to CORBA and J2SE 1.4's enterprise CORBA features. Parts 2 and 3 provided a thorough treatment of the Portable Object Adapter (POA) and its role in creating enterprise applications that perform and scale with CORBA. In this concluding article, I discuss portable interceptors and the Interoperable Naming Service (INS). Portable interceptors provide standard hooks into the ORB (object request broker) runtime and offer a mechanism for plugging in additional ORB behavior or even modifying existing ORB behavior. The Interoperable Naming Service (INS) is a URL-based naming system built on top of the CORBA Naming Service. It specifies a common bootstrap mechanism that lets applications share a common initial naming context across ORB vendor providers.
Read the whole series, "J2SE 1.4 Breathes New Life into the CORBA Community:"
Part 1: Get started developing enterprise CORBA applications with the latest version of J2SE
Part 2: Gain code portability with the Portable Object Adapter
Part 3: Create enterprise-level apps with the POA
Part 4: Portable interceptors and the Interoperable Naming Service
Portable interceptors
Portable interceptors are hooks into the ORB that allow ORB services to intercept, at well-defined points, the ORB's normal flow of execution. Two types of interceptors can be registered:
IORInterceptor : Sometimes, so the client's ORB service implementation will function properly, a portable ORB service implementation might need to add information describing the server's or object's ORB service-related capabilities to object references. The IORInterceptor and IORInfo interfaces support that functionality. The IORInterceptor establishes tagged components in the profiles within an interoperable object reference (IOR).
RequestInterceptor : A request interceptor intercepts 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 propagate between clients and servers. Request interceptors are primarily used for enabling ORB services to transfer context information between clients and servers. Two types of request interceptors exist:
A ClientRequestInterceptor intercepts the flow of a request/reply sequence through the ORB on the client side.
A ServerRequestInterceptor intercepts the flow of a request/reply sequence through the ORB on the server side.
The logging service
To show you how to use interceptors, I created a simple logging service based on request interceptors:
package hello;
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TCKind;
import org.omg.IOP.ServiceContext;
import org.omg.PortableInterceptor.*;
import org.omg.Dynamic.Parameter;
import java.util.logging.Logger;
public class LoggingServiceInterceptor extends org.omg.CORBA.LocalObject
implements ClientRequestInterceptor, ServerRequestInterceptor
{
private Current piCurrent;
private int outCallIndicatorSlotId;
private Logger logger = Logger.getLogger("hello.LoggingServiceInterceptor");
public LoggingServiceInterceptor(Current piCurrent, int outCallIndicatorSlotId)
{
this.piCurrent = piCurrent;
this.outCallIndicatorSlotId = outCallIndicatorSlotId;
}
public String name()
{
return "LoggingServiceInterceptor";
}
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");
}
// Server interceptor methods
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(RequestInfo ri, String point)
{
// IMPORTANT: Always set the TSC outcall 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 outcall 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)) {
logger.info(point + "::" + ri.request_id() + "::" + ri.operation());
}
} catch (InvalidSlot e) {
System.out.println("Exception handling not shown.");
}
}
}
The implementation is fairly straightforward. The LoggingServiceInterceptor class extends org.omg.CORBA.LocalObject to ensure that an instance of this class does not get marshalled, since an interceptor instance is intimately tied to the ORB with which it is registered. LoggingServiceInterceptor also implements the ClientRequestInterceptor and ServerRequestInterceptor interfaces, which indicate that both clients and servers can use the same logging service. All interface methods delegate the real work to the log() method, which logs a message using the J2SE 1.4 logging facility. Reading the comments, you see that I have done some extra work to avoid potential infinite recursion, in which the logging service keeps calling the log() method.
Register the logging service
The class ORBInitializer (actually a class that implements the ORBInitializer interface) facilitates interceptor registration and ORB initialization. As I mentioned before, interceptors are intended to be a means by which ORB services (such as the logging service created above) access ORB processing, thus effectively becoming part of the ORB. Therefore, by the time the init() method call on the ORB class returns an ORB instance, the interceptors have already been registered. It follows that interceptors cannot be registered with an ORB instance returned from the init() method call.
In J2SE 1.4, ORBInitializer s can be registered via Java ORB properties. The property names take the following form: org.omg.PortableInterceptor.ORBInitializerClass. , where is the string name of a class that implements org.omg.PortableInterceptor.ORBInitializer . Hence, to register an interceptor, create an associated ORBInitializer class that implements the ORBInitializer interface and register this initializer via a Java ORB property. One such initializer for the logging service is shown below:
package hello;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.PortableInterceptor.*;
import java.util.logging.Logger;
public class LoggingServiceORBInitializer extends org.omg.CORBA.LocalObject
implements org.omg.PortableInterceptor.ORBInitializer
{
public LoggingServiceORBInitializer()
{
Logger logger = Logger.getLogger("hello.LoggingServiceORBInitializer");
logger.info("LoggingServiceORBInitializer::Constructor called");
}
public void pre_init(ORBInitInfo info)
{
Logger logger = Logger.getLogger("hello.LoggingServiceORBInitializer");
logger.info("LoggingServiceORBInitializer::pre_init called");
}
public void post_init(ORBInitInfo info)
{
Logger logger = Logger.getLogger("hello.LoggingServiceORBInitializer");
logger.info("LoggingServiceORBInitializer::post_init called");
try {
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.
LoggingServiceInterceptor interceptor =
new LoggingServiceInterceptor(piCurrent, outCallIndicatorSlotId);
info.add_client_request_interceptor(interceptor);
info.add_server_request_interceptor(interceptor);
} catch (Throwable t) {
System.out.println("Exception handling not shown.");
}
}
}
During the ORB initialization (that is, the init() method call), the ORB runtime collects the ORB properties that begin with org.omg.PortableInterceptor.ORBInitializerClass ; each property's portion is extracted; an initializer object is instantiated with the string as its class name; and the pre_init() and post_init() methods are called on the initializer object. If any exceptions occur, the ORB ignores them and proceeds with further initialization.
To see the logging service in action, let's modify Part 1 's Hello World example so that it uses the logging service. You won't believe how easy this is. To run the hello server with the logging service installed as an interceptor, use the following command line:
java -Dorg.omg.PortableInterceptor.ORBInitializerClass.hello.LoggingServiceORBInitializer HelloServer -ORBInitialPort 1050 -ORBInitialHost localhost
Note that the only difference from the server command above and Part 1's equivalent command is the presence of a system pr
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: J2SE 1.4
breathes new life into the CORBA community, Part
4
View Tutorial: J2SE 1.4
breathes new life into the CORBA community, Part
4
Related
Tutorials:
RMI over IIOP -
JavaWorld
December 1999
RMI over IIOP -
JavaWorld
December 1999 |
Java security evolution
and concepts, Part 1: Security nuts and bolts - JavaWorld April
2000
Java security evolution
and concepts, Part 1: Security nuts and bolts - JavaWorld April
2000 |
Clean up your wire protocol with SOAP, Part 1 - JavaWorld March 2001
Clean up your wire protocol with SOAP, Part 1 - JavaWorld March 2001 |
Master Merlin's new I/O classes
Master Merlin's new I/O classes |
J2SE 1.4
premieres Java's assertion
capabilities, Part
1
J2SE 1.4
premieres Java's assertion
capabilities, Part
1 |
J2SE 1.4
premieres Java's
assertion capabilities, Part 2
J2SE 1.4
premieres Java's
assertion capabilities, Part 2 |
Java security evolution
and concepts, Part 5
Java security evolution
and concepts, Part 5 |
Rumble in the
jungle: J2EE versus .Net, Part
1
Rumble in the
jungle: J2EE versus .Net, Part
1 |
J2SE 1.4
breathes new life into the CORBA community, Part
1
J2SE 1.4
breathes new life into the CORBA community, Part
1 |
Business process
automation
made easy with
Java, Part 1
Business process
automation
made easy with
Java, Part 1 |
J2SE 1.4
breathes new life into the CORBA community, Part
2
J2SE 1.4
breathes new life into the CORBA community, Part
2 |
J2SE 1.4
breathes new life into the CORBA community, Part
3
J2SE 1.4
breathes new life into the CORBA community, Part
3 |
Check out three
collections libraries
Check out three
collections libraries |
Effort on the
edge, Part 1
Effort on the
edge, Part 1 |
J2SE 1.4
breathes new life into the CORBA community, Part
4
J2SE 1.4
breathes new life into the CORBA community, Part
4 |
Overcome J2SE
1.3-1.4 incompatibilities
Overcome J2SE
1.3-1.4 incompatibilities |
Apache Geronimo
Apache Geronimo
Welcome to Apache Geronimo, the J2EE server project of the Apache Software Foundation. Please help us make this a world class, certified J2EE container! |
Bridging the Gap: J2SE 5.0 Annotations
Bridging the Gap: J2SE 5.0 Annotations
It takes a long time for the Java community to fully absorb a major new JDK release; it seems to take about two more releases after a brand new version of the JDK before everything settles down. Application server v |
Network Programming with JavaTM 2 Platform, Standard Edition 1.4 (J2SETM)
This article provides an overview of the new features and enhancements in the Java 2 Platform, Standard Edition 1.4 (J2SE), and shows you how to use them effectively. |
Five Reasons to Move to the J2SE 5 Platform
Five important reasons to move to the Java 2 Platform, Standard Edition (J2SE platform) 5.0, supported by data and references to prove that the 5.0 release will reduce development and runtime costs. |
|
|
|