The following comment has been added to this issue:

     Author: Ate Douma
    Created: Fri, 28 May 2004 5:26 AM
       Body:
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 folder).
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:
  http://issues.apache.org/jira/browse/JS2-56?page=comments#action_35764

---------------------------------------------------------------------
View the issue:
  http://issues.apache.org/jira/browse/JS2-56

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: 
             Components Core
   Fix Fors:
             2.0-dev/cvs
   Versions:
             2.0-a1

   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

Description:
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

http://cvs.apache.org/viewcvs.cgi/db-ojb/src/java/org/apache/ojb/broker/util/ConstructorHelper.java

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):

http://cvs.apache.org/viewcvs.cgi/jakarta-jetspeed-2/commons/src/java/org/apache/jetspeed/container/JetspeedContainerServlet.java

see the infuseClasspath method







---------------------------------------------------------------------
JIRA INFORMATION:
This message is automatically generated by JIRA.

If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa

If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to