You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@geronimo.apache.org by Stephane Bailliez <sb...@apache.org> on 2005/06/14 17:18:43 UTC

ClassLoader Architecture

Hi all,

I'd like to clarify  a couple of points about the Geronimo ClassLoader 
architecture. I have had a discussion about it with Gianny Damour on 
IRC, so i'm bringing the discussion here to have some feedback about the 
existing implementation and my thoughts.

It looks like as of now the CL architecture is exposing its internal 
implementation to applications [1] if I'm reading correctly.

Say for example, if Geronimo is using component 1.x it will be visible 
to applications.

There are 2 aspects:

1. if the application uses component 2.x which is incompatible with 1.x 
you could then be in a blocker situation.

2. if the application incidentally forgets to ship with component 1.x, 
in a normal world, this would end up with a CNFE. In our case it would 
simply mask it to the user, actually run by accident..and may blow up 
later, say when upgrading the apps, or Geronimo.

3. some component unfortunately autoconfigure based on the presence or 
absence of another component (a good example is ActiveMQ autoconfiguring 
itself with derby persistence if available in the classpath). I don't 
like too much autoconfiguration, as it will often lead to problems 
later. The  rational being to put as little configuration as possible 
and thus forgetting to say 'even if you find that component don't do 
that, use this instead' (for activemq it would be explicity configuring 
vmpersistence). My rational is to avoid magic. A component should always 
start the same way.

To be more general:

In the OSS J2EE CL land, we have as of now 2 different hierarchies:

- JBoss with its Unified ClassLoader [2]
AFAIK what has been said publicly to defend this design was originally 
to 'please' users and to avoid them the dreaded ClassCast or 
ClassNotFound, VeryErrors,etc..... by stuffing as much components as 
they could find into a gigantic 'unified' pot. This led to a terrible 
thing which any serious user has been fighting against in 
production...not mentioning that classloader isolation settings have 
been changing between micro releases.

- JOnAS
It has a similar classloader hierarchy of Geronimo's [3] (or vice-versa) 
but is unfortunately exposing its implementation to applications. There 
is now a very serious problems with deployment of Hibernate based apps 
which use ASM and the ASM version used within JOnAS internals...which 
are incompatible.


Web applications (WARs) deployed in those J2EE containers generally can 
change the delegation model from the java2 delegation model (parent 
first) to a servlet 2.3+ model (current first), but this is insufficient 
in itself because it is only for the WAR part..you could very well have 
this problem in the EJB tiers .. so you need to be able to change the 
model type as well in the EJB tier.

Being able to change the delegation model of the EJB tiers of course 
does not prevent actually having the case described in (2) and (3) 
happening. Unless we can filter for sure what can be delegated which is 
not so straightforward to me.

Indeed, it does not mean filtering out to allow 'only' J2EE apis and 
implementation. In your app, you may perfectly need visibility of 
components located in the boostrap classpath or in jre/lib/ext (for 
example a crypto provider, etc...)

Shouldn't the classloader architecture have a child classloader to load 
internals (just like it does for the database driver)

Any thoughts on that ? I would really like to avoid having a release 
with a ClassLoader architecture that is already known to expose the 
users to some serious problems. Otherwise this may lead to tightly 
coupled components that will be very hard to decouple later (if not now).

Any comment is welcome.

Cheers,

Stephane


[1] http://chariotsolutions.com/geronimo/elements-classloaders.html
[2] http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassLoadingConfiguration
[3] http://www.redhat.com/docs/manuals/rhaps/jonas-guide/s1-conclusion.html


Re: ClassLoader Architecture

