diff --git a/spring-webflow/changelog.txt b/spring-webflow/changelog.txt index 159879c6..10752431 100644 --- a/spring-webflow/changelog.txt +++ b/spring-webflow/changelog.txt @@ -46,7 +46,10 @@ Package org.springframework.webflow.engine Useful for testing (SWF-307). * Ensures that all exceptions (including RuntimeExceptions) are handled properly by the FlowExecution (SWF-333). * Ensured the RequestContext attribute map can never be null (SWF-347). - +* Renamed TransitionExecutingStateExceptionHandler to TransitionExecutingFlowExecutionExceptionHandler. + This handler now exposes the handled flow execution exception under the key "flowExecutionException" + instead of the key "stateException (SWF-281). + Package org.springframework.webflow.execution * Added a holder for the FlowExecutionContext of a request (SWF-163). * Made the Event class non-final to allow for extension (SWF-330). diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java index 96d23d85..3f72c355 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java @@ -73,7 +73,7 @@ import org.springframework.webflow.engine.support.BeanFactoryFlowVariable; import org.springframework.webflow.engine.support.BooleanExpressionTransitionCriteria; import org.springframework.webflow.engine.support.SimpleFlowVariable; import org.springframework.webflow.engine.support.TransitionCriteriaChain; -import org.springframework.webflow.engine.support.TransitionExecutingStateExceptionHandler; +import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler; import org.springframework.webflow.execution.Action; import org.springframework.webflow.execution.ScopeType; import org.springframework.webflow.util.ResourceHolder; @@ -1058,7 +1058,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder { } private FlowExecutionExceptionHandler parseTransitionExecutingExceptionHandler(Element element) { - TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler(); + TransitionExecutingFlowExecutionExceptionHandler handler = new TransitionExecutingFlowExecutionExceptionHandler(); Class exceptionClass = (Class) fromStringTo(Class.class).execute(element.getAttribute(ON_EXCEPTION_ATTRIBUTE)); TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(TargetStateResolver.class) .execute(element.getAttribute(TO_ATTRIBUTE)); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/support/TransitionExecutingStateExceptionHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/support/TransitionExecutingFlowExecutionExceptionHandler.java similarity index 83% rename from spring-webflow/src/main/java/org/springframework/webflow/engine/support/TransitionExecutingStateExceptionHandler.java rename to spring-webflow/src/main/java/org/springframework/webflow/engine/support/TransitionExecutingFlowExecutionExceptionHandler.java index 46c7dc72..c37e7f47 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/support/TransitionExecutingStateExceptionHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/support/TransitionExecutingFlowExecutionExceptionHandler.java @@ -34,24 +34,23 @@ import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.ViewSelection; /** - * A flow execution exception handler that maps the occurence of a specific type of exception to a transition to a new + * A flow execution exception handler that maps the occurrence of a specific type of exception to a transition to a new * {@link org.springframework.webflow.engine.State}. *

