You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@felix.apache.org by Kevin Lohmann <ke...@d-velop.de> on 2008/09/24 12:08:20 UTC

Some thoughts about classloaders

Hi *,

I guess, I have a misunderstanding about classloaders in OSGi and i
appreciate, if someone can engross those thoughts.

Here's a specific situation:

Bundle A exports exports stax-api and implementation WoodStox. Bundle B
has an import on just the stax-api (javax.xml.stream). Bundle B calls
'XMLInputFactory.newInstance();'.

Now whats going on? According to
'http://java.sun.com/webservices/docs/2.0/tutorial/doc/StAX4.html' it is
looking for file 'META-INF/services/javax.xml.stream.XMLInputFactory'
"in jars available to the JRE". Bundle B finds this file and because
bundle A exports the WoodStox-classes, everything works fine.

But why? Remember: Bundle A has no exporting advice for META-INF (if
thats ever possible) and bundle B has no importing on that.

I try to split bundle A in two bundles: Bundle A1 contains the stax-api,
bundle A2 the implementation (WoodStox). But now, when I call
'XMLInputFactory.newInstance();' in bundle B the file
'META-INF/services/javax.xml.stream.XMLInputFactory' is NOT found.

I don't get the point and hope, someone can bring light into my/the
darkness.

Cheers,
 Kevin

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Some thoughts about classloaders

Posted by Pierre De Rop <pi...@alcatel-lucent.fr>.
Hi Kevin;

Well, maybe the better way to understand what is going on is looking at 
the source code of the XMLInputFactory.newInstance().
I guess this method do something like the following:

   1. If the Thread Context ClassLoader is set, then use that class
      loader in order to lookup the
      META-INF/services/javax.xml.stream.XMLInputFactory file.
   2. If no Thread Context ClassLoader is set (null), then use the class
      loader which loaded the XmlInputFactory class (that is: the class
      loader of your bundle B)
   3. Else fall back on the system class loader and lookup the
      META-INF/services/javax.xml.stream.XMLInputFactory from the classpath.


In your working case, I think that the step 2 applies here, because you 
have embedded both API + Impl in bundle A.
But, if you split the API and Impl in separate bundles A1 and A2, then 
it does not work, because in step 2, the class loader used to load the 
API (XMLInputFactory) is the one from bundle A1, not from A2 ...

Are you using the thread context class loader ?

 From my side I do the following: I have written a special  SPILoader 
bundle which uses the extender pattern: it listens to
"Bundle Started" events. And when it detects that a bundle is started, 
then it checks if that bundle contains a META-INF/services/factory file. 
If so, then it loads the implementation (with the just started 
bundle.loadClass method) and registers it into the OSGi service registry.
Hence, other client bundles can gain access to the API, from the OSGi 
registry, not using the Factory methods, like XMLInputFactory.newInstance().

So, in your case, you could retrieve your XMLInputFactory instance from 
your bundle activator, like this:

public void start(BundleContext bctx) {
   ServiceReference ref = 
bctx.getServiceReference(XMLInputFactory.class.getName());
   XMLInputFactory factory = (XMLInputFactory) ref.getService(ref);
}

(of course, it would be nicer to use some dependency framework, like  
iPOJO,  DependencyManager, SCR, etc ...)

However, you could argue that this solution is not applicable for third 
party libraries which invokes directly the XMLInputFactory.newInstance() 
method ... and you would be right ...


Regards
/pierre

Kevin Lohmann wrote:
> Hi *,
>
> I guess, I have a misunderstanding about classloaders in OSGi and i
> appreciate, if someone can engross those thoughts.
>
> Here's a specific situation:
>
> Bundle A exports exports stax-api and implementation WoodStox. Bundle B
> has an import on just the stax-api (javax.xml.stream). Bundle B calls
> 'XMLInputFactory.newInstance();'.
>
> Now whats going on? According to
> 'http://java.sun.com/webservices/docs/2.0/tutorial/doc/StAX4.html' it is
> looking for file 'META-INF/services/javax.xml.stream.XMLInputFactory'
> "in jars available to the JRE". Bundle B finds this file and because
> bundle A exports the WoodStox-classes, everything works fine.
>
> But why? Remember: Bundle A has no exporting advice for META-INF (if
> thats ever possible) and bundle B has no importing on that.
>
> I try to split bundle A in two bundles: Bundle A1 contains the stax-api,
> bundle A2 the implementation (WoodStox). But now, when I call
> 'XMLInputFactory.newInstance();' in bundle B the file
> 'META-INF/services/javax.xml.stream.XMLInputFactory' is NOT found.
>
> I don't get the point and hope, someone can bring light into my/the
> darkness.
>
> Cheers,
>  Kevin
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>   


AW: AW: Some thoughts about classloaders

Posted by Kevin Lohmann <ke...@d-velop.de>.
Pierre De Rop wrote:
> Oups, your are right: in the step 2, I made a mistake, and typed "B" 
> instead of "A":
> here is the fixed step 2:
> 
>  2. If no Thread Context ClassLoader is set (null), then use the class
>      loader which loaded the XmlInputFactory class (that is: the class
>      loader of your bundle A)
> 
> Here, the newInstance method probably uses the class loader 
> of the bundle A, which has visibility over the impl jar file 
> (and the impl jar file contains the 
> META-INF/services/javax.xml.stream.XMLInputFactory).