Posted by Stephane Bailliez <sb...@apache.org>.
Dain Sundstrom wrote:
> Stephane and I chatted about this on irc, so I wanted to post up the  
> notes.
> 
> The issues Stephane points are big deal.  This is a problem Paul  
> Hammant first pointed out to me a the last OSCon, and I have been  
> thinking about how to address for a while.  Of course I never brought  
> it up for discussion here :(

If that's of interest, I could certainly describe the problem on a wiki 
page so that there is something left behind. Folks who are interested in 
it, could possibly give their feedback.

> In the long run (for Geronimo 2.0), I'm currently leaning towards  using 
> OSGI to solve this problem.  OSGI is the framework that eclipse  plugins 
> use, and they have really solved the class loader problems.   This would 
> require a major architectural change so I don't think it  can be done in 
> 1.x.  For those of you that are interested, the  current OSGi r3 spec 
> chapter 4 describes the class loader  architecture.  The next yet to be 
> published r4 spec expands on the  model addressing some of the bad 
> assumptions (e.g., furure versions  of any library are backwards 
> compatible with all previous versions).

OK.

> In the short term, I like Stephane's idea of adding an optional child  
> first delegation class loader to applications (not just wep  
> application).  This would help applications avoid conflicts with  
> Geronimo system classes.  Anyone want to take a look at implementing  this?

Would you mind to actually give some pointers of the current 
architecture (ie modules and components) and event sequence concerning 
component loading so that people know where to start looking ?


Re: ClassLoader Architecture

Posted by Dain Sundstrom <da...@iq80.com>.
Paul,

I agree with you on the OSGi component model, which is why I don't  
want to use it.  I think we can bridge geronimo components into OSGi,  
but I wouldn't ask people to write to the spec.  I really only want  
to use their class loader architecture, because they have really  
solved the problems of this space.  Class worlds is a very good  
library, but I think OSGi is actually more powerful.  Anyway, the  
class loader model is something we're still experimenting with so  
OSGi may not be the final solution, it just looks really good right now.

-dain


On Jun 26, 2005, at 7:23 AM, Paul Hammant wrote:

> Dain,
>
> OSGi is a Dependency Lookup father than Dependency Injection form  
> of Inversion of control (running with the  the common mistake that  
> component assembly is what defines IoC, ignoring configuration  
> etc). I think the industry long term future is in Dependency  
> Injection, particularly CDI. That is for static languages like  
> Java. Experience gleaned from the worlds of Ruby and Python is that  
> component assembly issues are less of a problem there. I just don't  
> like OSGi and think even the original Avalon (Stefano's baby from  
> 1998 and onwards) has a better dependency lookup API.
>
> Anyway,  In the NanoContainer project we've always been pushing to  
> have hierarchies of components and containers that have class and  
> implementation visibilities sorted out. PicoContainer does not  
> provide any reflection-esque way of instantiating components.  
> NanoContainer (as well as many other things) wraps PicoContainer  
> and does do that. In the same timeline as this tread we wrote a  
> tiny boot class that allows for components in a tree to not even  
> see the classes for NanoContainer & Groovy (our preferred but not  
> mandated composition language)...
>
> Primordial--|
>             |--Boot
>             |
>             |
>             |--Pico--|--Nano, Groovy,
>                      |   ASM, CLI
>                      |
>                      |
>                      |--Common--|
>                           API   |--Comp A
>                                 |
>                                 |--Comp B
>
> Comp A and B (in separate classloaders) can see Common-API, which  
> can see the classloader that contains PicoContainer who's parent is  
> the classes in rt.jar
>
> On a separate branch, is the Boot classloader (once main() is  
> executed the thing plays no further part in the running of the  
> 'machine'). It creates NanoContainer and all the associated libs it  
> is going to use to create trees of comps, in one classloader giving  
> it PicoContainer (etc) as its parent classloader.
>
> Anyway, it works well and allows us to implement separations. It  
> also allows us to have say Component-B depend on Component-A  
> provided the type A implemented was in the Common-API classloader  
> or higher.
>
> Making this more complex is the need to depend on things not there  
> at boot time. We've experimented with the notion of hot deployment  
> (in MicroContainer as it happens), but we'll talk about the  
> mechanics here (not sell another product). A hypothetical Kernel  
> could be running is the same space as the Nano/Groovy thing, and  
> hot deploy (via some user action or archive dropped into a dir) a  
> component. The component could introduce a new thing for others to  
> avail of. For example, the component could be DefaultSpellChecker  
> and implement SpellChecker that it ships with. If the mechanism for  
> delivering the component allows for a diff jar each for interface  
> and implementaion, and the former was in some way marked, the  
> Kernel could take it and allow it to join the classloader at Common- 
> API level while mounting its implementation in a new classloader  
> alongside Comp-A and Comp-B.  This is a once off deal though. The  
> interface itself, once mounted cannot be replaced in that  
> classloader. So we gained late deploy and hot deploy via that. We  
> also have re-hot-deploy sorted via the same mechanism, but not if  
> the API changed.
>
> What clearly is not done via that mechanism is redeployment of a  
> second or superseding version of the same interface. This is  
> possible of course. Just it is pushed elsewhere I think.  Bob  
> McWhirter's and Jason van Zyl's ClassWorlds will do it. (directed/ 
> constrained graphs with selection package inheritance). Peter  
> Donald has something inside Loom that does it too called ClassMan.  
> With those and cunning use of some context during classloading, you  
> should be able to lace things correctly.
>
> Stick with DI lads - it has a rosy future...
>
> Incidentally we aim with NanoContainer to deliver whole  
> applications that leverage cherry picked components from projects  
> (Geronimo, Spring, Jetty, Hibernate etc). Composed like so :-
>
>   builder = NanoContainerBuilder()
>
>   parent = builder.container 
> (parent:parent,class:ImplementationHidingNanoPicoContainer) {
>       classpathelement(path:"lib/api.jar")
>       hidden() {
>           classpathelement(path:"lib/a.jar")
>           component(key:"A", class:"AImpl")
>       }
>       hidden() {
>           classpathelement(path:"lib/b.jar")
>           component(class:"BImpl")
>       }
>   }
>
> - Paul
>
>
> On Jun 16, 2005, at 2:00 PM, Dain Sundstrom wrote:
>
>> Stephane and I chatted about this on irc, so I wanted to post up  
>> the notes.
>>
>> The issues Stephane points are big deal.  This is a problem Paul  
>> Hammant first pointed out to me a the last OSCon, and I have been  
>> thinking about how to address for a while.  Of course I never  
>> brought it up for discussion here :(
>>
>> In the long run (for Geronimo 2.0), I'm currently leaning towards  
>> using OSGI to solve this problem.  OSGI is the framework that  
>> eclipse plugins use, and they have really solved the class loader  
>> problems.  This would require a major architectural change so I  
>> don't think it can be done in 1.x.  For those of you that are  
>> interested, the current OSGi r3 spec chapter 4 describes the class  
>> loader architecture.  The next yet to be published r4 spec expands  
>> on the model addressing some of the bad assumptions (e.g., furure  
>> versions of any library are backwards compatible with all previous  
>> versions).
>>
>> In the short term, I like Stephane's idea of adding an optional  
>> child first delegation class loader to applications (not just wep  
>> application).  This would help applications avoid conflicts with  
>> Geronimo system classes.  Anyone want to take a look at  
>> implementing this?
>>
>> -dain
>>
>> On Jun 14, 2005, at 8:18 AM, Stephane Bailliez wrote:
>>
>>
>>> Hi all,
>>>
>>> I'd like to clarify  a couple of points about the Geronimo  
>>> ClassLoader architecture. I have had a discussion about it with  
>>> Gianny Damour on IRC, so i'm bringing the discussion here to have  
>>> some feedback about the existing implementation and my thoughts.
>>>
>>> It looks like as of now the CL architecture is exposing its  
>>> internal implementation to applications [1] if I'm reading  
>>> correctly.
>>>
>>> Say for example, if Geronimo is using component 1.x it will be  
>>> visible to applications.
>>>
>>> There are 2 aspects:
>>>
>>> 1. if the application uses component 2.x which is incompatible  
>>> with 1.x you could then be in a blocker situation.
>>>
>>> 2. if the application incidentally forgets to ship with component  
>>> 1.x, in a normal world, this would end up with a CNFE. In our  
>>> case it would simply mask it to the user, actually run by  
>>> accident..and may blow up later, say when upgrading the apps, or  
>>> Geronimo.
>>>
>>> 3. some component unfortunately autoconfigure based on the  
>>> presence or absence of another component (a good example is  
>>> ActiveMQ autoconfiguring itself with derby persistence if  
>>> available in the classpath). I don't like too much  
>>> autoconfiguration, as it will often lead to problems later. The   
>>> rational being to put as little configuration as possible and  
>>> thus forgetting to say 'even if you find that component don't do  
>>> that, use this instead' (for activemq it would be explicity  
>>> configuring vmpersistence). My rational is to avoid magic. A  
>>> component should always start the same way.
>>>
>>> To be more general:
>>>
>>> In the OSS J2EE CL land, we have as of now 2 different hierarchies:
>>>
>>> - JBoss with its Unified ClassLoader [2]
>>> AFAIK what has been said publicly to defend this design was  
>>> originally to 'please' users and to avoid them the dreaded  
>>> ClassCast or ClassNotFound, VeryErrors,etc..... by stuffing as  
>>> much components as they could find into a gigantic 'unified' pot.  
>>> This led to a terrible thing which any serious user has been  
>>> fighting against in production...not mentioning that classloader  
>>> isolation settings have been changing between micro releases.
>>>
>>> - JOnAS
>>> It has a similar classloader hierarchy of Geronimo's [3] (or vice- 
>>> versa) but is unfortunately exposing its implementation to  
>>> applications. There is now a very serious problems with  
>>> deployment of Hibernate based apps which use ASM and the ASM  
>>> version used within JOnAS internals...which are incompatible.
>>>
>>>
>>> Web applications (WARs) deployed in those J2EE containers  
>>> generally can change the delegation model from the java2  
>>> delegation model (parent first) to a servlet 2.3+ model (current  
>>> first), but this is insufficient in itself because it is only for  
>>> the WAR part..you could very well have this problem in the EJB  
>>> tiers .. so you need to be able to change the model type as well  
>>> in the EJB tier.
>>>
>>> Being able to change the delegation model of the EJB tiers of  
>>> course does not prevent actually having the case described in (2)  
>>> and (3) happening. Unless we can filter for sure what can be  
>>> delegated which is not so straightforward to me.
>>>
>>> Indeed, it does not mean filtering out to allow 'only' J2EE apis  
>>> and implementation. In your app, you may perfectly need  
>>> visibility of components located in the boostrap classpath or in  
>>> jre/lib/ext (for example a crypto provider, etc...)
>>>
>>> Shouldn't the classloader architecture have a child classloader  
>>> to load internals (just like it does for the database driver)
>>>
>>> Any thoughts on that ? I would really like to avoid having a  
>>> release with a ClassLoader architecture that is already known to  
>>> expose the users to some serious problems. Otherwise this may  
>>> lead to tightly coupled components that will be very hard to  
>>> decouple later (if not now).
>>>
>>> Any comment is welcome.
>>>
>>> Cheers,
>>>
>>> Stephane
>>>
>>>
>>> [1] http://chariotsolutions.com/geronimo/elements-classloaders.html
>>> [2] http://wiki.jboss.org/wiki/Wiki.jsp? 
>>> page=ClassLoadingConfiguration
>>> [3] http://www.redhat.com/docs/manuals/rhaps/jonas-guide/s1- 
>>> conclusion.html
>>>
>>>
>>
>>
>


