avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stephen McConnell <mcconn...@apache.org>
Subject Re: lifecycle questions
Date Fri, 14 Mar 2003 14:27:09 GMT


Jakob Praher wrote:

>hi Stephen,
>
>Am Don, 2003-03-13 um 14.20 schrieb Stephen McConnell:
>  
>
>>Jakob Praher wrote:
>>    
>>
>
>  
>
>>>What it lacks is the interception of calls from the client to the
>>>component, since, once the reference is out of the container, the
>>>container can't control the use (except in an micro kernel design, but
>>>that is suboptimial here).
>>>
>>>      
>>>
>>I personally don't see this as a problem. The lifecycle
>>interface deal with the defintion of the contract for an extension
>>implementation under the creation and access phases. The subject
>>of both of these phases is a component implementation and the
>>relationship between the container and extensions introduced into
>>the containement environment.
>>    
>>
>
>
>  
>
>> Things like interception of method
>>invocations is a seperate subject. For example, I use the
>>extensions to implement aspects of a system that are related to
>>deployment - I use interceptors for things like principal identity
>>propergation and establishment. The issues dealt with are quite
>>different.
>>    
>>
>Interesting - I wanted to use something like that in my last project.
>What are you using - javaassist or bcel or sth else?
>  
>

I'm using the IIOP interceptor architecture (CORBA etc.).  In this 
particular case the issues of transaction identifiers, pricipals 
identities etc. are all handled before the invocation is hitting the 
service.  The implementations of these interceptors leverage the Merlin 
framework in terms of interceptor establishment and dependency management.

>But seeing it as a black box, from a clients perspective, I mean from th
>e service consumer, that takes a component from the container and uses
>it, it does not matter where the added service is added, for instance
>transaction service - a client takes a component from the server and
>wants transaction support, but for transaction boundaries access/release
>boundaries are probably to coarse grained - how are you seeing it?
>I think it's all about adding services to components.
>  
>

I agree (its a black-box as far as the client is concerned).  The trick 
is to handle this is a manner that is easiy understood and manageable in 
an environment of complex components.  I do not believe that it is 
benefitial to take a "intercepts-equals-total-solution" approach (too 
much experience with interceptors to signup to that idea).

I think its more that just adding service to component.  The container 
is responsible for the establishment of the component - and using things 
like proxies, it possible to modify the behaviour on an invocation.  The 
questions concern the structure for declaring extensions to invocation 
semantics to a container - and doing that in a manner that is consitent 
across containers.

>  
>
>>>So the notion of a call interceptor get's introduced, the client get's a
>>>proxy back that intercepts the method call and does some extra magic. 
>>>
>>>      
>>>
>>Yes - possible (but in my opinion its orthoginal to the container
>>extension architecture).
>>    
>>
>by orthogonal you think it is independent of - or?
>  
>

I mean that the notion of introducing customization of the behaviour of 
a container is common to both the questions of lifecycle phase estansion 
and invocation interception policy extension.  However, the two concerns 
are very different in terms of the entry-point and time of existance. 
 Lifecycle extensions exist during deployment, decommissioning and 
requersts for instance creation and destruction.  The handling of 
interceptor policies is also an extension but it needs to be 
differentiated from lifecycle extension.  So - by orthogonal - I mean 
that both problems share comonality at some point - but they both deal 
with seperate problems.

>  
>
>>>To support proxies, as Leo pointed out, one could change the interface
>>>from
>>>
>>>void created( Object object, Context context )
>>>
>>>to 
>>>Object created( Object object, Context context )
>>>
>>>      
>>>
>>I'm still wondering about this. Guess I need to talk some more to Leo.
>>Suffice to say that I'm not convinced of the need for proxies during the
>>container side management phases. I have the impression that there is
>>mixup of concerns - lifecycle extensions are dealing with extension to
>>the deployment lifecycle which is a container concern unrelated to
>>extensions dealing with an invocation against a service.
>>    
>>
>
>Thinking about lifecycle I guess you are right - lifecycle means the
>lifespan of the object, which has not much to do with intercepting
>method calls, but one of the point is that the proxies must get
>introduced somewhere, since for interceptors to work the client should
>never receive a non proxy, so implementing this as special lifecycle
>extension would be convinient, since adding a proxy layer after object
>is created and *before* it is returned to the caller is afait a good
>place do it - where would you put it?
>

