Based on the groundwork we already established in the earlier steps, the above implementation is quite straightforward. One thing you must note is the exception-processing logic. Considering transaction-context propagation is mainly one-way and request context is more important, for simplicity, we don't piggyback the client-side service context in the response message, which is the return value of the
invoke() method. However, adding the response service-context support does not require much work, so I leave this task to you.
The final design is shown in Figure 5.
I'd like to return to the
ServiceInterceptorInterface interfaces as an approach for eliminating the coupling with the server-side
ServiceInterface implementations. A dynamic server-side skeleton interceptor could also be used for the same purpose. However, I consider server-side transparency to be less significant than on the client-side, and to increase runtime efficiency and reduce deployment overhead, I chose this simpler approach.
However, my decoupling approach does incur some coding cost, mainly due to the JDK 1.4 rmic bug (bug-id: 5002152, reported by the author). When RMI/IIOP (
rmic -iiop) is used, the
ServiceInterceptorRemoteInterface interface must be redeclared for each subclass of the
Service class. In some cases, this may cause problems, for instance, when the source code of the specialized
Service implementation is not available. This bug does not apply to RMI/JRMP.
The performance costs mainly come from reflection, both on the client and server sides:
- Dynamic proxy creation for the interceptor on the client side—this is a one-time cost
- Cost associated with dynamic proxy invocation handler implementation on the client side
- Reflection cost for identifying the target method on the server side
- Marshaling cost for passing argument type names
Costs related to the service-context propagation function itself are not included. From the above analysis, we can see that the costs are mostly decided by the class signature, the number of overloaded methods, the target method signature, and the number of arguments. In other words, the total cost is static and does not depend on the size of instance data passed as arguments in the runtime, as opposed to RMI marshaling costs on the IIOP or JRMP layers. In most cases, the performance overhead is negligible, especially considering the overhead of RMI marshaling (let alone the IIOP marshaling).
Some simple measurements show that on a standard PC environment, with JDK 1.4, the RMI invocation overhead will be less than 5 ms for methods that have at least two arguments and two overloaded variants. In reality, the average overhead could be lower. I don't have any performance numbers for the equivalent cost associated with IIOP service-context propagation. Regardless, it will be much smaller than the cost of argument data marshaling.
You've been presented with some ways that RMI can be extended to meet the challenging design requirements we face in building today's distributed applications. The common concepts of service context and interceptor were illustrated to establish the high-level application context.
Many other items remain to be explored, such as a local method-invocation interceptor at the component level, a deployment strategy for registering, loading, configuring, and controlling service-specific interceptors, as well as further API-level abstraction. With all these further developments, the solution presented in this article can be easily made into a ready-to-use framework component.
Learn more about this topic
- Download the source code that accompanies this article
- The CORBA specification documents on the CORBA architecture related to the portable interceptor
- Java Transaction Service (JTS) Specification on the transaction context API
- CORBA Transaction Service (OTS) Specification on the transaction context thread model
- "Explore the Dynamic Proxy API," Jeremy Blosser (JavaWorld, November 2000)
- IIOP CompleteUnderstanding CORBA and Middleware Interoperability, William Ruh, et al. (Addison Wesley, 2000; ISBN0201379252)
- J2SE Reflection documents
- For more articles on CORBA, browse the CORBA section of JavaWorld's Topical Index
- For more articles on RMI, browse the RMI/RMI-IIOP section of JavaWorld's Topical Index