Re: [picocontainer-dev] Re: ClassLoader Architecture

Posted by Dain Sundstrom <da...@iq80.com>.
Rickard,

It's good to see you around here :)

It is going to take me a few days to digest this, especially  
considering I'm at JavaOne right now, but I was curious if you had  
looked at the OSGi spec.   I think they have captured most of these  
ideas in the spec, but as Paul points out they do it in a very  
"dependency lookup" style.  If you have read the spec, I'm curious  
what you think of their model in comparison to what you have shown here.

-dain

On Jun 26, 2005, at 11:04 PM, Rickard Öberg wrote:

> Jeremy Boynes wrote:
>
>> I would be very interested if you have the time.
>>
>
> Since you asked :-)
>
> There are a couple of issues I wanted to fix with such a scheme.
>
> First of all, a component should be able to expose an API, and only  
> that API should be exposed by the component. Other components  
> should not be able to access helper objects or components, and they  
> should not be able to cast the component to other interfaces than  
> what is explicitly exposed.
>
> Second, a component must be able to either use other API's exposed  
> by other components (trivial) *or* have an internal structure where  
> it hosts components as helpers, and which are not exposed to other  
> components. An example of the latter might be a DataSource that is  
> specific for a component and which should not be autowired into any  
> other component. A component should not "leak" by accident.
>
> Third, components must be lazy-loadable, yet eager-resolvable. Our  
> system is so large that starting up all components at startup-time  
> takes way too long. Components (or at least some) should be lazy- 
> loadable(/lazy-startable) upon the first call to any of the methods  
> in the exposed API.
>
> The basic approach is to use ContainerComposers (CC), which (IIRC)  
> is how MCA works as well. One component, one CC. I then have a base  
> class that allows me to do things like this:
> public class PortletContainerComponent
>    extends ComponentContainerComposer
> {
>    public void composeContainer(MutablePicoContainer parent, Object o)
>    {
>       MutablePicoContainer container = makeChildContainer(parent);
>
>       container.registerComponentImplementation 
> (PortletRegistryImpl.class);
>       container.registerComponentImplementation 
> (PortletDeployer.class);
> container.registerComponentImplementation 
> (TomcatJMXPortletDeployer.class);
>       container.registerComponentImplementation 
> (PortletRenderer.class);
>
>       register(PortletRegistry.class);
>       register(PortletRenderer.class);
>    }
> }
> ---
> A component using this approach always does three things:
> 1) set up a child container for the internal structure. Using  
> makeChildContainer() on the provided parent is the most common, but  
> it can be more complex if you want to.
> 2) configure the internal structure
> 3) expose the API, which will register the API in "parent"
>
> Requirement 1 and 3 above makes it necessary to introduce proxies  
> which can be eagerly resolved by other components without having to  
> have an actual backend component at the resolution time. This, of  
> course, also allows components to be passivated at any time if  
> necessary, but so far the lazy-start is the most important to me.  
> By using the implementation hiding component adapter it is also  
> ensured that only the API is exposed. For example, if the exposed  
> class PortletRegistryImpl implements Startable this is not visible  
> to "parent" above. Hence lifecycle events will only be executed in  
> the internal container. Creating and registering the proxy is done  
> in step 3) above.
>
> To allow for explicit lazy-loading of components I can do things  
> like this:
> public class SearchEngineComponent
>    extends ComponentContainerComposer
> {
>    public void composeContainer(MutablePicoContainer con, Object o)
>    {
>       MutablePicoContainer container = makeChildContainer(con,  
> LAZY_LOAD);
>       container.registerComponentImplementation 
> (SearchEngineImpl.class);
> container.registerComponentImplementation 
> (ClientSearchEngineImpl.class);
>
>       register(SearchEngine.class);
>       register(SearchIndex.class);
>       register(ClientSearch.class);
>    }
> }
> ---
> This will ensure that the objects in this component will only be  
> instantiated and started iff a method of the exposed API is called.  
> Lazy-loading can only be done if none of the objects start threads  
> or exposes some static methods that are not exposed through a Pico  
> API interface. For example, the above would be only half of the  
> search component in our system, with the indexing (having threads)  
> added like so:
> public class IndexingComponent
>    extends ComponentContainerComposer
> {
>    public void composeContainer(MutablePicoContainer con, Object o)
>    {
>       MutablePicoContainer container = makeChildContainer(con);
> container.registerComponentImplementation(SearchIndexOptimizer.class);
>       container.registerComponentImplementation 
> (IndexMaintainer.class);
> container.registerComponentImplementation 
> (IndexMaintainListener.class);
>       container.registerComponentImplementation(IndexRebuilder.class);
>
>       register(IndexRebuilder.class);
>       register(IndexMaintainer.class);
>    }
> }
> ---
> ... since IndexMaintainer uses threads and hence needs to be  
> started before anyone calls its API. These two together implement  
> the "search component" in our system:
> public class SearchComponent
>    extends ComponentContainerComposer
> {
>    public void composeContainer(MutablePicoContainer con, Object o)
>    {
>       new IndexingComponent().composeContainer(con, o);
>       new SearchEngineComponent().composeContainer(con, o);
>    }
> }
> ---
> Note that in this case the composer does not create a sub- 
> container, but instead composes itself directly using the other  
> composers. If it had created a new child container it would have to  
> explicitly register() the API of the child components in order to  
> "push" them upwards. This explicitness ensures that it is  
> impossible to accidentally access the internal structure of a  
> component.
>
> That's about it I think. Some implementation details in  
> ComponentContainerComposer, and there's no class loading going on  
> above (would be easy to add it though).
>
> Overall, this scheme should make it possible to have lots of  
> components, large components, composed components, expose what you  
> want, hide what you want, and yet be reasonably easy to understand  
> and use.
>
> Comments, thoughts, suggestions?
>
> /Rickard
>


