Hi Joseph,

This error occurs if you run the application through the Application's main 
method. The static initialization of the ERXApplication class triggers the load 
of the _NSUtilities class. You need to run the application from a separated 
class, like the AppRunner I've described, to ensure the _NSUtilities has not 
been loaded yet.

Sorry for this inconvenience, but it's the only way I've found to make it work 
without a special classloader. 

Cheers,

Henrique

On 13/06/2012, at 19:53, Joseph Pachod wrote:

> Hi Henrique
> 
> Thanks for the feedbacks.
> 
> I've been short on time recently, so I quickly tried your fix but I
> encounter the following issue:
> java.lang.reflect.InvocationTargetException
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>       at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>       at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>       at java.lang.reflect.Method.invoke(Method.java:597)
>       at com.resurgences.guice.WOInject.loadClass(WOInject.java:158)
>       at com.resurgences.guice.WOInject.main(WOInject.java:117)
>       at 
> com.resurgences.demo.admin.ApplicationAdminDemo.main(ApplicationAdminDemo.java:14)
> Caused by: java.lang.LinkageError: loader (instance of
> sun/misc/Launcher$AppClassLoader): attempted  duplicate class
> definition for name: "com/webobjects/foundation/_NSUtilities"
>       at java.lang.ClassLoader.defineClass1(Native Method)
>       at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
>       at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
>       at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
>       ... 7 more
> 
> As I should be sleeping, I don't have much time to investigate right
> now, but I'll soon. Line numbers doesn't match your code since there
> are the extra guice stuff in there as well. Furthermore, I effectively
> have two instances of this class on my classpath (ERExtensions and
> JavaFoundations classes), so it doesn't look incorrect.
> 
> BTW, are you sure Guice AOP works for binding realized through a
> provider? I have the memory it doesn't... If not, just injecting
> members after objects creation through _NSUtilities looks like good
> enough.
> 
> Thanks again for your helpful answers :)
> 
> best
> joseph
> 
> 2012/6/10 Henrique Prange <[email protected]>:
>> Joseph,
>> 
>> I have created a issue [1] to track this problem.
>> 
>> There is a new commit in the hotfix-classloading branch that tries to solve 
>> the problem. It removes the dependency on a custom class loader. It's still 
>> very experimental, but I would like to know if this patch solves your 
>> problem.
>> 
>> There is one requirement: you have to create a AppRunner class, and start 
>> your application from it. Here is an example of a very simple runner:
>> 
>> public class AppRunner {
>>    public static void main(String[] args) {
>>        WOInject.init("your.app.Application", args);
>>    }
>> }
>> 
>> I've deployed a new WOInject SNAPSHOT to the WOCommunity repository. Just 
>> update to the 1.1-SNAPSHOT version in your pom to download the latest 
>> changes.
>> 
>> [1]https://github.com/hprange/woinject/issues/7
>> 
>> Cheers,
>> 
>> Henrique
>> 
>> On 07/06/2012, at 23:30, Henrique Prange wrote:
>> 
>>> 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