Thomas Herzog created OWB-803:
---------------------------------
Summary: 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
Fix For: 1.1.8
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