Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
1.1.7
Description
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
"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; }
"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; }