From 281f745b18cb45c015b72cdc8e275441319dcacd Mon Sep 17 00:00:00 2001 From: Erwin Vervaet Date: Sat, 17 Mar 2007 12:40:56 +0000 Subject: [PATCH] FlowExecutionImpl.handleException() now also tries to handle FlowExecutionExceptions that occur during exception handling (SWF-261). --- spring-webflow/changelog.txt | 4 +++ .../engine/impl/FlowExecutionImpl.java | 20 +++++++---- .../engine/impl/ExceptionThrowingAction.java | 34 +++++++++++++++++++ .../engine/impl/FlowExecutionImplTests.java | 15 ++++++++ .../engine/impl/exceptionHandlingFlow.xml | 25 ++++++++++++++ .../webflow/engine/impl/testFlow.xml | 10 +++--- 6 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 spring-webflow/src/test/java/org/springframework/webflow/engine/impl/ExceptionThrowingAction.java create mode 100644 spring-webflow/src/test/java/org/springframework/webflow/engine/impl/exceptionHandlingFlow.xml diff --git a/spring-webflow/changelog.txt b/spring-webflow/changelog.txt index 332a27b7..b53abfa4 100644 --- a/spring-webflow/changelog.txt +++ b/spring-webflow/changelog.txt @@ -22,6 +22,10 @@ Package org.springframework.webflow.conversation * The SessionBindingConversationManager now re-binds the ConversationContainer in the session every time a contained conversation is unlocked (SWF-244). +Package org.springframework.webflow.engine +* FlowExecutionImpl.handleException() now also tries to handle FlowExecutionExceptions that + occur during exception handling (SWF-261). + Package org.springframework.webflow.execution * Added FlowExecutionListener.sessionCreated(RequestContext, FlowSession) callback, useful for setting flow attributes before the flow starts (SWF-223). diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/FlowExecutionImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/FlowExecutionImpl.java index 3ded37d6..918aea9e 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/FlowExecutionImpl.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/FlowExecutionImpl.java @@ -307,14 +307,20 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable { if (logger.isDebugEnabled()) { logger.debug("Attempting to handle [" + exception + "]"); } - // the state could be null if the flow was attempting a start operation - ViewSelection selectedView = tryStateHandlers(exception, context); - if (selectedView != null) { - return selectedView; + try { + // the state could be null if the flow was attempting a start operation + ViewSelection selectedView = tryStateHandlers(exception, context); + if (selectedView != null) { + return selectedView; + } + selectedView = tryFlowHandlers(exception, context); + if (selectedView != null) { + return selectedView; + } } - selectedView = tryFlowHandlers(exception, context); - if (selectedView != null) { - return selectedView; + catch (FlowExecutionException newException) { + // exception handling resulted in a new FlowExecutionException, try to handle it + return handleException(newException, context); } if (logger.isDebugEnabled()) { logger.debug("Rethrowing unhandled flow execution exception"); diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/ExceptionThrowingAction.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/ExceptionThrowingAction.java new file mode 100644 index 00000000..bbd92d1e --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/ExceptionThrowingAction.java @@ -0,0 +1,34 @@ +/* + * Copyright 2004-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.webflow.engine.impl; + +import org.springframework.webflow.action.AbstractAction; +import org.springframework.webflow.execution.Event; +import org.springframework.webflow.execution.RequestContext; + +/** + * Test action that throws an exception. + * + * @author Erwin Vervaet + */ +public class ExceptionThrowingAction extends AbstractAction { + + protected Event doExecute(RequestContext context) throws Exception { + Class exceptionType = Class.forName(context.getAttributes().getString("exceptionType")); + throw (Exception)exceptionType.newInstance(); + } + +} 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 823c9550..688ee1ea 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 @@ -50,8 +50,10 @@ import org.springframework.webflow.execution.FlowExecutionListener; import org.springframework.webflow.execution.MockFlowExecutionListener; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.TestAction; +import org.springframework.webflow.execution.ViewSelection; import org.springframework.webflow.execution.support.ApplicationView; import org.springframework.webflow.test.MockExternalContext; +import org.springframework.webflow.test.MockFlowServiceLocator; /** * General flow execution tests. @@ -61,6 +63,19 @@ import org.springframework.webflow.test.MockExternalContext; * @author Ben Hale */ public class FlowExecutionImplTests extends TestCase { + + public void testExceptionWhileHandlingException() { + MockFlowServiceLocator serviceLocator = new MockFlowServiceLocator(); + serviceLocator.registerBean("testAction", new ExceptionThrowingAction()); + XmlFlowBuilder flowBuilder = + new XmlFlowBuilder(new ClassPathResource("exceptionHandlingFlow.xml", this.getClass())); + flowBuilder.setFlowServiceLocator(serviceLocator); + Flow flow = new FlowAssembler("flow", flowBuilder).assembleFlow(); + FlowExecution flowExecution = new FlowExecutionImpl(flow); + ViewSelection view = flowExecution.start(null, new MockExternalContext()); + assertEquals("failed", ((ApplicationView)view).getViewName()); + assertFalse(flowExecution.isActive()); + } public void testFlowExecutionListener() { Flow flow = new Flow("myFlow"); diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/exceptionHandlingFlow.xml b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/exceptionHandlingFlow.xml new file mode 100644 index 00000000..19aa440a --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/exceptionHandlingFlow.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/testFlow.xml b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/testFlow.xml index 31ea9ebb..591f0347 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/testFlow.xml +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/testFlow.xml @@ -1,7 +1,9 @@ - - - + + +