[ 
https://issues.apache.org/jira/browse/OWB-803?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Thomas Herzog updated OWB-803:
------------------------------

    Attachment: DecoratorForeverLoopDemo.zip

Here the demo app which illustrates this issue.
The issue can be reproduced when you run the included test class.

Comment the testNotDecorated method out and you will see the test will run.
Uncomment this method and the test will hung as described in the issue.
                
> Forever loop when abstract decorator does not implement invoked method
> ----------------------------------------------------------------------
>
>                 Key: OWB-803
>                 URL: https://issues.apache.org/jira/browse/OWB-803
>             Project: OpenWebBeans
>          Issue Type: Bug
>          Components: Interceptor and Decorators
>    Affects Versions: 1.1.7
>            Reporter: Thomas Herzog
>              Labels: decorator
>             Fix For: 1.1.8
>
>         Attachments: DecoratorForeverLoopDemo.zip
>
>
> If there is a decorated service, where the decorator is abstract and does not 
> implement all methods of the interface,
> then there will occur a forever loop within the 
> org.apache.webbeans.decorator.DelegateHandler#invoke(Object instance, Method 
> method, Object[] arguments) (line: 89),
> if a method, which is not implemented in the abstract decorator, is tried to 
> be invoked on the proxied decorator instance.
> This occured within the openEjb-Lite 4.5.1 which uses openwebbeans 1.1.7.
> As we have seen, owb 1.1.6 did implement it differently, so we switched back 
> to OpebEjb-lite 4.5.0 which uses openwebbeans 1.1.6
> {code:title="org.apache.webbeans.decorator.DelegateHandler#invoke(Object 
> instance, Method method, Object[] arguments) openwebbeans 1.1.7"}
>  public Object invoke(Object instance, Method method, Object[] arguments) 
> throws Exception
>     {
>         // Tuck away a reference to the bean being Decorated
>         if (actualInstance == null)
>         {
>             actualInstance = instance;
>         }
>         int hit = 0;
>         int decoratorsSize = decorators.size();
>         while (position.get().intValue() < decoratorsSize)
>         {
>             hit++;
>             // !!!!!! Current position will always be 1, this part is 
> implemented differntly in 1.1.6  !!!!!!
>             int currentPosition = position.get().intValue();
>             Object decorator = 
> decorators.get(position.get().getAndIncrement());
>             try
>             {
>                 Method decMethod = 
> decorator.getClass().getMethod(method.getName(), method.getParameterTypes());
>                 boolean methodInInterface = 
> checkForMethodInInterfaces(decorator.getClass(), method);
>                 if (decMethod != null && methodInInterface)
>                 {
>                     if (!decMethod.isAccessible())
>                     {
>                         
> bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(decMethod,
>  true);
>                     }
>                     try
>                     {
>                         return decMethod.invoke(decorator, arguments);
>                     }
>                     finally
>                     {
>                         if (currentPosition == 0) // if we go back on the 
> first decorator no more need of this thread local
>                         {
>                             position.remove();
>                         }
>                     }
>                 }
>             }
>             catch (SecurityException e)
>             {
>                 logger.log(Level.SEVERE, OWBLogConst.ERROR_0011, 
> WebBeansLoggerFacade.args(method.getName(), decorator.getClass().getName()));
>                 throw new WebBeansException(e);
>             }
>             catch (NoSuchMethodException e)
>             {
>                 continue;
>             }
>             catch (InvocationTargetException e)
>             {
>                 Throwable cause = e.getCause();
>                 //If the wrapped exception tells us the method didn't exist, 
> continue
>                 if(cause instanceof NoSuchMethodException)
>                 {
>                     continue;
>                 }
>                 logger.log(Level.SEVERE, OWBLogConst.ERROR_0012, 
> WebBeansLoggerFacade.args(e.getTargetException(), method.getName(), 
> decorator.getClass().getName()));
>                 if (cause instanceof Exception)
>                 {
>                     throw (Exception) cause;
>                 }
>                 else if (cause instanceof Error)
>                 {
>                     throw (Error) cause;
>                 }
>                 else
>                 {
>                     throw new WebBeansException(e);
>                 }
>             }
>             catch (IllegalAccessException e)
>             {
>                 logger.log(Level.SEVERE, OWBLogConst.ERROR_0014, 
> WebBeansLoggerFacade.args(method.getName(), decorator.getClass().getName()));
>                 throw new WebBeansException(e);
>             }
>         }
>         if (hit == decoratorsSize) // if we hit all decorators but noone was 
> called (see while loop) then clean here
>         {
>             position.remove();
>         }
>         if (!method.isAccessible())
>         {
>             
> bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(method,
>  true);
>         }
>         Object result = null;
>         
>         if(!(bean instanceof EnterpriseBeanMarker))
>         {
>             result = method.invoke(actualInstance, arguments);
>         }
>         else
>         {
>             if(ejbContext != null)
>             {
>                 Method ejbMethod = ejbContext.getMethod();
>                 
>                 // don't use method.equals(), it may only differ by being 
> abstract in the EJB proxy.
>                  
>                 if (method.getName().equals(ejbMethod.getName()) && 
>                         
> method.getReturnType().equals(ejbMethod.getReturnType())) 
>                 {
>                     result = ejbContext.proceed();
>                 }
>                 else 
>                 {
>                     Object ejbInstance = ejbContext.getTarget();
>                     result = method.invoke(ejbInstance, arguments);
>                 }
>             }
>         }
>         return result;
>     }
> {code}
> {code:title="org.apache.webbeans.decorator.DelegateHandler#invoke(Object 
> instance, Method method, Object[] arguments) openwebbeans 1.1.6"}
>    public Object invoke(Object instance, Method method, Object[] arguments) 
> throws Exception
>     {
>         // Tuck away a reference to the bean being Decorated
>         if (actualInstance == null)
>         {
>             actualInstance = instance;
>         }
>         while (position.get().intValue() < decorators.size())
>         {
>                   // !!!! No current position occurs here !!!!!
>                       // !!!! This works when not implemented method of 
> abstract decorator is tried to be invoked !!!!!
>             Object decorator = 
> decorators.get(position.get().getAndIncrement());
>             try
>             {
>                 Method decMethod = 
> decorator.getClass().getMethod(method.getName(), method.getParameterTypes());
>                 boolean methodInInterface = 
> checkForMethodInInterfaces(decorator.getClass(), method);
>                 if (decMethod != null && methodInInterface)
>                 {
>                     if (!decMethod.isAccessible())
>                     {
>                         
> bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(decMethod,
>  true);
>                     }
>                     Object returnValue = decMethod.invoke(decorator, 
> arguments);
>                     position.remove();
>                     return returnValue;
>                 }
>             }
>             catch (SecurityException e)
>             {
>                 logger.log(Level.SEVERE, OWBLogConst.ERROR_0011, 
> WebBeansLoggerFacade.args(method.getName(), decorator.getClass().getName()));
>                 throw new WebBeansException(e);
>             }
>             catch (NoSuchMethodException e)
>             {
>                 continue;
>             }
>             catch (InvocationTargetException e)
>             {
>                 Throwable cause = e.getCause();
>                 //If the wrapped exception tells us the method didn't exist, 
> continue
>                 if(cause instanceof NoSuchMethodException)
>                 {
>                     continue;
>                 }
>                 logger.log(Level.SEVERE, OWBLogConst.ERROR_0012, 
> WebBeansLoggerFacade.args(e.getTargetException(), method.getName(), 
> decorator.getClass().getName()));
>                 if (cause instanceof Exception)
>                 {
>                     throw (Exception) cause;
>                 }
>                 else if (cause instanceof Error)
>                 {
>                     throw (Error) cause;
>                 }
>                 else
>                 {
>                     throw new WebBeansException(e);
>                 }
>             }
>             catch (IllegalAccessException e)
>             {
>                 logger.log(Level.SEVERE, OWBLogConst.ERROR_0014, 
> WebBeansLoggerFacade.args(method.getName(), decorator.getClass().getName()));
>                 throw new WebBeansException(e);
>             }
>         }
>         position.remove();
>         if (!method.isAccessible())
>         {
>             
> bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(method,
>  true);
>         }
>         Object result = null;
>         
>         if(!(bean instanceof EnterpriseBeanMarker))
>         {
>             result = method.invoke(actualInstance, arguments);
>         }
>         else
>         {
>             if(ejbContext != null)
>             {
>                 Method ejbMethod = ejbContext.getMethod();
>                 
>                 // don't use method.equals(), it may only differ by being 
> abstract in the EJB proxy.
>                  
>                 if (method.getName().equals(ejbMethod.getName()) && 
>                         
> method.getReturnType().equals(ejbMethod.getReturnType())) 
>                 {
>                     result = ejbContext.proceed();
>                 }
>                 else 
>                 {
>                     Object ejbInstance = ejbContext.getTarget();
>                     result = method.invoke(ejbInstance, arguments);
>                 }
>             }
>         }
>         
>         return result;
>     }
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to