portals-jetspeed-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject [jira] Commented: (JS2-56) Objects Fail to Create with Tomcat Classloaders and cross context
Date Fri, 28 May 2004 12:27:01 GMT
The following comment has been added to this issue:

     Author: Ate Douma
    Created: Fri, 28 May 2004 5:26 AM
I think I have found solution which I think might be the easiest way to go.

There is one big consequence that I don't like but it applies to any other valid solution
we have come up with so far (except patching the Tomcat ClassLoaders or OJB itself which I
personally don't see as acceptable options). I will come back to this consequence below.

What I did was moving all the classes which OJB might instantiate dynamically (using the currentThread
contextClassLoader) into commons.
This involves *all* the om classes, a few ojb util classes like the FieldConversion implementations,
and the OJB jar itself.

I also needed to refactor the StoreablePortletDefinitionDelegate which was dependent on PersistencyStore.
I solved that by creating a new interface (PortletDefinitionStoreDelegate) which defines handling
the store functionality and a implementation class of which a StoreablePortletDefinitionDelegate
gets supplied in its constructor.

Furthermore, I moved registry o.a.j.components.portletentity.PortletEntityImpl, which really
is an om class, to a new commons package o.a.j.om.common.entity.impl. I guess this one was
overlooked in abstracting the om classes.

Thats all.
All the current classloader issues are solved by this.

Because I moved all these om packages to commons we will lose the cvs history on all these
files though. Thats bad, but the price of still using cvs.

There is one more big consequence though which should be considered before this is applied
(I will attach a patch file after this comment).
Moving the ojb jar to tomcat shared/lib means that external portlet apps which also want to
use ojb really are forced to use the version supplied by J2. 
In theory, a web-app can supply its own version of ojb in its WEB-INF/lib folder and it *will*
override the version in shared/lib (servlet api spec compliance).
But, because J2 also uses OJB, om objects loaded through J2 will have a different classloader
as the ones loaded through a portlet app.
Thus, this locks portlet developers who want to use OJB (but, who would, honestly?) into the
version supplied by J2 (and are not even allowed to put the same version in their WEB-INF/lib
Currently, I don't see how this can be prevented though. If we don't want to put OJB into
shared/lib we will have to hack the Tomcat classloaders, or hack OJB itself for not using
the ContextClassLoader anymore. 
I think the OJB team made a wrong decision how to implement the dynamic classloading. In its
current form OJB cannot be used by any web application using cross-context functionality without
the same consequence. Maybe they can be convinced to change this but I don't see that happen
overnight and we need a solution now...

If we are going for this solution then we can go full speed ahead again. 

But we must be very careful not (re)introducing these kind of problems. Maybe not only OJB
causes these kind of problems.
The rules to prevent this are simple:
1) Put all classes which might get dynamically created through the ContextClassLoader by a
external web app into shared/lib.
2) If one of those classes need an object reference only available to J2 itself, Dependency
Injection is required based on interfaces in shared/lib (like I did with StoreablePortletDefinitionDelegate).
View this comment:

View the issue:

Here is an overview of the issue:
        Key: JS2-56
    Summary: Objects Fail to Create with Tomcat Classloaders and cross context
       Type: Task

     Status: Open
   Priority: Major

    Project: Jetspeed 2
             Components Core
   Fix Fors:

   Assignee: David Sean Taylor
   Reporter: David Sean Taylor

    Created: Tue, 25 May 2004 9:35 PM
    Updated: Fri, 28 May 2004 5:26 AM
Environment: Tomcat 4 and 5

J2 uses a cross-context class loader to share objects created in the jetspeed context with
other portlet application contexts. This works fine when objects have already been instantiated
in the jetspeed context. 

J2 infuses a common servlet into every portlet application that is deployed into a Tomcat
application server via the J2 portal's PAM (Portlet Application Manager). The code that runs
in this servlet is placed in Tomcat's shared/lib directory so that both Jetspeed common servlet
and the Jetspeed portal can share objects. 

The problems I am seeing with this approach are rooting in the creation of new objects. For
example, if a portlet application, such as the HW_App, has a portlet UserInfo, that requires
creation of preference objects. Preference objects by OJB. Looking at the code used by the
ojb object broker


you see object creation taking place as:

  result = constructor.newInstance(NO_ARGS);

And this code fails, class not found exception. It fails to find the object to be created,
such as a NodeImpl, which is deployed in the Prefs jar, normally stored under jetspeed's WEB-INF/lib
directory. This tells me that the classloader being used by the code above is not the same
as the cross-context classloader in Tomcat...or...the Tomcat cross-context class loader is
not designed to handle this kind of object construction.

I think we have several directions we can take for a solution
One experiment I tried with Tomcat 4.1.30, was:

1. move every jar out of WEB-INF/lib into shared/lib
2. delete all classes under WEB-INF/classes
3. copy jetspeed-2.0-a1.jar into shared/lib
4. move the JDBC driver into Tomcat's system directory or into the classpath

This seemed to work, although for some reason I could not login to the LoginPortlet tonight.
Not sure if its related. The solution is simple here: move everything down into shared/lib.

A second solution would be to replace Tomcat's cross-context class loader with our own.
Although I have not found a 'pluggable' way to do this.

A third solution would be to modify the classloader in the Jetspeed common servlet.
I have started some testing in this area without any success (yet):


see the infuseClasspath method

This message is automatically generated by JIRA.

If you think it was sent incorrectly contact one of the administrators:

If you want more information on JIRA, or have a bug to report see:

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

View raw message