Thsi is somewhat container specific.  In the Merlin container - the 
Appliance is the source of a service. It uses a bunch of internal 
managers to establish the component (or non-component) representing the 
service instance. When you make a lookup invocation on the 
ServiceManager - the ServiceManager implementation is simply invoking 
resolve on the appliance and returning the result to the client.  The 
appliance has access to the object providing the service and all of its 
associated meta information and meta data.  If meta data were to include 
interception policy declarations. the appliace can use this information 
to establish an invocation handler (proxy).

>  
>
>  
>
>>>but what I am missing here is how to state which kind of aspect the
>>>object supports, for isntance, take the example of a componetn
>>>configuration with a "standardized" transaction support:
>>>
>>><component class="..." role="..." >
>>>  <ts:transaction-supported>auto</ts:transaction-supprted>
>>></component> 
>>>
>>>if you change the Method and add a configuration instance, or something
>>>like that, it would be much more interesting:
>>>
>>>Object created( Obejct object, Context context, Configuration config ) ;
>>>
>>>so you can transparently use a proxy to implement the invocation handler
>>>and *know* which kind of transaction logic should be used.
>>>(naive question: is this the kind of transaction demarcation support
>>>Peter asked?)
>>>
>>>      
>>>
>>Honestly I don't know what the Fortress implementation approach is to
>>configuration of a extension handler - however, I can explain why this
>>is not needed within Merlin. In the Merlin environment an extension
>>handler is a component and as such, it configured during its deployment.
>>Any supplementary information can be supplied to the handler using the
>>existing signature via the context argument.
>>    
>>
>
>I have worked much, albeit with the excalibur impl, yet, and must
>confess I haven't had the time to look into the details of merlin, I am
>looking forward to get my hands on that beast - so I used the
>configuration metaphor from excalibur here. 
>Your description of Merlin sounds interesting - is this the direciton
>which Avalon5 is taking?
>

Merlin makes extensive use of meta info and meta data.  Certainly a 
community based evolution of a common Avalon meta model is on the 
roadmap.  Once you establish that you eliminate a broad spectrum of 
incompatibility issues.  For example, Merlin provides support for both 
the Phoenix and Meta packages in terms of meta model - this is why 
Merlin can run Phoenix components.  With the establishment of a common 
meta model the container becomes academic - or more correctly - you 
select a container based on requires such as the ability to embed, 
functionality, utility, scalability, etc.  It this the direction that 
Avalon is going ? 

Yes.

>  
>
>>>I hope I have explained my ideas understandable, and bear with me since
>>>I am currently trying to get a handle on all of the AOP, Call
>>>interception things. As Leo pointed out the implementation of AOP in
>>>Java using bytecode transformation, custom proxies and the like is
>>>relatively easy and well documented, but for me it is sometimes hard to
>>>transform the topic to practical use, so any discussion is appreciated.
>>>
>>>      
>>>
>>Take a couple of example.
>>
>>Let's imagine I want to introduce a different initialize signature
>>into my component. Perhaps it takes a ServletConfig as an argument
>>and throws a ServletException. This is perfect case for use of the
>>lifecycle extensions package. In this scenario that handler could
>>be constructing the config instance - perhaps based on service that
>>the handler has acquired from its own dependencies. The handler
>>simply builds the config argument and applies this to the supplied
>>component. No need for proxies - good isolation of the extension
>>from the container - and clear separation of container / component
>>concerns between the extension handler and the target component.
>>
>>    
>>
>as you could write a custom Creator class that calls on that component,
>in the create method, 
>
>class MyCreator implements Creator {
>
>  ServletConfig servletConfig = ?;
>
>  public void created( Object object, Context context )
>  throws Exception {
>   
>    ((Foo )object).specialConfig( servletConfig ) ;
>  }
>
>  ...
>
>}
>
>is this right?
>

