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]
