axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "James M Snell" <jasn...@us.ibm.com>
Subject Re: [Architecture Improvement] Handler lifecycle events and undo()
Date Fri, 14 Dec 2001 23:00:38 GMT
IF we were to follow through on this (not saying that we should, this is 
just a thought exercise at the moment), it would be quite easy for us to 
define lifecycle interfaces that could be implemented to do these types of 
things.  As you mention "Initializable" and "Disposable" could be two 
options.  We could even, at some point, define a "Transactional" interface 
that handles that functionality.  It would make the code more flexible 
that's for sure.  But it would require quite a bit more consideration as 
to whether or not we really want to go down that road.  I'd be all for 
exploring this in a post 1.0 release.  I'd say fix up undo() for now, 
leave init() and destroy() alone for 1.0.

- James M Snell/Fresno/IBM
    Web services architecture and strategy
    Internet Emerging Technologies, IBM
    544.9035 TIE line
    559.587.1233 Office
    919.486.0077 Voice Mail
    jasnell@us.ibm.com
=================================================================
Have I not commanded you?  Be strong and courageous.  Do not be terrified, 

do not be discouraged, for the Lord your God will be with you wherever you 
go.  
- Joshua 1:9

Please respond to axis-dev@xml.apache.org 
To:     axis-dev@xml.apache.org
cc: 
Subject:        Re: [Architecture Improvement] Handler lifecycle events and undo()



Sanjiva Weerawarana wrote:

> I'd like to see this taken further. Using your own argument Glynn,
> has anyone given a "*real*, non-fictional example" or where any
> of init()/destroy()/undo() is useful? If so keep them all (rename
> or do whatever; I don't care).
>
> If not, YAGNI.


Since we are talking about Lifecycle and Architecture, I have to pipe up 
;P

It is very important that architecture be consistent, and that the
method names be accurately named.  This reduces the learning curve.

Here is what the Avalon team has learned in respect to Lifecycle:

1) Not every component will need every lifecycle interface
2) A collection of components will more than likely need all lifecycle
    interfaces.  While it is rare for one component to use all of them,
    when you have a number of Components with different needs, each will
    use a different set--and eventually all lifecycle methods are needed.
3) Event based systems scale better than monolithic ones (i.e. SAX vs.
    DOM, non-blocking vs. blocking IO, event based architecture vs.
    thread per client architecture).

In order to address this, the Avalon team developed a set of interfaces
that handle different aspects of the lifecycle.  The lifecycle follows
a well defined path so as not to confuse people unnecessarily.

Many components have *real* needs to prepare itself before it can be
used.  Again, many components have real needs to release resources
when the component is no longer needed.  The Avalon interfaces for
these are Initializable and Disposable, and each have one method:

Initializable.initialize() throws Exception;
Disposable.dispose();

For instance, a Handler may have lookup data that it needs to obtain
outside of itself, and cannot get a reference to the required component
during construction.  This is quite common in environments that enforce
Inversion of Control.  Again, that lookup data will have to be released
properly when the Handler is no longer needed.

Regarding undo(), it is improperly named--but the concept is quite
necessary.  It is for transactional services.  If the service failed,
the handler needs to clean up resources from the transaction.  This does
not mean that the component/handler needs to release all resources--just
the ones from this transaction.

However, transactional services do require a more traditional commit/abort
cycle.

Getting back to the init()/destroy()/delete() functionality issues, it
is incorrect to force _all_ Handlers to define them.  A Handler's 
interface
should only support the methods required to *Handle* a request.  All other
methods that are sometimes required should be placed in other interfaces.

This approach allows the developer to separate the concern areas of his
specific handler.  The simplest Handlers will merely process information
on the fly with no lookup information required for operation.  More 
complex
handlers can add functionality as needed.  While this does add a little 
more
complexity to the Container for the Handlers, the complexity is easily
managed.  For example, with the three point "lifecycle" that Handlers have
hardcoded, during initialization, the Container tests all the Handlers if
they implement the Initializable interface and call the appropriate
method as needed.  During run time, all the Handlers are treated 
identically.
During tear down, the same idea happens with the Disposable interface
as what happened with the Initializable one.

This separation of concerns simplifies the system for the Handler writer.




It is something to consider....

--

"They that give up essential liberty to obtain a little temporary safety
  deserve neither liberty nor safety."
                 - Benjamin Franklin




Mime
View raw message