I guessed something like that, but couldn't yet verify that.

So, if you had not written 'probably' I would be pleased ;)

Thanks again for your reply!

Cheers,
 Kevin

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: AW: Some thoughts about classloaders

Posted by Pierre De Rop <pi...@alcatel-lucent.fr>.
Kevin Lohmann wrote:
> Thanks Pierre and Guillaume for your replies.
>
> I will give these ideas a try!
>
> @Pierre:
>   
>> Well, maybe the better way to understand what is going on is 
>> looking at 
>> the source code of the XMLInputFactory.newInstance().
>> I guess this method do something like the following:
>>    1. If the Thread Context ClassLoader is set, then use that class
>>       loader in order to lookup the
>>       META-INF/services/javax.xml.stream.XMLInputFactory file.
>>    2. If no Thread Context ClassLoader is set (null), then 
>> use the class
>>       loader which loaded the XmlInputFactory class (that is: 
>> the class
>>       loader of your bundle B)
>>    3. Else fall back on the system class loader and lookup the
>>       META-INF/services/javax.xml.stream.XMLInputFactory from 
>> the classpath.
>> In your working case, I think that the step 2 applies here, 
>> because you 
>> have embedded both API + Impl in bundle A.
>>     
> So maybe i haven't understood the ThreadContextClassLoader mechanism
> yet, but how can have bundle B the XMLInputFactory-file in its
> classpath, even when B has only an import on one package from bundle A?
>   
Oups, your are right: in the step 2, I made a mistake, and typed "B" 
instead of "A":
here is the fixed step 2:

 2. If no Thread Context ClassLoader is set (null), then use the class
     loader which loaded the XmlInputFactory class (that is: the class
     loader of your bundle A)

Here, the newInstance method probably uses the class loader of the bundle A, which has visibility over the impl jar file 
(and the impl jar file contains the META-INF/services/javax.xml.stream.XMLInputFactory).


/pierre



> Thanks again && cheers,
>  Kevin
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>   


AW: Some thoughts about classloaders

Posted by Kevin Lohmann <ke...@d-velop.de>.
Thanks Pierre and Guillaume for your replies.

I will give these ideas a try!

@Pierre:
> Well, maybe the better way to understand what is going on is 
> looking at 
> the source code of the XMLInputFactory.newInstance().
> I guess this method do something like the following:
>    1. If the Thread Context ClassLoader is set, then use that class
>       loader in order to lookup the
>       META-INF/services/javax.xml.stream.XMLInputFactory file.
>    2. If no Thread Context ClassLoader is set (null), then 
> use the class
>       loader which loaded the XmlInputFactory class (that is: 
> the class
>       loader of your bundle B)
>    3. Else fall back on the system class loader and lookup the
>       META-INF/services/javax.xml.stream.XMLInputFactory from 
> the classpath.
> In your working case, I think that the step 2 applies here, 
> because you 
> have embedded both API + Impl in bundle A.
So maybe i haven't understood the ThreadContextClassLoader mechanism
yet, but how can have bundle B the XMLInputFactory-file in its
classpath, even when B has only an import on one package from bundle A?

Thanks again && cheers,
 Kevin

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Some thoughts about classloaders

Posted by Guillaume Nodet <gn...@gmail.com>.
FWIW, in ServiceMix, we have enhanced version of some specifications
(Stax included) which allows existing code to run seamlessly in OSGi:
i.e. code using XMLInputFactory.newInstance() will work as long as one
implementation bundle has been deployed.  You can find some
explanations at
http://gnodet.blogspot.com/2008/05/jee-specs-in-osgi.html and some
released artifacts are available from the public repositories in
http://repo1.maven.org/maven2/org/apache/servicemix/specs/.
This works roughly as Pierre explained: i.e. when a new bundle is
resolved, we look inside for META-INF/services and those informations
are used by the spec jar when a factory is about to be created.
The benefit (and it was the main goal) is to allow existing code to
run without any modification.

On Wed, Sep 24, 2008 at 12:08 PM, Kevin Lohmann
<ke...@d-velop.de> wrote:
>
> Hi *,
>
> I guess, I have a misunderstanding about classloaders in OSGi and i
> appreciate, if someone can engross those thoughts.
>
> Here's a specific situation:
>
> Bundle A exports exports stax-api and implementation WoodStox. Bundle B
> has an import on just the stax-api (javax.xml.stream). Bundle B calls
> 'XMLInputFactory.newInstance();'.
>
> Now whats going on? According to
> 'http://java.sun.com/webservices/docs/2.0/tutorial/doc/StAX4.html' it is
> looking for file 'META-INF/services/javax.xml.stream.XMLInputFactory'
> "in jars available to the JRE". Bundle B finds this file and because
> bundle A exports the WoodStox-classes, everything works fine.
>
> But why? Remember: Bundle A has no exporting advice for META-INF (if
> thats ever possible) and bundle B has no importing on that.
>
> I try to split bundle A in two bundles: Bundle A1 contains the stax-api,
> bundle A2 the implementation (WoodStox). But now, when I call
> 'XMLInputFactory.newInstance();' in bundle B the file
> 'META-INF/services/javax.xml.stream.XMLInputFactory' is NOT found.
>
> I don't get the point and hope, someone can bring light into my/the
> darkness.
>
> Cheers,
>  Kevin
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://open.iona.com

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org