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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]






--


Stephen J. McConnell
mailto:[EMAIL PROTECTED]
http://www.osm.net




--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to