Re: [picocontainer-dev] Re: ClassLoader Architecture

Posted by Rickard Öberg <ri...@senselogic.se>.
Jeremy Boynes wrote:
> I would be very interested if you have the time.

Since you asked :-)

There are a couple of issues I wanted to fix with such a scheme.

First of all, a component should be able to expose an API, and only that 
API should be exposed by the component. Other components should not be 
able to access helper objects or components, and they should not be able 
to cast the component to other interfaces than what is explicitly exposed.

Second, a component must be able to either use other API's exposed by 
other components (trivial) *or* have an internal structure where it 
hosts components as helpers, and which are not exposed to other 
components. An example of the latter might be a DataSource that is 
specific for a component and which should not be autowired into any 
other component. A component should not "leak" by accident.

Third, components must be lazy-loadable, yet eager-resolvable. Our 
system is so large that starting up all components at startup-time takes 
way too long. Components (or at least some) should be 
lazy-loadable(/lazy-startable) upon the first call to any of the methods 
in the exposed API.

The basic approach is to use ContainerComposers (CC), which (IIRC) is 
how MCA works as well. One component, one CC. I then have a base class 
that allows me to do things like this:
public class PortletContainerComponent
    extends ComponentContainerComposer
{
    public void composeContainer(MutablePicoContainer parent, Object o)
    {
       MutablePicoContainer container = makeChildContainer(parent);

       container.registerComponentImplementation(PortletRegistryImpl.class);
       container.registerComponentImplementation(PortletDeployer.class);
 
container.registerComponentImplementation(TomcatJMXPortletDeployer.class);
       container.registerComponentImplementation(PortletRenderer.class);

       register(PortletRegistry.class);
       register(PortletRenderer.class);
    }
}
---
A component using this approach always does three things:
1) set up a child container for the internal structure. Using 
makeChildContainer() on the provided parent is the most common, but it 
can be more complex if you want to.
2) configure the internal structure
3) expose the API, which will register the API in "parent"

Requirement 1 and 3 above makes it necessary to introduce proxies which 
can be eagerly resolved by other components without having to have an 
actual backend component at the resolution time. This, of course, also 
allows components to be passivated at any time if necessary, but so far 
the lazy-start is the most important to me. By using the implementation 
hiding component adapter it is also ensured that only the API is 
exposed. For example, if the exposed class PortletRegistryImpl 
implements Startable this is not visible to "parent" above. Hence 
lifecycle events will only be executed in the internal container. 
Creating and registering the proxy is done in step 3) above.

To allow for explicit lazy-loading of components I can do things like this:
public class SearchEngineComponent
    extends ComponentContainerComposer
{
    public void composeContainer(MutablePicoContainer con, Object o)
    {
       MutablePicoContainer container = makeChildContainer(con, LAZY_LOAD);
       container.registerComponentImplementation(SearchEngineImpl.class);
 
container.registerComponentImplementation(ClientSearchEngineImpl.class);

       register(SearchEngine.class);
       register(SearchIndex.class);
       register(ClientSearch.class);
    }
}
---
This will ensure that the objects in this component will only be 
instantiated and started iff a method of the exposed API is called. 
Lazy-loading can only be done if none of the objects start threads or 
exposes some static methods that are not exposed through a Pico API 
interface. For example, the above would be only half of the search 
component in our system, with the indexing (having threads) added like so:
public class IndexingComponent
    extends ComponentContainerComposer
{
    public void composeContainer(MutablePicoContainer con, Object o)
    {
       MutablePicoContainer container = makeChildContainer(con);
 
container.registerComponentImplementation(SearchIndexOptimizer.class);
       container.registerComponentImplementation(IndexMaintainer.class);
 
container.registerComponentImplementation(IndexMaintainListener.class);
       container.registerComponentImplementation(IndexRebuilder.class);

       register(IndexRebuilder.class);
       register(IndexMaintainer.class);
    }
}
---
... since IndexMaintainer uses threads and hence needs to be started 
before anyone calls its API. These two together implement the "search 
component" in our system:
public class SearchComponent
    extends ComponentContainerComposer
{
    public void composeContainer(MutablePicoContainer con, Object o)
    {
       new IndexingComponent().composeContainer(con, o);
       new SearchEngineComponent().composeContainer(con, o);
    }
}
---
Note that in this case the composer does not create a sub-container, but 
instead composes itself directly using the other composers. If it had 
created a new child container it would have to explicitly register() the 
API of the child components in order to "push" them upwards. This 
explicitness ensures that it is impossible to accidentally access the 
internal structure of a component.

That's about it I think. Some implementation details in 
ComponentContainerComposer, and there's no class loading going on above 
(would be easy to add it though).

Overall, this scheme should make it possible to have lots of components, 
large components, composed components, expose what you want, hide what 
you want, and yet be reasonably easy to understand and use.

Comments, thoughts, suggestions?

/Rickard


Re: [picocontainer-dev] Re: ClassLoader Architecture

Posted by Jeremy Boynes <jb...@apache.org>.
Rickard Öberg wrote:
> Paul Hammant wrote:
> 
>> Comp A and B (in separate classloaders) can see Common-API, which can 
>> see the classloader that contains PicoContainer who's parent is the 
>> classes in rt.jar
> 
> <snip>
> 
> One thing that I have whined about before, and I'm not sure whether it's 
> been fixed yet, is that a component A needs to be able to have an 
> internal structure (component!=1 object) and it needs to be able to 
> expose API implementations to other components without having to expose 
> its own internal structure. In the discussions so far I have not seen 
> mention of this problem (but maybe I have simply missed it).
> 

This is the role of a Configuration in Geronimo - to package together a 
pre-wired set of closely coupled GBeans and define the external 
interfaces (APIs/services offered, dependencies required). It is the 
Configurations themselves that are designed to be hot-swapped and not 
their constituents.

The implementation we have at this time is horribly naive contributing 
to the monolithic mess that is the J2EE Server configuration. Hopefully 
we can solve this sooner rather than later and avoid some of the less 
maintainable workarounds being considered.

> I have my own solution for fixing this, but I am wondering if a more 
> standard solution to this is available? (now or later) My own solution 
> is more of a best-practice use of Pico rather than an extension, and if 
> anyone is interested I can describe it in more detail.
> 

I would be very interested if you have the time.