Yes.

>
>* where would you declare this lifecycle extensions then? (in the case
>of merlin, for instance ? )
>

There are two parts - the component and the handler.
The component declares the requirement for lifecycle stage interface
support as follows:

  <type>
    <!-- custom meta attributes go here -->
    <!-- logging, context and service depedencies go here -->
    <!-- services that the implementation provides go here -->
    <!-- lifecycle stage depedencies go here -->
    <stages>
      <stage type="org.apache.avalon.playground.Exploitable" />
      <stage type="org.apache.avalon.playground.Demonstratable"/>
    </stages>
  </type>

The above XML is contained in a file name <classname>.xinfo.  It is
the decklaration by a component implementation of its requirements
from a container.  In the case of lifecycle depedencies, this includes
the declaration of the interface that it implements that should be
considered as a deployment phase lifecycle stage.  The order of stage
declarations presented above determines the order in which these stages
are applied to the component.

The next aspect is the declaration of extension handling ability.  
Another component (the handler) is declared using the same meta info
model as you have seen above, but in this case, a component is declaring
that it is a handler for a particular lifecycle stage interface.

 <type>
    <!-- other stuff -->
    <!-- declaration of extension handling abilities -->
    <extensions>
      <extension type="org.apache.avalon.playground.Exploitable" />
    </extensions>
  </type>

Based on the <extensions> tag, the container can register this component
type as a condidate handler.  During the assembly phase, the container can
make assesment of all candidates capable of supporting the Exploitable
interface (in the case of multiple candidates, you can include you own
selection policy or you can let Merlin take care of this automatically).

During the deployment phase, Merlin will assembly and deploy the selected
handler and apply the handler to the deployment of the target component
implementation.

>
>* there must be a notion of lifecycle order - is this done asserted at
>registration ?
>

This is done in strinct accordance with the declarations by the 
component that is being handled.  In the above examples the Exploitable 
handler will be invoked ahead of the Demonstratable handler.

>[for instance the object might need the data from the servletConfig, for
>other initialisation work ]
>
>  
>
>>Another scenario - access control based on a principal identity.
>>This information is unavailable at deployment time. It's a runtime
>>concern. A proxy can intercept an invocation and do stuff like
>>unmarchal a principal identifier or whatever, pass the argument to
>>some code to handle the business logic (e.g. an access decision),
>>and then apply the invocation to the target. The extendibility
>>issue here concerns the ability to "plug-in" a handler for access
>>control which can be used by the proxy implementation. This is
>>where interceptor chains come into play.
>>
>>    
>>
>yep - the jboss people are doing this with jaas?
>
>  
>
>>In the Merlin environment the object that actually exposes a proxy
>>is the Appliance (a.k.a. the component deployment handler). An
>>appliance is a component and as such it can have multiple dependencies,
>>context, configuration, etc. This immediately eliminates a bunch of
>>classic problems related to intercept style management - namely the
>>ordering and synchronization of multiple interceptors. However - at
>>least in Merlin, there isn't a way for the container to acquire an
>>interceptor or interceptors without introducing a specialized
>>appliance (but its is an interesting through).
>>
>>    
>>
>
>ok. So you see the point of proxies and aspects therefore in the
>appliance "extension point" (using eclipse terms here ;-) ).
>
>Will be playing with merlin - sounds interesting.
>  
>

Lets us know how you find it - feedback is very highly appreciated.

Cheers, Steve.

>  
>
>>Cheers, Steve.
>>    
>>
>
>thanks for your insights,
>
> -- Jakob
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
>For additional commands, e-mail: dev-help@avalon.apache.org
>
>
>
>  
>

-- 

Stephen J. McConnell
mailto:mcconnell@apache.org
http://www.osm.net




---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Mime
View raw message