Simon Laws wrote:
Hi Gang
I'm wondering how much work it would be to simply pass a generic context
object, which includes all the current messages involved in the
invocation and allow get/set objects as added states, through all
interceptors/handler and also inject it into component implementation if
requested. Wouldn't it be simpler conceptually?
I think that's the conclusion that I'm coming to also so instead of
(or as well as if we can't unpick it) having a ThreadMessageContext
have a ThreadContext that contains service message (and reference
message if required).
Regards
Simon
I'd prefer something like Raymond's proposal. Here's how I think it
would work in a bit more detail:
1. The beforeHandler for a service invocation Foo creates an object
containing information that it wants to make available to the
application Foo method. Let's suppose that this object is of
type com.myappl.MyInfo.
2. The handler calls a Tuscany API to add the MyInfo object to the
invocation context for request Foo. The invocation context is
similar to the thread message context but it has a different
lifecycle (see steps 6 and 10 below).
3. The application code uses the @Context annotation (or possibly the
JSR 250 @Resource annotation) on a field of type com.myappl.MyInfo.
4. When the component implementation instance is created, the Tuscany
runtime injects the MyInfo object from the invocation context.
Note: This doesn't work for multithreaded COMPOSITE-scoped component
implementations. Support for this could be provided by allowing
the injection of ThreadLocal<MyInfo> into the application code.
The Foo implementation method would call get() on the injected
ThreadLocal<MyInfo> object to access the MyInfo object belonging to
the currently executing thread.
5. The application implementation's Foo method can get data from the
injected MyInfo object and can also put data into the same
MyInfo object.
6. The application implementation's Foo method makes a reference
invocation Bar. This creates a new message context for Bar but
it doesn't change the invocation context.
7. The beforeHandler for the Bar reference invocation is called.
This calls a Tuscany API to get the MyInfo object out of the
Foo invocation context. This allows the handler to access data
that the application has put into the MyInfo object in step 5.
8. The Bar reference invocation returns and its afterHandler is called.
This handler has access to the Foo invocation context and the same
MyInfo object.
9. Eventually the Foo request completes and the afterHandler for the
Foo service invocation is called. This handler has access to
the Foo invocation context and the same MyInfo object.
10. On completion of the afterHandler for the Foo service invocation,
the MyInfo object is freed up for garbage collection.
I think this is lot cleaner than having a Tuscany-defined generic
context object containing all the message contents (inbound and outbound).
It allows the handlers to control exactly what information is made
available to application code, and it doesn't require application code
to reference a Tuscany-specific generic context class.
Simon