> It really is a big big big issue once you get either loads of components 
> or large components. We have both cases in our system right now.
> 

Hear, hear - this is a big problem in Geronimo.

--
Jeremy

Re: [picocontainer-dev] Re: ClassLoader Architecture

Posted by Rickard Öberg <ri...@senselogic.se>.
Paul Hammant wrote:
> Comp A and B (in separate classloaders) can see Common-API, which can 
> see the classloader that contains PicoContainer who's parent is the 
> classes in rt.jar
<snip>

One thing that I have whined about before, and I'm not sure whether it's 
been fixed yet, is that a component A needs to be able to have an 
internal structure (component!=1 object) and it needs to be able to 
expose API implementations to other components without having to expose 
its own internal structure. In the discussions so far I have not seen 
mention of this problem (but maybe I have simply missed it).

I have my own solution for fixing this, but I am wondering if a more 
standard solution to this is available? (now or later) My own solution 
is more of a best-practice use of Pico rather than an extension, and if 
anyone is interested I can describe it in more detail.

It really is a big big big issue once you get either loads of components 
or large components. We have both cases in our system right now.

/Rickard

Re: ClassLoader Architecture

Posted by Paul Hammant <ha...@apache.org>.
Dain,

OSGi is a Dependency Lookup father than Dependency Injection form of  
Inversion of control (running with the  the common mistake that  
component assembly is what defines IoC, ignoring configuration etc).  
I think the industry long term future is in Dependency Injection,  
particularly CDI. That is for static languages like Java. Experience  
gleaned from the worlds of Ruby and Python is that component assembly  
issues are less of a problem there. I just don't like OSGi and think  
even the original Avalon (Stefano's baby from 1998 and onwards) has a  
better dependency lookup API.

Anyway,  In the NanoContainer project we've always been pushing to  
have hierarchies of components and containers that have class and  
implementation visibilities sorted out. PicoContainer does not  
provide any reflection-esque way of instantiating components.  
NanoContainer (as well as many other things) wraps PicoContainer and  
does do that. In the same timeline as this tread we wrote a tiny boot  
class that allows for components in a tree to not even see the  
classes for NanoContainer & Groovy (our preferred but not mandated  
composition language)...

Primordial--|
             |--Boot
             |
             |
             |--Pico--|--Nano, Groovy,
                      |   ASM, CLI
                      |
                      |
                      |--Common--|
                           API   |--Comp A
                                 |
                                 |--Comp B

Comp A and B (in separate classloaders) can see Common-API, which can  
see the classloader that contains PicoContainer who's parent is the  
classes in rt.jar

On a separate branch, is the Boot classloader (once main() is  
executed the thing plays no further part in the running of the  
'machine'). It creates NanoContainer and all the associated libs it  
is going to use to create trees of comps, in one classloader giving  
it PicoContainer (etc) as its parent classloader.

Anyway, it works well and allows us to implement separations. It also  
allows us to have say Component-B depend on Component-A provided the  
type A implemented was in the Common-API classloader or higher.

Making this more complex is the need to depend on things not there at  
boot time. We've experimented with the notion of hot deployment (in  
MicroContainer as it happens), but we'll talk about the mechanics  
here (not sell another product). A hypothetical Kernel could be  
running is the same space as the Nano/Groovy thing, and hot deploy  
(via some user action or archive dropped into a dir) a component. The  
component could introduce a new thing for others to avail of. For  
example, the component could be DefaultSpellChecker and implement  
SpellChecker that it ships with. If the mechanism for delivering the  
component allows for a diff jar each for interface and implementaion,  
and the former was in some way marked, the Kernel could take it and  
allow it to join the classloader at Common-API level while mounting  
its implementation in a new classloader alongside Comp-A and Comp-B.   
This is a once off deal though. The interface itself, once mounted  
cannot be replaced in that classloader. So we gained late deploy and  
hot deploy via that. We also have re-hot-deploy sorted via the same  
mechanism, but not if the API changed.

What clearly is not done via that mechanism is redeployment of a  
second or superseding version of the same interface. This is possible  
of course. Just it is pushed elsewhere I think.  Bob McWhirter's and  
Jason van Zyl's ClassWorlds will do it. (directed/constrained graphs  
with selection package inheritance). Peter Donald has something  
inside Loom that does it too called ClassMan. With those and cunning  
use of some context during classloading, you should be able to lace  
things correctly.

Stick with DI lads - it has a rosy future...

Incidentally we aim with NanoContainer to deliver whole applications  
that leverage cherry picked components from projects (Geronimo,  
Spring, Jetty, Hibernate etc). Composed like so :-

   builder = NanoContainerBuilder()

   parent = builder.container 
(parent:parent,class:ImplementationHidingNanoPicoContainer) {
       classpathelement(path:"lib/api.jar")
       hidden() {
           classpathelement(path:"lib/a.jar")
           component(key:"A", class:"AImpl")
       }
       hidden() {
           classpathelement(path:"lib/b.jar")
           component(class:"BImpl")
       }
   }

- Paul


On Jun 16, 2005, at 2:00 PM, Dain Sundstrom wrote:

