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