Re: WOInject: harmed twice by classloader manipulation

2012-06-27 Thread Henrique Prange
Hi Joseph,

On 25/06/2012, at 10:57, Joseph Pachod wrote:

 
 HI Henrique
 
 I finally had the  time to test your changes, launching my app from
 another class than the application one.
 
 It works smoothly, so well done, thanks :)
 

Good to hear! :)

 Only issue left is how to tackle the integration of this fix. Indeed
 we have something like 300 launchers currently, all being in their
 application's class. I've to figure out a way to cleanly migrate them
 all. Or maybe you've a better way, if so let me know.
 

That's the drawback of this solution. I'll write a more general e-mail to the 
WO-dev list explaining the problem and asking for suggestions. I may be missing 
something obvious. For instance, maybe we could do something on the WOBootstrap 
level, but I'm not sure.

 Thanks again !
 
 As a side note: how are you able to figure out which class get loaded
 when precisely? I
 

I've enabled the log of class loading by passing the -verbose argument when 
running the app. The _NSUtilities class is loaded during the static 
initialization of ERXApplication or WOApplication when running the application 
through the main method of the Application class. So, it is too late to load 
the custom _NSUtilities even doing this as soon as possible. When running the 
application through the AppRunner the static initialization of those classes is 
delayed and it's possible to load a custom _NSUtilities without conflicts.

Cheers,

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

This email sent to arch...@mail-archive.com


Fwd: WOInject: harmed twice by classloader manipulation

2012-06-25 Thread Joseph Pachod
FI


-- Forwarded message --
From: Joseph Pachod jpac...@improve.fr
Date: 2012/6/25
Subject: Re: WOInject: harmed twice by classloader manipulation
To: Henrique Prange hpra...@gmail.com


HI Henrique

I finally had the  time to test your changes, launching my app from
another class than the application one.

It works smoothly, so well done, thanks :)

Only issue left is how to tackle the integration of this fix. Indeed
we have something like 300 launchers currently, all being in their
application's class. I've to figure out a way to cleanly migrate them
all. Or maybe you've a better way, if so let me know.

Thanks again !

As a side note: how are you able to figure out which class get loaded
when precisely? I

Best
Joseph

2012/6/18 Henrique Prange hpra...@gmail.com:
 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 hpra...@gmail.com:
 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

Re: WOInject: harmed twice by classloader manipulation

2012-06-13 Thread Joseph Pachod
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 hpra...@gmail.com:
 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 

Re: WOInject: harmed twice by classloader manipulation

2012-06-09 Thread Henrique Prange
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 

Re: WOInject: harmed twice by classloader manipulation

2012-06-07 Thread Henrique Prange
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 

WOInject: harmed twice by classloader manipulation

2012-06-06 Thread Joseph Pachod
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).

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?

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.

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 ?

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

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.

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.

Best,
joseph

The encryption error:
java.lang.SecurityException: JCE cannot authenticate the provider BC
at javax.crypto.Cipher.getInstance(DashoA13*..)
at 
org.bouncycastle.openpgp.PGPEncryptedDataGenerator$PubMethod.addSessionInfo(Unknown
Source)
at org.bouncycastle.openpgp.PGPEncryptedDataGenerator.open(Unknown 
Source)
at org.bouncycastle.openpgp.PGPEncryptedDataGenerator.open(Unknown 
Source)
at 
com.resurgences.xdi.invs.INVSService.encryptFile(INVSService.java:1571)
(...)
Caused by: java.util.jar.JarException: Class is on the bootclasspath
at javax.crypto.SunJCE_c.a(DashoA13*..)
at javax.crypto.SunJCE_b.b(DashoA13*..)
at javax.crypto.SunJCE_b.a(DashoA13*..)
 ___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com