> Stephane and I chatted about this on irc, so I wanted to post up  
> the notes.
>
> The issues Stephane points are big deal.  This is a problem Paul  
> Hammant first pointed out to me a the last OSCon, and I have been  
> thinking about how to address for a while.  Of course I never  
> brought it up for discussion here :(
>
> In the long run (for Geronimo 2.0), I'm currently leaning towards  
> using OSGI to solve this problem.  OSGI is the framework that  
> eclipse plugins use, and they have really solved the class loader  
> problems.  This would require a major architectural change so I  
> don't think it can be done in 1.x.  For those of you that are  
> interested, the current OSGi r3 spec chapter 4 describes the class  
> loader architecture.  The next yet to be published r4 spec expands  
> on the model addressing some of the bad assumptions (e.g., furure  
> versions of any library are backwards compatible with all previous  
> versions).
>
> In the short term, I like Stephane's idea of adding an optional  
> child first delegation class loader to applications (not just wep  
> application).  This would help applications avoid conflicts with  
> Geronimo system classes.  Anyone want to take a look at  
> implementing this?
>
> -dain
>
> On Jun 14, 2005, at 8:18 AM, Stephane Bailliez wrote:
>
>
>> Hi all,
>>
>> I'd like to clarify  a couple of points about the Geronimo  
>> ClassLoader architecture. I have had a discussion about it with  
>> Gianny Damour on IRC, so i'm bringing the discussion here to have  
>> some feedback about the existing implementation and my thoughts.
>>
>> It looks like as of now the CL architecture is exposing its  
>> internal implementation to applications [1] if I'm reading correctly.
>>
>> Say for example, if Geronimo is using component 1.x it will be  
>> visible to applications.
>>
>> There are 2 aspects:
>>
>> 1. if the application uses component 2.x which is incompatible  
>> with 1.x you could then be in a blocker situation.
>>
>> 2. if the application incidentally forgets to ship with component  
>> 1.x, in a normal world, this would end up with a CNFE. In our case  
>> it would simply mask it to the user, actually run by accident..and  
>> may blow up later, say when upgrading the apps, or Geronimo.
>>
>> 3. some component unfortunately autoconfigure based on the  
>> presence or absence of another component (a good example is  
>> ActiveMQ autoconfiguring itself with derby persistence if  
>> available in the classpath). I don't like too much  
>> autoconfiguration, as it will often lead to problems later. The   
>> rational being to put as little configuration as possible and thus  
>> forgetting to say 'even if you find that component don't do that,  
>> use this instead' (for activemq it would be explicity configuring  
>> vmpersistence). My rational is to avoid magic. A component should  
>> always start the same way.
>>
>> To be more general:
>>
>> In the OSS J2EE CL land, we have as of now 2 different hierarchies:
>>
>> - JBoss with its Unified ClassLoader [2]
>> AFAIK what has been said publicly to defend this design was  
>> originally to 'please' users and to avoid them the dreaded  
>> ClassCast or ClassNotFound, VeryErrors,etc..... by stuffing as  
>> much components as they could find into a gigantic 'unified' pot.  
>> This led to a terrible thing which any serious user has been  
>> fighting against in production...not mentioning that classloader  
>> isolation settings have been changing between micro releases.
>>
>> - JOnAS
>> It has a similar classloader hierarchy of Geronimo's [3] (or vice- 
>> versa) but is unfortunately exposing its implementation to  
>> applications. There is now a very serious problems with deployment  
>> of Hibernate based apps which use ASM and the ASM version used  
>> within JOnAS internals...which are incompatible.
>>
>>
>> Web applications (WARs) deployed in those J2EE containers  
>> generally can change the delegation model from the java2  
>> delegation model (parent first) to a servlet 2.3+ model (current  
>> first), but this is insufficient in itself because it is only for  
>> the WAR part..you could very well have this problem in the EJB  
>> tiers .. so you need to be able to change the model type as well  
>> in the EJB tier.
>>
>> Being able to change the delegation model of the EJB tiers of  
>> course does not prevent actually having the case described in (2)  
>> and (3) happening. Unless we can filter for sure what can be  
>> delegated which is not so straightforward to me.
>>
>> Indeed, it does not mean filtering out to allow 'only' J2EE apis  
>> and implementation. In your app, you may perfectly need visibility  
>> of components located in the boostrap classpath or in jre/lib/ext  
>> (for example a crypto provider, etc...)
>>
>> Shouldn't the classloader architecture have a child classloader to  
>> load internals (just like it does for the database driver)
>>
>> Any thoughts on that ? I would really like to avoid having a  
>> release with a ClassLoader architecture that is already known to  
>> expose the users to some serious problems. Otherwise this may lead  
>> to tightly coupled components that will be very hard to decouple  
>> later (if not now).
>>
>> Any comment is welcome.
>>
>> Cheers,
>>
>> Stephane
>>
>>
>> [1] http://chariotsolutions.com/geronimo/elements-classloaders.html
>> [2] http://wiki.jboss.org/wiki/Wiki.jsp? 
>> page=ClassLoadingConfiguration
>> [3] http://www.redhat.com/docs/manuals/rhaps/jonas-guide/s1- 
>> conclusion.html
>>
>>
>
>


Re: ClassLoader Architecture

Posted by Dain Sundstrom <da...@iq80.com>.
That's bound not to work with the current code.  I mean theoretically  
it should work, but I'd guess that a lot of code makes assumptions  
about the class loader hierarchy.  I think offering a child-first  
option would have a much smaller impact then reorganizing the class  
loader hierarchy.

-dain

On Jun 16, 2005, at 3:35 PM, Aaron Mulder wrote:

>     Can't we find a better way to segregate server classes?  You know,
> set up a path like (forgive my ASCII art):
>
>                         ,-- Geronimo Server
> system -- j2ee specs --/
>                        \------ App 1
>                         \----- App 2
>
>     I know that all the construction bits of the server would need to
> be on the server side of the fence, but I think we could throw apps  
> in an
> isolated CL that didn't have anything but the most common stuff like
> specs.
>
> Aaron
>
> On Thu, 16 Jun 2005, Dain Sundstrom wrote:
>
>
>> Stephane and I chatted about this on irc, so I wanted to post up the
>> notes.
>>
>> The issues Stephane points are big deal.  This is a problem Paul
>> Hammant first pointed out to me a the last OSCon, and I have been
>> thinking about how to address for a while.  Of course I never brought
>> it up for discussion here :(
>>
>> In the long run (for Geronimo 2.0), I'm currently leaning towards
>> using OSGI to solve this problem.  OSGI is the framework that eclipse
>> plugins use, and they have really solved the class loader problems.
>> This would require a major architectural change so I don't think it
>> can be done in 1.x.  For those of you that are interested, the
>> current OSGi r3 spec chapter 4 describes the class loader
>> architecture.  The next yet to be published r4 spec expands on the
>> model addressing some of the bad assumptions (e.g., furure versions
>> of any library are backwards compatible with all previous versions).
>>
>> In the short term, I like Stephane's idea of adding an optional child
>> first delegation class loader to applications (not just wep
>> application).  This would help applications avoid conflicts with
>> Geronimo system classes.  Anyone want to take a look at implementing
>> this?
>>
>> -dain
>>
>> On Jun 14, 2005, at 8:18 AM, Stephane Bailliez wrote:
>>
>>
>>> Hi all,
>>>
>>> I'd like to clarify  a couple of points about the Geronimo
>>> ClassLoader architecture. I have had a discussion about it with
>>> Gianny Damour on IRC, so i'm bringing the discussion here to have
>>> some feedback about the existing implementation and my thoughts.
>>>
>>> It looks like as of now the CL architecture is exposing its
>>> internal implementation to applications [1] if I'm reading  
>>> correctly.
>>>
>>> Say for example, if Geronimo is using component 1.x it will be
>>> visible to applications.
>>>
>>> There are 2 aspects:
>>>
>>> 1. if the application uses component 2.x which is incompatible with
>>> 1.x you could then be in a blocker situation.
>>>
>>> 2. if the application incidentally forgets to ship with component
>>> 1.x, in a normal world, this would end up with a CNFE. In our case
>>> it would simply mask it to the user, actually run by accident..and
>>> may blow up later, say when upgrading the apps, or Geronimo.
>>>
>>> 3. some component unfortunately autoconfigure based on the presence
>>> or absence of another component (a good example is ActiveMQ
>>> autoconfiguring itself with derby persistence if available in the
>>> classpath). I don't like too much autoconfiguration, as it will
>>> often lead to problems later. The  rational being to put as little
>>> configuration as possible and thus forgetting to say 'even if you
>>> find that component don't do that, use this instead' (for activemq
>>> it would be explicity configuring vmpersistence). My rational is to
>>> avoid magic. A component should always start the same way.
>>>
>>> To be more general:
>>>
>>> In the OSS J2EE CL land, we have as of now 2 different hierarchies:
>>>
>>> - JBoss with its Unified ClassLoader [2]
>>> AFAIK what has been said publicly to defend this design was
>>> originally to 'please' users and to avoid them the dreaded
>>> ClassCast or ClassNotFound, VeryErrors,etc..... by stuffing as much
>>> components as they could find into a gigantic 'unified' pot. This
>>> led to a terrible thing which any serious user has been fighting
>>> against in production...not mentioning that classloader isolation
>>> settings have been changing between micro releases.
>>>
>>> - JOnAS
>>> It has a similar classloader hierarchy of Geronimo's [3] (or vice-
>>> versa) but is unfortunately exposing its implementation to
>>> applications. There is now a very serious problems with deployment
>>> of Hibernate based apps which use ASM and the ASM version used
>>> within JOnAS internals...which are incompatible.
>>>
>>>
>>> Web applications (WARs) deployed in those J2EE containers generally
>>> can change the delegation model from the java2 delegation model
>>> (parent first) to a servlet 2.3+ model (current first), but this is
>>> insufficient in itself because it is only for the WAR part..you
>>> could very well have this problem in the EJB tiers .. so you need
>>> to be able to change the model type as well in the EJB tier.
>>>
>>> Being able to change the delegation model of the EJB tiers of
>>> course does not prevent actually having the case described in (2)
>>> and (3) happening. Unless we can filter for sure what can be
>>> delegated which is not so straightforward to me.
>>>
>>> Indeed, it does not mean filtering out to allow 'only' J2EE apis
>>> and implementation. In your app, you may perfectly need visibility
>>> of components located in the boostrap classpath or in jre/lib/ext
>>> (for example a crypto provider, etc...)
>>>
>>> Shouldn't the classloader architecture have a child classloader to
>>> load internals (just like it does for the database driver)
>>>
>>> Any thoughts on that ? I would really like to avoid having a
>>> release with a ClassLoader architecture that is already known to
>>> expose the users to some serious problems. Otherwise this may lead
>>> to tightly coupled components that will be very hard to decouple
>>> later (if not now).
>>>
>>> Any comment is welcome.
>>>
>>> Cheers,
>>>
>>> Stephane
>>>
>>>
>>> [1] http://chariotsolutions.com/geronimo/elements-classloaders.html
>>> [2] http://wiki.jboss.org/wiki/Wiki.jsp? 
>>> page=ClassLoadingConfiguration
>>> [3] http://www.redhat.com/docs/manuals/rhaps/jonas-guide/s1-
>>> conclusion.html
>>>
>>>
>>
>>
>


