SPR-6760: method called twice if exits via exception in a 'normal' case

This commit is contained in:
Andy Clement
2010-02-01 19:53:34 +00:00
parent e3cdabfaac
commit 4c35697c79
5 changed files with 194 additions and 4 deletions

View File

@@ -90,8 +90,28 @@ public class ConstructorReference extends SpelNodeImpl {
return executorToUse.execute(state.getEvaluationContext(), arguments);
}
catch (AccessException ae) {
// this is OK - it may have gone stale due to a class change,
// let's try to get a new one and call it before giving up
// Two reasons this can occur:
// 1. the method invoked actually threw a real exception
// 2. the method invoked was not passed the arguments it expected and has become 'stale'
// In the first case we should not retry, in the second case we should see if there is a
// better suited method.
// To determine which situation it is, the AccessException will contain a cause - this
// will be the exception thrown by the reflective invocation. Inside this exception there
// may or may not be a root cause. If there is a root cause it is a user created exception.
// If there is no root cause it was a reflective invocation problem.
Throwable causeOfAccessException = ae.getCause();
Throwable rootCause = (causeOfAccessException==null?null:causeOfAccessException.getCause());
if (rootCause!=null) {
// User exception was the root cause - exit now
String typename = (String) children[0].getValueInternal(state).getValue();
throw new SpelEvaluationException(getStartPosition(), rootCause, SpelMessage.CONSTRUCTOR_INVOCATION_PROBLEM,
typename,FormatHelper.formatMethodForMessage("", argumentTypes));
}
// at this point we know it wasn't a user problem so worth a retry if a better candidate can be found
this.cachedExecutor = null;
}
}

View File

@@ -77,8 +77,27 @@ public class MethodReference extends SpelNodeImpl {
state.getEvaluationContext(), state.getActiveContextObject().getValue(), arguments);
}
catch (AccessException ae) {
// this is OK - it may have gone stale due to a class change,
// let's try to get a new one and call it before giving up
// Two reasons this can occur:
// 1. the method invoked actually threw a real exception
// 2. the method invoked was not passed the arguments it expected and has become 'stale'
// In the first case we should not retry, in the second case we should see if there is a
// better suited method.
// To determine which situation it is, the AccessException will contain a cause - this
// will be the exception thrown by the reflective invocation. Inside this exception there
// may or may not be a root cause. If there is a root cause it is a user created exception.
// If there is no root cause it was a reflective invocation problem.
Throwable causeOfAccessException = ae.getCause();
Throwable rootCause = (causeOfAccessException==null?null:causeOfAccessException.getCause());
if (rootCause!=null) {
// User exception was the root cause - exit now
throw new SpelEvaluationException( getStartPosition(), rootCause, SpelMessage.EXCEPTION_DURING_METHOD_INVOCATION,
this.name, state.getActiveContextObject().getValue().getClass().getName(), rootCause.getMessage());
}
// at this point we know it wasn't a user problem so worth a retry if a better candidate can be found
this.cachedExecutor = null;
}
}