You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomee.apache.org by Shawn Jiang <ge...@gmail.com> on 2011/05/19 09:25:40 UTC

org.apache.openejb.core.interceptor.ReflectionInvocation can not access a member of class org.apache.geronimo.ejb.timer.TestTimeoutBean with modifiers "private"

This is a new regression I found in openejb trunk.     A private method of
EJB is defined in ejb-jar.xml as timeout method.      It's legal from ejb 31
spec.18.2.5.3

"A timeout callback method can have public, private, protected, or package
level access. A timeout callback method must not be declared as final or
static."


In our code,   we have logic to set the private method accessible.

org.apache.openejb.assembler.classic.MethodScheduleBuilder.build(BeanContext,
EnterpriseBeanInfo)
{

......

//get the timeout method from the info in DD or annotation.
 timeoutMethodOfSchedule = MethodInfoUtil.toMethod(clazz, info.method);

//set the method accessible so that we could call it even it's a private
method.
 SetAccessible.on(timeoutMethodOfSchedule);
.....

}


It used to work well.    And I can confirm these logic was executed when I
debug into it.     Can anyone shed some light on this ?   At least,   how
could I tell if the private method was accessible after calling
SetAccessible.on() to it ?


I will open a jira and attach the sample ejb jar with source code.



------------------------------------------------------------------------------------
2011-05-19 15:17:30,308 WARN  [Timer] Exception from ejbTimeout on
timerEJB.jar/TestTimeoutBean
org.apache.openejb.ApplicationException: java.lang.IllegalAccessException:
Class
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocat
 a member of class org.apache.geronimo.ejb.timer.TestTimeoutBean with
modifiers "private": Class
org.apache.openejb.core.interceptor.ReflectionInvocatio
n can not access a member of class
org.apache.geronimo.ejb.timer.TestTimeoutBean with modifiers "private"
        at
org.apache.openejb.core.transaction.EjbTransactionUtil.handleApplicationException(EjbTransactionUtil.java:122)
        at
org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:240)
        at
org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:176)
        at
org.apache.openejb.core.timer.EjbTimerServiceImpl.ejbTimeout(EjbTimerServiceImpl.java:332)
        at
org.apache.openejb.core.timer.EjbTimeoutJob.execute(EjbTimeoutJob.java:39)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
        at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.IllegalAccessException: Class
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation
can not access a member of
geronimo.ejb.timer.TestTimeoutBean with modifiers "private"
        at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
        at java.lang.reflect.Method.invoke(Method.java:588)
        at
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:182)
        at
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:164)
        at
org.apache.openejb.monitoring.StatsInterceptor.record(StatsInterceptor.java:174)
        at
org.apache.openejb.monitoring.StatsInterceptor.AroundTimeout(StatsInterceptor.java:138)
        at sun.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)
        at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:182)
        at
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:164)
        at
org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:126)
        at
org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:224)

-- 
Shawn

Re: org.apache.openejb.core.interceptor.ReflectionInvocation can not access a member of class org.apache.geronimo.ejb.timer.TestTimeoutBean with modifiers "private"

Posted by Shawn Jiang <ge...@gmail.com>.
I opened a JIRA and attached the ejb jar to recreate this.
https://issues.apache.org/jira/browse/OPENEJB-1552

Ivan pointed out that Method..isAccessible()  could be used to tell if the
Method is set to accessble succesfully.   with the info, I debug it further
and found the accessble timeout method is not stored into beanContext at
all.

Following code in BeanContext is used to store method context info at build
time.

 public MethodContext getMethodContext(Method method) {
        MethodContext methodContext = methodContextMap.get(method);
        if (methodContext == null) {
            methodContext = new MethodContext(this, method);
            methodContextMap.put(method, methodContext);
        }
        return methodContext;
    }