Re: ClassLoader Architecture

Posted by Aaron Mulder <am...@alumni.princeton.edu>.
	Can't we find a better way to segregate server classes?  You know, 
set up a path like (forgive my ASCII art):

                        ,-- Geronimo Server
system -- j2ee specs --/
                       \------ App 1
                        \----- App 2

	I know that all the construction bits of the server would need to 
be on the server side of the fence, but I think we could throw apps in an 
isolated CL that didn't have anything but the most common stuff like 
specs.

Aaron
  
On Thu, 16 Jun 2005, Dain Sundstrom wrote:

> Stephane and I chatted about this on irc, so I wanted to post up the  
> notes.
> 
> The issues Stephane points are big deal.  This is a problem Paul  
> Hammant first pointed out to me a the last OSCon, and I have been  
> thinking about how to address for a while.  Of course I never brought  
> it up for discussion here :(
> 
> In the long run (for Geronimo 2.0), I'm currently leaning towards  
> using OSGI to solve this problem.  OSGI is the framework that eclipse  
> plugins use, and they have really solved the class loader problems.   
> This would require a major architectural change so I don't think it  
> can be done in 1.x.  For those of you that are interested, the  
> current OSGi r3 spec chapter 4 describes the class loader  
> architecture.  The next yet to be published r4 spec expands on the  
> model addressing some of the bad assumptions (e.g., furure versions  
> of any library are backwards compatible with all previous versions).
> 
> In the short term, I like Stephane's idea of adding an optional child  
> first delegation class loader to applications (not just wep  
> application).  This would help applications avoid conflicts with  
> Geronimo system classes.  Anyone want to take a look at implementing  
> this?
> 
> -dain
> 
> On Jun 14, 2005, at 8:18 AM, Stephane Bailliez wrote:
> 
> > Hi all,
> >
> > I'd like to clarify  a couple of points about the Geronimo  
> > ClassLoader architecture. I have had a discussion about it with  
> > Gianny Damour on IRC, so i'm bringing the discussion here to have  
> > some feedback about the existing implementation and my thoughts.
> >
> > It looks like as of now the CL architecture is exposing its  
> > internal implementation to applications [1] if I'm reading correctly.
> >
> > Say for example, if Geronimo is using component 1.x it will be  
> > visible to applications.
> >
> > There are 2 aspects:
> >
> > 1. if the application uses component 2.x which is incompatible with  
> > 1.x you could then be in a blocker situation.
> >
> > 2. if the application incidentally forgets to ship with component  
> > 1.x, in a normal world, this would end up with a CNFE. In our case  
> > it would simply mask it to the user, actually run by accident..and  
> > may blow up later, say when upgrading the apps, or Geronimo.
> >
> > 3. some component unfortunately autoconfigure based on the presence  
> > or absence of another component (a good example is ActiveMQ  
> > autoconfiguring itself with derby persistence if available in the  
> > classpath). I don't like too much autoconfiguration, as it will  
> > often lead to problems later. The  rational being to put as little  
> > configuration as possible and thus forgetting to say 'even if you  
> > find that component don't do that, use this instead' (for activemq  
> > it would be explicity configuring vmpersistence). My rational is to  
> > avoid magic. A component should always start the same way.
> >
> > To be more general:
> >
> > In the OSS J2EE CL land, we have as of now 2 different hierarchies:
> >
> > - JBoss with its Unified ClassLoader [2]
> > AFAIK what has been said publicly to defend this design was  
> > originally to 'please' users and to avoid them the dreaded  
> > ClassCast or ClassNotFound, VeryErrors,etc..... by stuffing as much  
> > components as they could find into a gigantic 'unified' pot. This  
> > led to a terrible thing which any serious user has been fighting  
> > against in production...not mentioning that classloader isolation  
> > settings have been changing between micro releases.
> >
> > - JOnAS
> > It has a similar classloader hierarchy of Geronimo's [3] (or vice- 
> > versa) but is unfortunately exposing its implementation to  
> > applications. There is now a very serious problems with deployment  
> > of Hibernate based apps which use ASM and the ASM version used  
> > within JOnAS internals...which are incompatible.
> >
> >
> > Web applications (WARs) deployed in those J2EE containers generally  
> > can change the delegation model from the java2 delegation model  
> > (parent first) to a servlet 2.3+ model (current first), but this is  
> > insufficient in itself because it is only for the WAR part..you  
> > could very well have this problem in the EJB tiers .. so you need  
> > to be able to change the model type as well in the EJB tier.
> >
> > Being able to change the delegation model of the EJB tiers of  
> > course does not prevent actually having the case described in (2)  
> > and (3) happening. Unless we can filter for sure what can be  
> > delegated which is not so straightforward to me.
> >
> > Indeed, it does not mean filtering out to allow 'only' J2EE apis  
> > and implementation. In your app, you may perfectly need visibility  
> > of components located in the boostrap classpath or in jre/lib/ext  
> > (for example a crypto provider, etc...)
> >
> > Shouldn't the classloader architecture have a child classloader to  
> > load internals (just like it does for the database driver)
> >
> > Any thoughts on that ? I would really like to avoid having a  
> > release with a ClassLoader architecture that is already known to  
> > expose the users to some serious problems. Otherwise this may lead  
> > to tightly coupled components that will be very hard to decouple  
> > later (if not now).
> >
> > Any comment is welcome.
> >
> > Cheers,
> >
> > Stephane
> >
> >
> > [1] http://chariotsolutions.com/geronimo/elements-classloaders.html
> > [2] http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassLoadingConfiguration
> > [3] http://www.redhat.com/docs/manuals/rhaps/jonas-guide/s1- 
> > conclusion.html
> >
> 
> 

