directory-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alex Karasulu <aok...@bellsouth.net>
Subject Re: [eve] merlin wrappers
Date Sun, 04 Jul 2004 02:03:27 GMT
On Fri, 2004-07-02 at 20:58, Stephen McConnell wrote:
> Alex Karasulu wrote:
> 
> > Vince, Steve,
> > 
> > <snip/>
> > 
> >>>We can still benefit from this to allow hot
> >>>swaping if the Avalon wrapper components are in separate jars.  Is this
> >>>a correct assumption?
> >>
> >>The avalon components "could" be in separate jars but they will be 
> >>sharing the jars containing the apis and pojos.  This means that the 
> >>only thing you gain is the ability to swap out the adapter (and I really 
> >>can;t see why that would be useful).
> > 
> > Not exactly.  Your adapter component, which from now on I'll just for
> > simplicity refer to as the adapter, may or may not use the default POJO
> > implementation.  The "adapter" may not be an adapter at all or may be an
> > adapter to a component implementation that is not the default POJO
> > implementation in the frontend.jar.  So the frontend.jar falls back to
> > being the api jar in situations where the default POJO is not being
> > used.
> > 
> > So the potential to swap out adapter components is still there.  One
> > version of the adapter may implement interface Foo, and it may wrap the
> > POJO Bar which implements Foo as well.  Another version of the adapter
> > may wrap another object of class Xyz which implements Foo.  So we can
> > swap out one component for the other and be ok hot swapping this way.
> > 
> > Effectively everything in the frontend.jar by containing POJO
> > implementations with their service interfaces is an API.  Because at the
> > end of the day the component developer chooses whether or not some
> > default implementation is worth using for them or not.  This API can be
> > used by anyone including us while writing wrappers for various
> > containers.  We may opt to use the default POJO provided if we want to
> > as a part of the API.  It is completely up to the framework specific
> > component developer.
> > 
> > 
> >>The main interest in hot-swapping is the ability to bring in a different 
> >>implementation and once established, re-sync a service to point to the 
> >>the new implementation (without taking down dependent services).  Merlin 
> > 
> > 
> > Not a problem at all.
> > 
> > 
> >>3.3.1-DEV provides support for the loading and unload of containers 
> >>dynamically, add, the ability to modify and remove component models 
> >>without a restart (there still of another layer needed to handle service 
> >>availability).
> > 
> > 
> > That's great and should be very exciting. 
> > 
> >>What this means is that we want to be able to swap out eve version X.Y 
> >>with eve X.Z - and that means demounting an implementation classloader 
> >>containing the pojo classes while maintaining the api classes in the 
> >>classloader (because these are referenced by consumers).
> > 
> > We can still have this by keeping a single frontend.jar with the service
> > interfaces, and their POJO implementations in the same jar.
> > 
> > 
> >>>The second thought was what the heck am I going to do with the different
> >>>conf/ directories I have for integration tests on the Merlin wrappers
> >>>using Merlin-Unit.  Right now having each component in its own project
> >>>makes it easy to have its separate conf/ directory to test the component
> >>>with.  The top level compoent for the frontend called the 'frontend
> >>>component' will have the final block.xml for the server's
> >>>configuration.  What are your opinions and thoughts here?  
> >>
> >>My current thinking is that we should structure thing as follows:
> >>
> >>    /frontend
> >>       /api <------ * absolutely minimal external dependencies
> >>                    * interface, exceptions
> >>                    * immutable data objects
> >>       /impl <----- * pojos, implementation classes, resources
> >>       /merlin <--- * definition of a container that exports
> >>                      services exposed by the api and handles
> >>                      deployment based on internal component
> >>                      definitions
> >>
> >> From the point of view of a classloader what this means is:
> >>
> >>     |-------------------------|
> >>     | eve api                 |
> >>     |-------------------------|
> >>     | merlin adapter          |
> >>     |-------------------------|
> >>     | eve impl                |
> >>     |-------------------------|
> >>
> >>WDYT?
> > 
> > 
> > This does look rather nice.  I especially like the part about the api
> > jar having minimal dependencies.  However I don't think this outwieghs
> > at least in my mind the points I've made above.
> 
> If that doesn't - the following will.
> 
> Generally speaking - a good API does not expose dependencies on other 
> libraries.  

Yes this is a good point.

> Inversely - and implementation can go to town and use 
> whatever it needs.  The issue is that you don't control the classloader 
> your running within.  

Are you referring to your ClassLoader or the parent ClassLoader? Or
both?

> This has some very heavy implications.  Assume for 
> a moment that you expose commons lang 2.0 and avalon framework 4.1.5 as 
> part of your API.  Let's also assume that (a) your running as an 
> embedded component inside another system that you know nothing about - 
> and lets assume that the embedder is running framework 4.2, secondly, 
> lets assume that your running a plugin of some kind inside eve that 
> assumes commons lang 1.0.

So for fun we presume our eve-frontend jar contains the classes in 
commons-lang-2.0.jar and avalon-framework-4.1.5.jar "as part of [our]
API".  I'm presuming that you're stating this to simply discuss this
matter but you are not really thinking of doing this right.  Normally we
would have dependencies on these jars.  But for now I'll try to follow
this hypothetical case.