- * The handled {@link FlowExecutionException} will be exposed in flash scope as {@link #STATE_EXCEPTION_ATTRIBUTE}. The - * underlying root cause of that exception will be exposed in flash scope as {@link #ROOT_CAUSE_EXCEPTION_ATTRIBUTE}. + * The handled {@link FlowExecutionException} will be exposed in flash scope as + * {@link #FLOW_EXECUTION_EXCEPTION_ATTRIBUTE}. The underlying root cause of that exception will be exposed in flash + * scope as {@link #ROOT_CAUSE_EXCEPTION_ATTRIBUTE}. * * @author Keith Donald */ -public class TransitionExecutingStateExceptionHandler implements FlowExecutionExceptionHandler { +public class TransitionExecutingFlowExecutionExceptionHandler implements FlowExecutionExceptionHandler { - // this class should really have been called TransitionExecutingFlowExceptionHandler - - private static final Log logger = LogFactory.getLog(TransitionExecutingStateExceptionHandler.class); + private static final Log logger = LogFactory.getLog(TransitionExecutingFlowExecutionExceptionHandler.class); /** - * The name of the attribute to expose a handled exception under in flash scope ("stateException"). + * The name of the attribute to expose a handled exception under in flash scope ("flowExecutionException"). */ - public static final String STATE_EXCEPTION_ATTRIBUTE = "stateException"; + public static final String FLOW_EXECUTION_EXCEPTION_ATTRIBUTE = "flowExecutionException"; /** * The name of the attribute to expose a root cause of a handled exception under in flash scope @@ -60,7 +59,7 @@ public class TransitionExecutingStateExceptionHandler implements FlowExecutionEx public static final String ROOT_CAUSE_EXCEPTION_ATTRIBUTE = "rootCauseException"; /** - * The exceptionType->targetStateResolver map. + * The exceptionType to targetStateResolver map. */ private Map exceptionTargetStateMappings = new HashMap(); @@ -70,23 +69,24 @@ public class TransitionExecutingStateExceptionHandler implements FlowExecutionEx private ActionList actionList = new ActionList(); /** - * Adds an exception->state mapping to this handler. + * Adds an exception-to-target state mapping to this handler. * @param exceptionClass the type of exception to map * @param targetStateId the id of the state to transition to if the specified type of exception is handled * @return this handler, to allow for adding multiple mappings in a single statement */ - public TransitionExecutingStateExceptionHandler add(Class exceptionClass, String targetStateId) { + public TransitionExecutingFlowExecutionExceptionHandler add(Class exceptionClass, String targetStateId) { return add(exceptionClass, new DefaultTargetStateResolver(targetStateId)); } /** - * Adds a exception->state mapping to this handler. + * Adds a exception-to-target state resolver mapping to this handler. * @param exceptionClass the type of exception to map * @param targetStateResolver the resolver to calculate the state to transition to if the specified type of * exception is handled * @return this handler, to allow for adding multiple mappings in a single statement */ - public TransitionExecutingStateExceptionHandler add(Class exceptionClass, TargetStateResolver targetStateResolver) { + public TransitionExecutingFlowExecutionExceptionHandler add(Class exceptionClass, + TargetStateResolver targetStateResolver) { Assert.notNull(exceptionClass, "The exception class is required"); Assert.notNull(targetStateResolver, "The target state resolver is required"); exceptionTargetStateMappings.put(exceptionClass, targetStateResolver); @@ -106,7 +106,7 @@ public class TransitionExecutingStateExceptionHandler implements FlowExecutionEx public ViewSelection handle(FlowExecutionException exception, RequestControlContext context) { if (logger.isDebugEnabled()) { - logger.debug("Handling state exception " + exception, exception); + logger.debug("Handling flow execution exception " + exception, exception); } exposeException(context, exception, findRootCause(exception)); actionList.execute(context); @@ -122,14 +122,13 @@ public class TransitionExecutingStateExceptionHandler implements FlowExecutionEx * @param context the request control context * @param exception the exception being handled * @param rootCause root cause of the exception being handled (could be null) - * @since 1.0.2 */ protected void exposeException(RequestContext context, FlowExecutionException exception, Throwable rootCause) { // note that all Throwables are Serializable so putting them in flash // scope should not be a problem - context.getFlashScope().put(STATE_EXCEPTION_ATTRIBUTE, exception); + context.getFlashScope().put(FLOW_EXECUTION_EXCEPTION_ATTRIBUTE, exception); if (logger.isDebugEnabled()) { - logger.debug("Exposing state exception root cause " + rootCause + " under attribute '" + logger.debug("Exposing flow execution exception root cause " + rootCause + " under attribute '" + ROOT_CAUSE_EXCEPTION_ATTRIBUTE + "'"); } context.getFlashScope().put(ROOT_CAUSE_EXCEPTION_ATTRIBUTE, rootCause); @@ -257,7 +256,6 @@ public class TransitionExecutingStateExceptionHandler implements FlowExecutionEx } public String toString() { - return new ToStringCreator(this).append("exceptionTargetStateMappings", exceptionTargetStateMappings) - .toString(); + return new ToStringCreator(this).append("exceptionHandlingMappings", exceptionTargetStateMappings).toString(); } } \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowTests.java index 69f283b0..1bd25b0b 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/FlowTests.java @@ -32,7 +32,7 @@ import org.springframework.webflow.engine.support.BeanFactoryFlowVariable; import org.springframework.webflow.engine.support.DefaultTargetStateResolver; import org.springframework.webflow.engine.support.EventIdTransitionCriteria; import org.springframework.webflow.engine.support.SimpleFlowVariable; -import org.springframework.webflow.engine.support.TransitionExecutingStateExceptionHandler; +import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.FlowExecutionException; import org.springframework.webflow.execution.ScopeType; @@ -303,7 +303,7 @@ public class FlowTests extends TestCase { public void testHandleStateException() { flow.getExceptionHandlerSet().add( - new TransitionExecutingStateExceptionHandler().add(TestException.class, "myState2")); + new TransitionExecutingFlowExecutionExceptionHandler().add(TestException.class, "myState2")); MockRequestControlContext context = new MockRequestControlContext(flow); context.setCurrentState(flow.getStateInstance("myState1")); FlowExecutionException e = new FlowExecutionException(flow.getId(), flow.getStartState().getId(), "Oops!", diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilderTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilderTests.java index b1ea0028..3eed129d 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilderTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilderTests.java @@ -33,7 +33,7 @@ import org.springframework.webflow.engine.Transition; import org.springframework.webflow.engine.ViewState; import org.springframework.webflow.engine.builder.FlowAssembler; import org.springframework.webflow.engine.support.ApplicationViewSelector; -import org.springframework.webflow.engine.support.TransitionExecutingStateExceptionHandler; +import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.FlowExecutionException; import org.springframework.webflow.execution.ViewSelection; @@ -74,9 +74,9 @@ public class XmlFlowBuilderTests extends TestCase { assertEquals(1, flow.getStartActionList().size()); assertEquals(1, flow.getEndActionList().size()); assertEquals(2, flow.getExceptionHandlerSet().size()); - assertTrue(flow.getExceptionHandlerSet().toArray()[0] instanceof TransitionExecutingStateExceptionHandler); - assertTrue(flow.getExceptionHandlerSet().toArray()[1] instanceof TransitionExecutingStateExceptionHandler); - TransitionExecutingStateExceptionHandler handler = (TransitionExecutingStateExceptionHandler) flow + assertTrue(flow.getExceptionHandlerSet().toArray()[0] instanceof TransitionExecutingFlowExecutionExceptionHandler); + assertTrue(flow.getExceptionHandlerSet().toArray()[1] instanceof TransitionExecutingFlowExecutionExceptionHandler); + TransitionExecutingFlowExecutionExceptionHandler handler = (TransitionExecutingFlowExecutionExceptionHandler) flow .getExceptionHandlerSet().toArray()[1]; FlowExecutionException exception = new FlowExecutionException("testFlow1", "actionState1", "test", new IOException()); diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/FlowExecutionImplTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/FlowExecutionImplTests.java index 09cbeac7..3162fa93 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/FlowExecutionImplTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/FlowExecutionImplTests.java @@ -45,7 +45,7 @@ import org.springframework.webflow.engine.builder.xml.XmlFlowBuilderTests; import org.springframework.webflow.engine.support.ApplicationViewSelector; import org.springframework.webflow.engine.support.DefaultTargetStateResolver; import org.springframework.webflow.engine.support.EventIdTransitionCriteria; -import org.springframework.webflow.engine.support.TransitionExecutingStateExceptionHandler; +import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler; import org.springframework.webflow.execution.Action; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.FlowExecution; @@ -130,7 +130,7 @@ public class FlowExecutionImplTests extends TestCase { throw new IllegalStateException("Whoops!"); } }); - TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler(); + TransitionExecutingFlowExecutionExceptionHandler handler = new TransitionExecutingFlowExecutionExceptionHandler(); handler.add(Exception.class, "error"); endState.getExceptionHandlerSet().add(handler); diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/support/DefaultTargetStateResolverTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/support/DefaultTargetStateResolverTests.java index b82c3972..dcfa2eba 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/support/DefaultTargetStateResolverTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/support/DefaultTargetStateResolverTests.java @@ -75,7 +75,7 @@ public class DefaultTargetStateResolverTests extends AbstractFlowExecutionTests } public void buildExceptionHandlers() throws FlowBuilderException { - TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler(); + TransitionExecutingFlowExecutionExceptionHandler handler = new TransitionExecutingFlowExecutionExceptionHandler(); handler.add(UnsupportedOperationException.class, "stateC"); getFlow().getExceptionHandlerSet().add(handler); } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/support/TransitionExecutingStateExceptionHandlerTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/support/TransitionExecutingFlowExecutionExceptionHandlerTests.java similarity index 87% rename from spring-webflow/src/test/java/org/springframework/webflow/engine/support/TransitionExecutingStateExceptionHandlerTests.java rename to spring-webflow/src/test/java/org/springframework/webflow/engine/support/TransitionExecutingFlowExecutionExceptionHandlerTests.java index 8b032182..590ecdfb 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/support/TransitionExecutingStateExceptionHandlerTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/support/TransitionExecutingFlowExecutionExceptionHandlerTests.java @@ -44,7 +44,7 @@ import org.springframework.webflow.execution.ViewSelection; import org.springframework.webflow.execution.support.ApplicationView; import org.springframework.webflow.test.MockExternalContext; -public class TransitionExecutingStateExceptionHandlerTests extends TestCase { +public class TransitionExecutingFlowExecutionExceptionHandlerTests extends TestCase { Flow flow; @@ -61,7 +61,7 @@ public class TransitionExecutingStateExceptionHandlerTests extends TestCase { } public void testTransitionExecutorHandlesExceptionExactMatch() { - TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler(); + TransitionExecutingFlowExecutionExceptionHandler handler = new TransitionExecutingFlowExecutionExceptionHandler(); handler.add(TestException.class, "state"); FlowExecutionException e = new FlowExecutionException(state.getOwner().getId(), state.getId(), "Oops", new TestException()); @@ -72,7 +72,7 @@ public class TransitionExecutingStateExceptionHandlerTests extends TestCase { } public void testTransitionExecutorHandlesExceptionSuperclassMatch() { - TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler(); + TransitionExecutingFlowExecutionExceptionHandler handler = new TransitionExecutingFlowExecutionExceptionHandler(); handler.add(Exception.class, "state"); FlowExecutionException e = new FlowExecutionException(state.getOwner().getId(), state.getId(), "Oops", new TestException()); @@ -84,12 +84,12 @@ public class TransitionExecutingStateExceptionHandlerTests extends TestCase { public void testFlowStateExceptionHandlingTransition() { EndState state2 = new EndState(flow, "end"); state2.setViewSelector(new ApplicationViewSelector(new StaticExpression("view"))); - TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler(); + TransitionExecutingFlowExecutionExceptionHandler handler = new TransitionExecutingFlowExecutionExceptionHandler(); handler.add(TestException.class, "end"); flow.getExceptionHandlerSet().add(handler); FlowExecutionListener listener = new FlowExecutionListenerAdapter() { public void sessionEnding(RequestContext context, FlowSession session, MutableAttributeMap output) { - assertTrue(context.getFlashScope().contains("stateException")); + assertTrue(context.getFlashScope().contains("flowExecutionException")); assertTrue(context.getFlashScope().contains("rootCauseException")); assertTrue(context.getFlashScope().get("rootCauseException") instanceof TestException); } @@ -100,7 +100,7 @@ public class TransitionExecutingStateExceptionHandlerTests extends TestCase { } public void testStateExceptionHandlingTransitionNoSuchState() { - TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler(); + TransitionExecutingFlowExecutionExceptionHandler handler = new TransitionExecutingFlowExecutionExceptionHandler(); handler.add(TestException.class, "end"); flow.getExceptionHandlerSet().add(handler); FlowExecutionImpl execution = new FlowExecutionImpl(flow); @@ -135,7 +135,7 @@ public class TransitionExecutingStateExceptionHandlerTests extends TestCase { public void buildExceptionHandlers() throws FlowBuilderException { getFlow().getExceptionHandlerSet().add( - new TransitionExecutingStateExceptionHandler().add(Exception.class, "showError")); + new TransitionExecutingFlowExecutionExceptionHandler().add(Exception.class, "showError")); } }; Flow flow = new FlowAssembler("flow", builder).assembleFlow(); @@ -144,9 +144,9 @@ public class TransitionExecutingStateExceptionHandlerTests extends TestCase { assertTrue(execution.isActive()); assertEquals("error", ((ApplicationView) view).getViewName()); assertTrue(((ApplicationView) view).getModel().containsKey( - TransitionExecutingStateExceptionHandler.ROOT_CAUSE_EXCEPTION_ATTRIBUTE)); + TransitionExecutingFlowExecutionExceptionHandler.ROOT_CAUSE_EXCEPTION_ATTRIBUTE)); assertTrue(((ApplicationView) view).getModel().containsKey( - TransitionExecutingStateExceptionHandler.STATE_EXCEPTION_ATTRIBUTE)); + TransitionExecutingFlowExecutionExceptionHandler.FLOW_EXECUTION_EXCEPTION_ATTRIBUTE)); } protected TargetStateResolver toState(String stateId) {