On May 21, 2008, at 5:04 PM, Dain Sundstrom wrote:

I think Rick may be able to provide more insight than me given his work on vm class loading, but I'll take a shot at this one....

I think the difference between the two exceptions is based on when the VM discovers it has an invalid class. The second exception shows us that the bad class is openejb.org.superbiz.cmp2.MovieBean, which is a class we generated directly using ASM. In "Style 1", I think something about the code in EjbHomeProxyHandler was causing the VM to perform a full verify on the class (FWIU the vm only verifies what is needs to improve VM startup time). Was EjbHomeProxyHandler doing something like scanning all the Method objects? Anyway, in "Style 1", for some reason the vm didn't have (or didn't provide) additional information about which class was having the error, which based on my coding experience is a pretty common situation. In "Style 2", the vm clearly knows what's going on and tells us everything necessary to fix the problem.

In the long term, we could catch this problem with the verifier or if they turn that off, we could just fill in a do nothing implementation.

Huh. Not sure. We're talking about zero code change anywhere in anything (even the test case) other than the following patch.

Index: src/main/java/org/apache/openejb/core/ivm/ EjbHomeProxyHandler.java
===================================================================
--- src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java (revision 655683) +++ src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java (working copy)
@@ -210,7 +210,7 @@
if (cause instanceof RemoteException && interfaceType.isLocal()) {
                 RemoteException re = (RemoteException) cause;
Throwable detail = (re.detail != null) ? re.detail : re; - cause = new EJBException(re.getMessage(), (Exception) detail); + cause = new EJBException(re.getMessage()).initCause(detail);
             }
             throw cause;
             /*

I'm not sure how class verification, etc. could be affected. Taking a fresh look at this, the ClassCastException part of Style 1 looks awfully fishy...

Yea, that's it.  Can't believe I missed it.

-David





-dain

On May 21, 2008, at 4:52 PM, David Blevins wrote:

There seems to be some major difference between these two styles of EJBException creation. I ran into this working on a CMP example I intend to use for the whole CMP+JPA->JPA merging logic. The real error is that I forgot to implement "setEntityContext" which is an easy mistake to make as the CMP2 bean class is abstract and compiles just fine without it. I got the first stack trace below, which is useless, and decided on a whim to tweak EjbHomeProxyHandler line 213 to the second style shown below. I was and am shocked at the difference in the stack trace.

[Style 1] throw new EJBException(re.getMessage(), (Exception) detail);
Yields:
java.lang.ClassCastException: java.lang.AbstractMethodError
at org .apache .openejb .core.ivm.EjbHomeProxyHandler._invoke(EjbHomeProxyHandler.java:213) at org .apache .openejb .core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:274)
        at org.superbiz.cmp2.$Proxy26.create(Unknown Source)
        at org.superbiz.cmp2.MoviesTest.test(MoviesTest.java:51)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun .reflect .NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun .reflect .DelegatingMethodAccessorImpl .invoke(DelegatingMethodAccessorImpl.java:25) at com .intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:32)


[Style 2] throw new EJBException(re.getMessage()).initCause(detail);
Yields:

javax.ejb.EJBException: The bean encountered a non-application exception.; nested exception is: java.lang.AbstractMethodError: openejb.org.superbiz.cmp2.MovieBean.setEntityContext(Ljavax/ejb/ EntityContext;)V at org .apache .openejb .core.ivm.EjbHomeProxyHandler._invoke(EjbHomeProxyHandler.java:213) at org .apache .openejb .core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:274)
        at org.superbiz.cmp2.$Proxy26.create(Unknown Source)
        at org.superbiz.cmp2.MoviesTest.test(MoviesTest.java:51)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun .reflect .NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun .reflect .DelegatingMethodAccessorImpl .invoke(DelegatingMethodAccessorImpl.java:25) at com .intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:32) Caused by: java.lang.AbstractMethodError: openejb.org.superbiz.cmp2.MovieBean.setEntityContext(Ljavax/ejb/ EntityContext;)V at org .apache .openejb.core.cmp.CmpContainer.setEntityContext(CmpContainer.java: 318) at org .apache .openejb.core.cmp.CmpContainer.createEJBObject(CmpContainer.java:592) at org.apache.openejb.core.cmp.CmpContainer.invoke(CmpContainer.java: 250) at org .apache .openejb .core.ivm.EjbHomeProxyHandler.create(EjbHomeProxyHandler.java:267) at org .apache .openejb .core.ivm.EjbHomeProxyHandler._invoke(EjbHomeProxyHandler.java:158)
        ... 21 more


Able to verify the stack trace behavior is this way in both intellij and maven. Obviously the stack trace for style #1 completely obfuscates the problem which is itself a big problem.

Anyone have any idea, what causes this difference?

Needless to say, I'll shortly be switching all our code over....

-David




Reply via email to