Re: ClassLoader Architecture

Posted by Dain Sundstrom <da...@iq80.com>.
Stephane and I chatted about this on irc, so I wanted to post up the  
notes.

The issues Stephane points are big deal.  This is a problem Paul  
Hammant first pointed out to me a the last OSCon, and I have been  
thinking about how to address for a while.  Of course I never brought  
it up for discussion here :(

In the long run (for Geronimo 2.0), I'm currently leaning towards  
using OSGI to solve this problem.  OSGI is the framework that eclipse  
plugins use, and they have really solved the class loader problems.   
This would require a major architectural change so I don't think it  
can be done in 1.x.  For those of you that are interested, the  
current OSGi r3 spec chapter 4 describes the class loader  
architecture.  The next yet to be published r4 spec expands on the  
model addressing some of the bad assumptions (e.g., furure versions  
of any library are backwards compatible with all previous versions).

In the short term, I like Stephane's idea of adding an optional child  
first delegation class loader to applications (not just wep  
application).  This would help applications avoid conflicts with  
Geronimo system classes.  Anyone want to take a look at implementing  
this?

-dain

On Jun 14, 2005, at 8:18 AM, Stephane Bailliez wrote:

> Hi all,
>
> I'd like to clarify  a couple of points about the Geronimo  
> ClassLoader architecture. I have had a discussion about it with  
> Gianny Damour on IRC, so i'm bringing the discussion here to have  
> some feedback about the existing implementation and my thoughts.
>
> It looks like as of now the CL architecture is exposing its  
> internal implementation to applications [1] if I'm reading correctly.
>
> Say for example, if Geronimo is using component 1.x it will be  
> visible to applications.
>
> There are 2 aspects:
>
> 1. if the application uses component 2.x which is incompatible with  
> 1.x you could then be in a blocker situation.
>
> 2. if the application incidentally forgets to ship with component  
> 1.x, in a normal world, this would end up with a CNFE. In our case  
> it would simply mask it to the user, actually run by accident..and  
> may blow up later, say when upgrading the apps, or Geronimo.
>
> 3. some component unfortunately autoconfigure based on the presence  
> or absence of another component (a good example is ActiveMQ  
> autoconfiguring itself with derby persistence if available in the  
> classpath). I don't like too much autoconfiguration, as it will  
> often lead to problems later. The  rational being to put as little  
> configuration as possible and thus forgetting to say 'even if you  
> find that component don't do that, use this instead' (for activemq  
> it would be explicity configuring vmpersistence). My rational is to  
> avoid magic. A component should always start the same way.
>
> To be more general:
>
> In the OSS J2EE CL land, we have as of now 2 different hierarchies:
>
> - JBoss with its Unified ClassLoader [2]
> AFAIK what has been said publicly to defend this design was  
> originally to 'please' users and to avoid them the dreaded  
> ClassCast or ClassNotFound, VeryErrors,etc..... by stuffing as much  
> components as they could find into a gigantic 'unified' pot. This  
> led to a terrible thing which any serious user has been fighting  
> against in production...not mentioning that classloader isolation  
> settings have been changing between micro releases.
>
> - JOnAS
> It has a similar classloader hierarchy of Geronimo's [3] (or vice- 
> versa) but is unfortunately exposing its implementation to  
> applications. There is now a very serious problems with deployment  
> of Hibernate based apps which use ASM and the ASM version used  
> within JOnAS internals...which are incompatible.
>
>
> Web applications (WARs) deployed in those J2EE containers generally  
> can change the delegation model from the java2 delegation model  
> (parent first) to a servlet 2.3+ model (current first), but this is  
> insufficient in itself because it is only for the WAR part..you  
> could very well have this problem in the EJB tiers .. so you need  
> to be able to change the model type as well in the EJB tier.
>
> Being able to change the delegation model of the EJB tiers of  
> course does not prevent actually having the case described in (2)  
> and (3) happening. Unless we can filter for sure what can be  
> delegated which is not so straightforward to me.
>
> Indeed, it does not mean filtering out to allow 'only' J2EE apis  
> and implementation. In your app, you may perfectly need visibility  
> of components located in the boostrap classpath or in jre/lib/ext  
> (for example a crypto provider, etc...)
>
> Shouldn't the classloader architecture have a child classloader to  
> load internals (just like it does for the database driver)
>
> Any thoughts on that ? I would really like to avoid having a  
> release with a ClassLoader architecture that is already known to  
> expose the users to some serious problems. Otherwise this may lead  
> to tightly coupled components that will be very hard to decouple  
> later (if not now).
>
> Any comment is welcome.
>
> Cheers,
>
> Stephane
>
>
> [1] http://chariotsolutions.com/geronimo/elements-classloaders.html
> [2] http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassLoadingConfiguration
> [3] http://www.redhat.com/docs/manuals/rhaps/jonas-guide/s1- 
> conclusion.html
>


Re: ClassLoader Architecture

Posted by Stephane Bailliez <sb...@apache.org>.
Stephane Bailliez wrote:
> Hi all,
> 
> I'd like to clarify  a couple of points about the Geronimo ClassLoader 
> architecture. I have had a discussion about it with Gianny Damour on 
> IRC, so i'm bringing the discussion here to have some feedback about the 
> existing implementation and my thoughts.
[...]

ping. Any comments from Geronimo developpers ?