Request context implementation.
Why a custom map?
The JAX-WS spec exposes properties as a
Map , but if we just use
an ordinary
HashMap for this, it doesn't work as fast as we'd like
it to be. Hence we have this class.
We expect the user to set a few properties and then use that same
setting to make a bunch of invocations. So we'd like to take some hit
when the user actually sets a property to do some computation,
then use that computed value during a method invocation again and again.
For this goal, we use
PropertySet and implement some properties
as virtual properties backed by methods. This allows us to do the computation
in the setter, and store it in a field.
These fields are used by
Stub.process to populate a
Packet .
How it works?
We make an assumption that a request context is mostly used to just
get and put values, not really for things like enumerating or size.
So we start by maintaining state as a combination of
RequestContext.others bag and strongly-typed fields. As long as the application uses
just
Map.put ,
Map.get , and
Map.putAll , we can
do things in this way. In this mode a
Map we return works as
a view into
RequestContext , and by itself it maintains no state.
If
RequestContext is in this mode, its state can be copied
efficiently into
Packet .
Once the application uses any other
Map method, we move to
the "fallback" mode, where the data is actually stored in a
HashMap ,
this is necessary for implementing the map interface contract correctly.
To be safe, once we fallback, we'll never come back to the efficient state.
Caution
Once we are in the fallback mode, none of the strongly typed field will
be used, and they may contain stale values. So the only method
the code outside this class can safely use is
RequestContext.copy() ,
RequestContext.fill(Packet) , and constructors. Do not access the strongly
typed fields nor
RequestContext.others directly.
author: Kohsuke Kawaguchi |