axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ann Robinson <robins...@us.ibm.com>
Subject Re: [AXIS2] Proposal for saving the message context
Date Fri, 22 Dec 2006 23:46:39 GMT

Sanjiva,
My apologies for the extra long note. I am trying to address a number of
points.

On Thu, 12-21-2006, Sanjiva Weerawarana wrote:
> As far as I can see none of this data is private to a message context;
> so the answer to the question I asked earlier appears to be that this
> code can perfectly well live in a utility class.
> [...]
> I'm confused. What do you mean by existing objects? A particular message
> exchange lives within a particular service context. You can't just put
> it back into some exiting object; it must go back into the corresponding
> service context etc.. is that what you mean? If so how do you record the
> ID of the service context object? Two different message contexts saved
> during two save actions could refer to the same service context with
> different state values of course.
> [...]
> Absolutely. As I stated earlier, there's nothing wrong with providing
> hooks that help people who build on top of Axis2. However, the concern I
> have with this proposal is that its being proposed at a generic level
> when what appears to be needed is a solution that works within the
> constrained world of WS-RM. Unless I missed something, this same
> proposal can live just fine as FooUtil.writeObject (MC, ..) instead of
> mc.writeObject (..). I'd like an answer on why that's not possible.

It is a generally accepted programming practice that an object in an
object-oriented
implementation encapsulates data and function and is responsible for its
own state.
One of the benefits in following object-oriented programming practices is
allowing
the object to evolve without necessarily having to change other parts of
the program.
Having said that, using a utilily class to introduce a new feature is a
quick way
to provide the new function, especially in the case of older-style
programs, as long as the
limitations of that design are acceptable. In this case, however, I think
that a utility class
is not the best approach.  In order to save/restore state of another class,
a utility class
requires access to the internal data of the other class.  As the other
class evolves and
is changed, the utility class needs to stay in sync with those changes.
Also, no state
information in the other class can ever be private because of the need to
have public
accessors to the information.  And, in the specific case of the message
context object graph,
unless you want the utility class to have detailed knowledege of the object
graph linkages
(and would need to stay in sync with any changes to object references among
the object graph),
you would need a set of utility classes where you could match a utility
class to an object.
Also, a general practice to use when saving/restoring information is to use
revision IDs
to identify the level of the data that been's saved versus the level of the
data that's
needed when being restored.  For example, let's say a message context was
saved on one engine
that was an older version of AXIS2 and is restored on an engine that is a
newer version of
AXIS2.  In theory, the revision IDs help to identify this situation so that
perhaps default
settings can be used for newer fields.  In the case of a utility class, I'm
also not sure
how you would manage the revision IDs across the many objects involved in
the message context
object graph.


A message context actually respresents a complex object graph where the
primary objects
in the object graph are:
- the message context
- the operation context
- the service context
- the service group context
- the configuration context
- the axis configuration
- the axis service group
- the axis service
- the axis operation

The axis objects represent configuration and deployment, so one way to
reduce the amount
of data needed to be saved is to limit the message context save/restore to
servers that
have the same configuration and deployed services.  As long as the axis
objects have
some form of identity (like names or QNames), then it is possible to locate
axis
objects on different servers that correspond to each other.

The context objects represent runtime data, so it is important to gather
state
information on **each** of these objects. These objects also have identity
or names
associated with them.

Here is a description of how the message context save/restore proposal
works.

1. The saving of the message context is initiated by writing the message
context to an
   output stream.

    // attach a stream capable of writing objects to the output stream
    ObjectOutputStream outObjStream = new ObjectOutputStream(outStream);
    // save the message context
    outObjStream.writeObject(messageContext);

