tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tim Whittington <tim.whitting...@orionhealth.com>
Subject Re: Problem loading classes with Class.forName() in StandardContext.createWrapper()
Date Mon, 04 Jan 2010 02:46:49 GMT

We've experienced similar issues integrating lots of third party libraries (Tomcat being one
of them) into our OSGi runtime. 

Essentially this boils down to OSGi liking extension functionality to be provided by instantiation
in the providing bundles, and publication using OSGi services. 
(i.e. pure OSGi services or declarative services etc.). Put another way, the concepts of global
application classloaders where Class.forName works (ala Java EE etc.) break down in OSGi.


Libraries that use the TCCL in preference to Class.forName help, but in cases like the one
you describe where there's no direct invocation from the bundle that has access to the classes
it doesn't help. Fragment bundles (and Eclipse specific buddy classloaders) also help, and
we've had to use them with tools like Hibernate, but they're less than ideal. 

I think the conclusion you've reached is correct - either fragment bundles (which is a sub-optimal
solution) or a pluggable extension loading framework could be the solution. 

I believe we ran into issues like this when integrating Tomcat 5.5 into our OSGi runtime -
we had to patch up the web app ClassLoaders at runtime to make taglib loading work. 
In that case we were able to wrap the ClassLoaders with the help of some declarative metadata
in bundles containing taglibs. 

If you can tell which bundles can contain implementions of whatever it is you're trying to
instantiate, you can construct a ClassLoader spanning those bundles yourself and use that
(you'd only want to use it for loading these extensions, as it defeats the purpose/nature
of OSGi to some extent to do this). 
It might be that the web application bundles would be all you need (and the upcoming OSGi
Enterprise Spec will give you a standard way of locating these), and that'd probably be a
reasonable limitation, or you could accomodate applications partitioned to a finer degree
by some additional marker to include other bundles. 

The other, more OSGi approach would be for listeners to be published as OSGi services with
target properties, that are then just looked up by name by the OSGi version of the extension
loader (as opposed to instantiating them). 
i.e. an instance of the Listener interface is published by a bundle as an OSGi service with
a property tomcatClassName=org.myproject.impl.MyListener. The extension loader then looks
up the service with a property filter on 'tomcatClassName' to find the available extension.

OSGi apps using Tomcat would simply publish these using Declarative Services or similar, and
this would be a very natural approach for an OSGi app. 

With this latter approach you have delightful lifecycle management issues because of the dynamic
nature of OSGi (extension bundles starting after the Tomcat bundles for instance). We solve
some of these with a combination of declarative only metadata (using the Eclipse Extension
Registry) to advertise extension existence on bundle resolution, and Declarative Services
to instantiate and publish the actual extension, and some by having the framework accept dynamic
injection of extensions (Listeners come and go). 

cheers 
tim 
----- Original Message ----- 
From: "David Jencks" <david_jencks@yahoo.com> 
To: "Tomcat Developers List" <dev@tomcat.apache.org> 
Sent: Friday, 25 December, 2009 11:27:09 AM GMT +12:00 New Zealand 
Subject: Re: Problem loading classes with Class.forName() in StandardContext.createWrapper()


I'd like to encourage a little more discussion on this topic. Mark 
commented on the bugzilla entry to the effect, IIUC, that he thought 
this was a geronimo problem. I did some more experimentation and I'm 
pretty sure it has nothing to do with geronimo specifically, but 
relates to how Class.forName works in osgi. 

I've concluded from my experiments that Class.forName in osgi will 
only load classes from the current bundle and not from any bundles 
wired to the current bundle through package-imports. I think this 
means that with the current code all listeners have to be in the same 
jar as the catalina.jar classes or in a fragment bundle attached to 
it. I haven't tried using a fragment bundle so I don't know if it 
would actually work. 

So, my conclusion is that the current code forces: 
if you want listeners that don't come with tomcat, you have to put 
them in a fragment bundle or repackage all of tomcat to include them. 
Is this really the policy tomcat wants to adopt towards osgi 
environments? I would think that delegating all reflective class 
loading to a pluggable component would be a more extension-friendly 
approach. 

BTW, has anyone tried to find out if the split into catalina.jar and 
coyote.jar works in osgi? 

thanks 
david jencks 

On Dec 19, 2009, at 5:12 PM, David Jencks wrote: 

> In the tomcat-7 geronimo/osgi integration we've run into a problem 
> when tomcat loads listener classes using Class.forName. Using the 
> InstanceManager to just create the objects works fine for us. 
> 
> In geronimo at the moment the InstanceManager has access to both 
> application and system classes, so it can load just about anything 
> that is supplied as a listener class. If listeners are supposed to 
> only be system classes, perhaps adding another method to 
> InstanceManager to create system objects would be appropriate. 
> 
> If changing this is unacceptable for some reason we do have a couple 
> of other solutions available such as overriding the method or adding 
> the geronimo listener classes in a fragment bundle, but I think 
> using the InstanceManager would be a more elegant solution. 
> 
> See https://issues.apache.org/bugzilla/show_bug.cgi?id=48414 (patch 
> included) and https://issues.apache.org/jira/browse/GERONIMO-4992 
> 
> Many thanks! 
> david jencks 
> 
> 
> --------------------------------------------------------------------- 
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org 
> For additional commands, e-mail: dev-help@tomcat.apache.org 
> 


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


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message