Previous | Table of Contents | Next |
A ServerRequestInterceptor
instance is registered with the ORB (see Section 21.7,
“Registering Interceptors,? on page 21-50). The ORB logically maintains an ordered
list of server-side Interceptors. The Interceptor list is traversed in order on the receiving interception points and in reverse
order on the sending interception points.
21.3.10.1 Server-side Flow Rules
The server-side flow rules are derived from the general flow rules (see Section 21.3.2,
“General Flow Rules,? on page 21-7).
• The starting interception point is receive_request_service_contexts; this interception point is called on any given request/reply sequence.
• The set of ending interception points is send_reply, send_exception, send_other. One and only one of these is called on any given request/reply sequence.
• The intermediate interception point is receive_request, which is called after receive_request_service_contexts and before an ending interception point.
• On an exception, receive_request may not be called.
• If and only if receive_request_service_contexts runs to completion is an ending interception point called.
21.3.10.2 Additional Server-side Details
If, during request processing, a request is canceled because of an ORB shutdown, send_exception is called with the system
exception BAD_INV_ORDER with a minor code of 4 (ORB has shutdown).
If a request is canceled for any other reason (for example, a GIOP cancel message has been received), send_exception is called
with the system exception TRANSIENT with a standard minor code of 3.
The following statement is made about the GIOP close connection message (CORBA v2.3 15-45):
“If the ORB sending the CloseConnection is a server, or bidirectional GIOP is in use, the sending ORB must not currently be
processing any Requests from the other side.?
With respect to portable Interceptors, “...processing any Requests...? means that receive_request_service_contexts has been
called on any Interceptor and no ending interception point has yet been invoked.
On oneway requests, there is no reply sent to the client; however, the target is called and the server can construct an empty
reply. Since closure is necessary, this reply is tracked and send_reply is called (unless an exception occurs, in which case
send_exception is called).
Asynchronous requests, from the server’s point of view, are just normal synchronous requests. Normal interception point flows
are followed.
If a POA and a servant locator are present, the order of their operations and interception points is:
1. ServerRequestInterceptor.receive_request_service_contexts;
2. ServantLocator.preinvoke;
3. ServerRequestInterceptor.receive_request
4. the operation
5. ServantLocator.postinvoke;
6. ServerRequestInterceptor send_reply, send_exception, or send_other.
preinvoke, the operation, and postinvoke are required to execute in the same thread
(see Section 11.3.7, “ServantLocator Interface,? on page 11-27). Since
receive_request occurs within this chain, receive_request shall also execute in the same thread.
postinvoke executes in the same thread as preinvoke in order for postinvoke to perform any necessary closure processing. Likewise,
the sending interception points (send_reply, send_exception, or send_other) shall also execute in the same thread.
21.3.10.3 Server-side Flow Examples
Given the server-side flow rules, here are some concrete examples.
For successful invocations, the chain of interception points, in order, is: receive_request_service_contexts, receive_request,
send_reply -a start point is followed by an intermediate point, which is followed by an end point.
For the following exception scenarios, assume we have Interceptors A, B, and C. On the receive interception points they are
called in the order A, B, C; on the send interception points they are called in the order C, B, A.
Scenario
An exception is raised by the target:
• A.receive_request_service_contexts is called;
• B.receive_request_service_contexts is called;
• C.receive_request_service_contexts is called;
• A.receive_request is called;
• B.receive_request is called;
• C.receive_request is called;
• C.send_exception is called;
• B.send_exception is called;
• A.send_exception is called.In this scenario you can see that the flow for each Interceptor follows the rules. The chain for all is: receive_request_service_contexts, receive_request,
send_exception - a start point is followed by an intermediate point that is followed by an end point.
Scenario
B.receive_request_service_contexts raises an exception:
• A.receive_request_service_contexts is called;
• B.receive_request_service_contexts is called and raises an exception;
• A.send_exception is called.;
In this scenario you can see that the flow for each Interceptor follows the rules:
• The flow for A is receive_request_service_contexts followed by send_exception - a start point followed by an end point, no intermediate points are called.
• The flow for B is receive_request_service_contexts - a start point did not complete, so no end point was called; B raised the exception, so there is no need to tell it that the exception occurred.
• The flow for C is non-existent since the exception occurred before any of C’s interception points were invoked.
Scenario
B.receive_request raises an exception:
• A.receive_request_service_contexts is called;
• B.receive_request_service_contexts is called;
• C.receive_request_service_contexts is called;
• A.receive_request is called;
• B.receive_request is called and raises an exception;
• C.send_exception is called;
• B.send_exception is called;
• A.send_exception is called.
In this scenario you can see that the flow for each Interceptor follows the rules:
• Since the receive_request_service_contexts starting point ran to completion then, no matter what happens in intermediate
points, a “terminating? interception point must be called for all interceptors.
Scenario
The target invocation returns successfully, but B.send_reply raises an exception:
• A.receive_request_service_contexts is called;
• B.receive_request_service_contexts is called;
• C.receive_request_service_contexts is called;
• A.receive_request is called;
• B.receive_request is called;
• C.receive_request is called;
• C.send_reply is called;
• B.send_reply is called and raises an exception;
• A.send_exception is called.
In this scenario you can see that the flow for each Interceptor follows the rules:
• The flow for A is: receive_request_service_contexts, receive_request, send_exception - a start point is followed by an intermediate point that is followed by an end point.
• The flow for B is receive_request_service_contexts, receive_request, send_reply - a start point is followed by intermediate point, which is followed by an end point.
• The flow for C is: receive_request_service_contexts, receive_request, send_reply - a start point is followed by an intermediate point which is followed by an end point.
The scenario for B raising an exception at send_other is similar to the scenario where B raises an exception at send_reply.
Scenario
An exception X is raised by the target, but B.send_exception changes the exception to Y:
• A.receive_request_service_contexts is called;
• B.receive_request_service_contexts is called;
• C.receive_request_service_contexts is called;
• A.receive_request is called;
• B.receive_request is called;
• C.receive_request is called;
• C.send_exception is called with X;
• B.send_exception is called with X, raises Y;
• A.send_exception is called with Y.
In this scenario, the flow for all Interceptors is receive_request_service_contexts, receive_request, send_exception - a start
point is followed by an intermediate point, which is followed by an end point; Interceptor A is handed exception Y while the
B and C are handed exception X.