Because in
org.apache.openejb.assembler.classic.InterceptorBindingBuilder.build(BeanContext,
EnterpriseBeanInfo) ,   all method is stored in methodContextMap when
building interceptorDatas for EJB.   The method(method Object 1) was not set
accessible because the method in interceptor build here is not callback
itself.

After that,  MethodScheduleBuilder.build() will get another method(method
Object 2) with reflection.   and then set it to accessible.  Method(Method
Object 2) does not get set to beancontext because

methodContextMap.get(method) != null  due to same hash code for method
Object1 and Object 2.       As a result,  the first inaccessible method will
be used to construct the timerdata and then be invoked.

A simple patch to setAccessible just before calling timeout method could
solve this.    But I'm wondering  if we need to differentiate methods with
different accessible status so that they won't be only one state method in
method context map of beanContext ?



On Thu, May 19, 2011 at 3:25 PM, Shawn Jiang <ge...@gmail.com> wrote:

> This is a new regression I found in openejb trunk.     A private method of
> EJB is defined in ejb-jar.xml as timeout method.      It's legal from ejb 31
> spec.18.2.5.3
>
> "A timeout callback method can have public, private, protected, or package
> level access. A timeout callback method must not be declared as final or
> static."
>
>
> In our code,   we have logic to set the private method accessible.
>
> org.apache.openejb.assembler.classic.MethodScheduleBuilder.build(BeanContext,
> EnterpriseBeanInfo)
> {
>
> ......
>
> //get the timeout method from the info in DD or annotation.
>  timeoutMethodOfSchedule = MethodInfoUtil.toMethod(clazz, info.method);
>
> //set the method accessible so that we could call it even it's a private
> method.
>  SetAccessible.on(timeoutMethodOfSchedule);
> .....
>
> }
>
>
> It used to work well.    And I can confirm these logic was executed when I
> debug into it.     Can anyone shed some light on this ?   At least,   how
> could I tell if the private method was accessible after calling
> SetAccessible.on() to it ?
>
>
> I will open a jira and attach the sample ejb jar with source code.
>
>
>
>
> ------------------------------------------------------------------------------------
> 2011-05-19 15:17:30,308 WARN  [Timer] Exception from ejbTimeout on
> timerEJB.jar/TestTimeoutBean
> org.apache.openejb.ApplicationException: java.lang.IllegalAccessException:
> Class
> org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocat
>  a member of class org.apache.geronimo.ejb.timer.TestTimeoutBean with
> modifiers "private": Class
> org.apache.openejb.core.interceptor.ReflectionInvocatio
> n can not access a member of class
> org.apache.geronimo.ejb.timer.TestTimeoutBean with modifiers "private"
>         at
> org.apache.openejb.core.transaction.EjbTransactionUtil.handleApplicationException(EjbTransactionUtil.java:122)
>         at
> org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:240)
>         at
> org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:176)
>         at
> org.apache.openejb.core.timer.EjbTimerServiceImpl.ejbTimeout(EjbTimerServiceImpl.java:332)
>         at
> org.apache.openejb.core.timer.EjbTimeoutJob.execute(EjbTimeoutJob.java:39)
>         at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
>         at
> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
>         at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
>         at java.lang.Thread.run(Thread.java:619)
> Caused by: java.lang.IllegalAccessException: Class
> org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation
> can not access a member of
> geronimo.ejb.timer.TestTimeoutBean with modifiers "private"
>         at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
>         at java.lang.reflect.Method.invoke(Method.java:588)
>         at
> org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:182)
>         at
> org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:164)
>         at
> org.apache.openejb.monitoring.StatsInterceptor.record(StatsInterceptor.java:174)
>         at
> org.apache.openejb.monitoring.StatsInterceptor.AroundTimeout(StatsInterceptor.java:138)
>         at sun.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)
>         at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>         at java.lang.reflect.Method.invoke(Method.java:597)
>         at
> org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:182)
>         at
> org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:164)
>         at
> org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:126)
>         at
> org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:224)
>
> --
> Shawn
>



-- 
Shawn