2. This causes the MessageContext.writeExternal(ObjectOutput out) method to
be invoked.

    This collects state information and writes it out to the output stream.
        - various flags
        - the message
        - where in the handler chain that the message context is executing
        - meta data about each handler
        - meta data about the inbound executed phases
        - meta data about the outbound executed phases
        - the Options object (which has its own writeExternal() method)
        - meta data about the AxisOperation object
            (this is really the identification/name associated with the
object)
        - the OperationContext object (which has its own writeExternal()
method)
            (this requires some special handling because it contains a
table
             of associated MessageContext objects associated with labels
             like "In", "Out", "Fault")
        - meta data about the AxisService object (ie, ID/name)
        - the ServiceContext object (which has its own writeExternal()
method)
        - meta data about the AxisServiceGroup object (ie, ID/name)
        - the ServiceGroupContext object (which has its own writeExternal()
method)
        - meta data about the AxisMessage object
        - the SessionContext object (which has its own writeExternal()
method)
        - meta data about the transportIn object (ie, ID/name)
        - meta data about the transportOut object (ID/name)
        - handler self-managed data associated with this message context

    Objects which have their own writeExternal() methods customized what
state information
    about themselves that they save.  Care is also taken to not duplicate
objects.  For instance,
    the MessageContext object saves the OperationContext object and also
contains pointers
    to the ServiceContext object and ServiceGroupContext object, both of
which should be
    in the parentage of the OperationContext.  But the MessageContext
object defers the
    saving of the ServiceContext object to the OperationContext and defers
the saving of the
    ServiceGroupContext to the ServiceContext.


3. A restoring of a saved message context is initiated by reading the saved
information from
   an input stream.

   // attach a stream capable of reading objects from the input stream
   ObjectInputStream inObjStream = new ObjectInputStream(inStream);
   // restore the message context
   restoredMessageContext = (MessageContext) inObjStream.readObject();


4. This causes the MessageContext.readExternal(ObjectInput in) method to be
invoked.

    Previously saved information is read back in the same order as it was
saved.
        - various flags
        - the message
        - where in the handler chain that the message context is executing
        - meta data about each handler
        - meta data about the inbound executed phases
        - meta data about the outbound executed phases
        - the Options object (which has its own writeExternal() method)
        - meta data about the AxisOperation object
            (this is really the identification/name associated with the
object)
        - the OperationContext object (which has its own readExternal()
method)
        - meta data about the AxisService object (ie, ID/name)
        - the ServiceContext object (which has its own readExternal()
method)
        - meta data about the AxisServiceGroup object (ie, ID/name)
        - the ServiceGroupContext object (which has its own readExternal()
method)
        - meta data about the AxisMessage object
        - the SessionContext object (which has its own readExternal()
method)
        - meta data about the transportIn object (ie, ID/name)
        - meta data about the transportOut object (ID/name)
        - handler self-managed data associated with this message context

    This results in a collection of objects that has not yet been fully
re-connected
    into an object graph.

5. The next step is to activate the restored MessageContext in order to
match meta data (IDs/names)
   to existing objects.

       - First, Axis* objects are searched to locate objects that
correspond to the service that
         the message context belongs (AxisService, AxisServiceGroup,
AxisOperation, AxisMessage).

       - Then, the context-side of the object graph is restored.
           - The OperationContext checks to see if a ServiceContext object
exists on this engine
             that correponds to the desired service ID/name.  If so, the
properties from the
             saved ServiceContext are merged into the existing
ServiceContext. The existing
             ServiceContext object is used in the object graph instead of
the restored
             ServiceContext object.  In this case, this also means that
properties from the
             restored ServiceGroupContext object are merged into the
existing ServiceGroupContext
             object.
           - If existing context objects cannot be located, then the
restored objects are used
             and fully connected into the object graph.
             Note that the next restored message context that references
these context objects
             would be able to re-use them, instead of having unique copies.
This means that
             service-level properties affect all operations under that
service, but note that
             operation-level properties are not shared.


6. The result is a message context that has a fully populated object graph,
sharing objects as
   appropriate.  The AxisConfiguration, AxisServiceGroup, AxisService,
AxisOperation are
   re-used.  The ConfigurationContext is re-used.  The ServiceGroupContext
and ServiceContext
   are re-used only if the existing objects correspond to the IDs/names of
the ServiceGroupContext
   and ServiceContext objects from the engine where the message context was
saved.  The OperationContext
   is unique.  The MessageContext is unique.




Ann

WebSphere Development, Web Services Engine
IBM
Mime
View raw message