Going on the "embedder", which is the application setting up Eve and
loading the eve-frontend.jar via some ClassLoader.  This application's
ClassLoader which is the parent of the ClassLoader with
eve-frontend.jar, has avalon-framework-4.2.jar loaded into it.  So we
have the following situation:

           Embeddor
 +------ ClassLoader -------+
 | avalon-framework-4.2.jar |
 +--------------------------+
               |
               V
    (assembled by Embeddor)
              Eve
+-------- ClassLoader --------+
| avalon-framework-4.1.5.jar  |
|    commons-lang-2.0.jar     |
+-----------------------------+
               |
               V
      (assembled by Eve)
            Pluggin
+-------- ClassLoader --------+
|    commons-lang-1.0.jar     |
+-----------------------------+

So is this the ClassLoader chain that you're referring to just to be on
base? 

> OK - so a runtime - you implementation classes will never see framework 
> 4.1.5 because the 4.2 classes are in a parent classloader - 

Yep after looking at the docs for a ClassLoader and a few questions
answered by Noel I would agree.  The classes within "Eve ClassLoader"
above will first see the 4.2 avalon classes before they see the 4.1.5
classes.  These classes will only see 4.1.5 classes that are not part of
the 4.2 jar file perhaps resulting in some really nasty side effects.

> which means 
> that potential differences may exist (e.g. bug fixes in 4.2 over 4.1.5 
> that may create a side effect you never tested for) - but also at the 
> other end of the spectrum - the plugin your running is assuming commons 
> lang 1.0 has been subverted by eve because eve is assuming 2.0 and even 
> worse - if the plugin also assumes framework 4.1.5 its also being 
> subverted by the system containing eve. And throw into this any classes 
> in the containers bootstrap classloader (which again is totally outside 
> of your control).

Ok I totally agree with you.

> But it gets worse - if you expose a bunch of external classes in you API 
> - it's like getting married to all of them collectively (including all 
> of the api exposed by the apis your exposing and the api exposed by the 
> dependent apis).  I.e. it's like getting married concurrently, paying 
> alimony up-front, and no honeymoon.

ROTFL - I love your analogies btw!  Yes I'm seeing the picture here.

> This is all simply due to the fact the the JVM goes hunting for classes 
> up the classloader chain before looking locally (for reasons of 
> security).  That's means that you loose the contract of assured 
> computation integrity the moment you expose something.  And this 
> situation will not change until the java language introduced version at 
> the level of classes and interfaces (and that's not going to happen 
> anytime soon).
> 
> But there is a solutions ..
> 
>    |------------------------------------|
>    | API - minimize risk by             |
>    | minimizing dependencies - i.e.     |
>    | don't let the embedding context    |
>    | screw up your assumptions          |
>    |------------------------------------|

You're absolutely right.  I made the mistake of thinking you were wrong
- my bad.

> The API should deal with the challenge of providing adequate 
> functionality while at the same time minimizing the risk resulting from 
> exposure.  One way of dealing with the dilemma is to break an API into a 
> API/SPI pair (which I'm not advocating for eve at this time).  Typically 
> the API is there for the mainstream users but the SPI provides a richer 
> set of interfaces dealing with perhaps privileged functionality such as 
> management and/or sub-system replacement.  For example - the Merlin 
> system can be view in terms of its API, SPI and Implementation:
> 
> http://www.apache.org/~mcconnell/site/products/runtime/javadoc/index.html
> 
> If you look at the three links referenced by the above page - you will 
> see a distinct difference between the three levels ... but most 
> importantly, the only non-Avalon dependency in the entire API/SPI suite 
> is the JRE.  This means that the risk of conflicts are significantly 
> reduced. The same applies to the James Mailet API - zero dependencies on 
> anything other than James defined interfaces and the Java runtime.

So my API should not have any common jar dependencies in that case -
oops that's not going to be the case if I mix the service interfaces and
the pojo implementation classes in this one eve-frontend-XX.XX.XX.jar. 
This will pose serious issues if I wanted to embed into Tomcat then.

> So - expanding my earlier picture a little bit ...
> 
>       |-------------------------|
>       | eve api                 |
>       |-------------------------|
>              ^
>              | publishes services into
>              | a foreign and hostile environment
>              |
>       |-------------------------|
>       | merlin adapter          |
>       |-------------------------|
>              |
>              | establishes, isolates,
>              | protects, modifies, evolves,
>              | replaces, terminates,
>              | etc.
>              V
>       |-------------------------|
>       | eve impl                |
>       |-------------------------|
> 
> 
> > Although this does not look as well structured I'm leaning more towards
> > the following:
> > 
> > /frontend
> > /merlin
> > 
> > This makes me feel like I'm bouncing between extremes.
> 
> Doing a API/IMP separation with an adapter in-between is IMO a 
> conservative strategy that achieves the goal of simple structure while 
> maintaining integrity.

Done!

> My 0.02.

You're two cents will save much more down the road.  We'll be separating
things out into a API jar and a pojo implementation jar.  If I ever have
any doubts again I will reread this email over and over again.

Thank you sir,
Alex



Mime
View raw message