Hi Joseph,

On 06/06/2012, at 04:04, Joseph Pachod wrote:

> Hi all
> 
> We've been using WOInject for a few months and encountered two issues
> due to the classloader manipulation done at startup (the one to enable
> interception through javassist, in the WOInject class).
> 

You're not alone. I've faced problems because of the classloader manipulation 
too. Take a look at issue #2 [1]. I've provided a simple fix, but I know it is 
not a definitive solution.

> The first issue is a known Guice 2.0 bug
> (http://code.google.com/p/google-guice/issues/detail?id=343). This one
> pops up when from Guice grabs some class from another classloader that
> the one it was started in. In our case, it meant Guice was grabing
> some class from the default class loader instead of the the javassist
> one. It appeared in a very unexpected way: suddenly one binding was
> causing the whole application to break down. Finally, we had to switch
> to Guice 3.0, which incorporates the bug fix and avoids the issue to
> show up another time somewhere else. Turned out since  that the
> woinject repo on github states "Guice 3.0" as a requirement. Was this
> bug the reason for it?
> 

In fact, I was not aware of this Guice bug until now. :)

The WOInject code responsible for object instantiation was heavily inspired by 
the AssistedInject module. It requires the bind().toConstructor() method API 
added in Guice 3.0. To support Guice 2.0, WOInject would not be able to take 
advantage of the AOP support, for instance.

> The second issue is a security exception when trying to encrypt some
> file. The issue was boiled down to a classloader one again, the
> required class being "on the bootclasspath" instead of the current
> classloader (the javassist one). I append the stack trace to the end
> of this mail, if some one wants to have a look at it.
> 

This problem seems to be related to the issue #2 mentioned above. Clearly, an 
alternative is required to the Javassist classloader to solve this problem.

> In order to get rid of this bug, we ended removing the classloading
> trick and, instead, using our own _NSUtilities where we do the
> injector.injectMembers(newInstance) ourselves. In order to make it
> possible, we made sure our own version of this class came on top of
> the classpath provided to the application (thanks to Maven). Since it
> works again.
> 
> What do you think of that ? Could it be done as well in WOInject ?
> 

Yes. It could be done. However, this solution also has some problems:

1) It doesn't scale: that is the same approach employed by Wonder. We can't 
apply this kind of solution every time, for every framework.

2) It is subject to license issues.

3) It makes the user responsible for the solution of the problem. This problem 
is an extension of the first problem. In the beginning, ERExtensions should 
come first in the classpath. Then ERFoundation and ERWebObjects were created 
and took precedence. With this solution, WOInject must come before those 
libraries.

4) I'm not sure this solution works in a JEE environment.

Changing the behavior of core classes of WebObjects is a general problem that 
anyone developing WO apps/frameworks face sooner or later. IMHO, we should 
develop a common solution in Wonder, some kind of ERPatcher framework. This 
would enable us to solve long-standing problems without violating the Apple 
license and in an organized manner. I really would like to know what others 
think about it. I'm really inclined to implement this framework, as soon as I 
figure out how. :)

> Indeed, we were planning to use WOInject once the "WOInjectProposal"
> on github would have been incorporated.
> 

I'm planning to add this feature in the next release. I'm really out of time 
right now, but it is in my TODO list.

> Personally, getting rid of classloader manipulations would be a plus
> IMHO. It removes a whole bunch of potential issues, from memory leaks
> to "classes from the wrong classloader".
> 

Classloader manipulations are complicated and can have side effects. However, 
it has been widely used in Java frameworks (including Guice). I'll try to 
produce a better solution. I'll ping you as soon as I have a new version for 
testing.

> For sure, I may miss some good points of javassist, so I'm really
> eager to read you back. Alternative solutions are also welcome, but
> the few I could make up (using an agent instead of classloader
> manipulation for example) don't come for cheap neither: overall class
> shadowing and classpath ordering look like the less impacting option.
> 

I also would like to avoid using an agent to solve this problem. IMHO, we have 
the following alternatives:

1) A better custom classloader: the Javassist classloader is just an example of 
how to create a Classloader able to load Javassist manipulated classes. We can 
write a better one that loads only the _NSUtilities class from Javassist and 
delegates everything else to the parent classloader.

2) Loading the manipulated classes right on the System classloader: the 
manipulated _NSUtilities could be loaded directly in the System classloader 
through reflection. I don't know what are the side effects of this solution yet.

3) Classpath ordering: as you mentioned, avoids runtime problems at the cost of 
delegating the responsibility to the user of the library.

I'll try to implement the first solution and send you a new version of WOInject 
as soon as possible.

[1]https://github.com/hprange/woinject/issues/2

Cheers,

Henrique
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to