From a0c26d52d329960e67ffeea5ccca9bd0b007f87e Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Fri, 18 Apr 2008 14:48:53 +0000 Subject: [PATCH] exception handler fix and tests --- .../builder/model/FlowModelFlowBuilder.java | 2 +- .../engine/model/ExceptionHandlerModel.java | 27 ++++++++----------- .../builder/xml/XmlFlowModelBuilder.java | 24 +++++++++++++---- .../model/builder/xml/spring-webflow-2.0.xsd | 18 +++---------- .../model/FlowModelFlowBuilderTests.java | 24 +++++++++++++++++ .../builder/xml/XmlFlowModelBuilderTests.java | 19 +++++++++++++ .../builder/xml/flow-exception-handler.xml | 27 +++++++++++++++++++ 7 files changed, 105 insertions(+), 36 deletions(-) create mode 100644 spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-exception-handler.xml diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.java index e0ad0a69..27249b2b 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.java @@ -745,7 +745,7 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder { private FlowExecutionExceptionHandler parseCustomExceptionHandler(ExceptionHandlerModel exceptionHandler) { return (FlowExecutionExceptionHandler) getLocalContext().getApplicationContext().getBean( - exceptionHandler.getBeanName(), FlowExecutionExceptionHandler.class); + exceptionHandler.getBean(), FlowExecutionExceptionHandler.class); } private Transition[] parseTransitions(List transitionModels) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/ExceptionHandlerModel.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/ExceptionHandlerModel.java index 38657e30..e756874d 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/ExceptionHandlerModel.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/ExceptionHandlerModel.java @@ -25,14 +25,15 @@ import org.springframework.util.StringUtils; * @author Scott Andrews */ public class ExceptionHandlerModel extends AbstractModel { - private String beanName; + + private String bean; /** * Create an exception handler model - * @param beanName the name of the bean to handle exceptions + * @param bean the name of the bean to handle exceptions */ - public ExceptionHandlerModel(String beanName) { - setBeanName(beanName); + public ExceptionHandlerModel(String bean) { + setBean(bean); } public boolean isMergeableWith(Model model) { @@ -42,21 +43,15 @@ public class ExceptionHandlerModel extends AbstractModel { public void merge(Model model) { } - /** - * @return the bean name - */ - public String getBeanName() { - return beanName; + public String getBean() { + return bean; } - /** - * @param beanName the bean name to set - */ - public void setBeanName(String beanName) { - if (StringUtils.hasText(beanName)) { - this.beanName = beanName; + public void setBean(String bean) { + if (StringUtils.hasText(bean)) { + this.bean = bean; } else { - this.beanName = null; + this.bean = null; } } } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilder.java index a9066acb..4fb689cf 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilder.java @@ -80,12 +80,20 @@ public class XmlFlowModelBuilder implements FlowModelBuilder { /** * Create a new XML flow model builder that will parse the XML document at the specified resource location and use * the provided locator to access parent flow models. + * @param resource the path to the XML flow definition (required) + */ + public XmlFlowModelBuilder(Resource resource) { + init(resource, null); + } + + /** + * Create a new XML flow model builder that will parse the XML document at the specified resource location and use + * the provided locator to access parent flow models. + * @param resource the path to the XML flow definition (required) + * @param modelLocator a locator for parent flow models to support flow inheritance */ public XmlFlowModelBuilder(Resource resource, FlowModelLocator modelLocator) { - Assert.notNull(resource, "The location of the XML-based flow definition is required"); - Assert.notNull(modelLocator, "The model locator for accessing other flow models for merging is required"); - this.resource = resource; - this.modelLocator = modelLocator; + init(resource, modelLocator); } /** @@ -214,6 +222,12 @@ public class XmlFlowModelBuilder implements FlowModelBuilder { return document != null ? document.getDocumentElement() : null; } + private void init(Resource resource, FlowModelLocator modelLocator) { + Assert.notNull(resource, "The location of the XML-based flow definition is required"); + this.resource = resource; + this.modelLocator = modelLocator; + } + private FlowModel parseFlow(Element element) { FlowModel flow = new FlowModel(); flow.setAbstract(element.getAttribute("abstract")); @@ -462,7 +476,7 @@ public class XmlFlowModelBuilder implements FlowModelBuilder { } private ExceptionHandlerModel parseExceptionHandler(Element element) { - return new ExceptionHandlerModel(element.getAttribute("bean-name")); + return new ExceptionHandlerModel(element.getAttribute("bean")); } private BeanImportModel parseBeanImport(Element element) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/spring-webflow-2.0.xsd b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/spring-webflow-2.0.xsd index 935e6d4d..806d31aa 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/spring-webflow-2.0.xsd +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/spring-webflow-2.0.xsd @@ -202,7 +202,7 @@ Actions to execute when this state is entered. - + @@ -1438,20 +1438,10 @@ The bean id of the custom exception handler. -WARNING: This element will only configure a security attribute in the definition. The flow execution must also be secured with a SecurityFlowExecutionListener. -
-For example: -
-	<web:flow-executor id="flowExecutor" flow-registry="flowRegistry">
-		<web:flow-execution-listeners>
-			<web:listener ref="securityFlowExecutionListener" />
-		</web:flow-execution-listeners>
-	</web:flow-executor>
-	
-	<bean id="securityFlowExecutionListener" class="org.springframework.webflow.security.SecurityFlowExecutionListener" />
-
+Note: This element configures a meta-attribute. +For the attribute to be enforced, the flow execution must be observed by a SecurityFlowExecutionListener. ]]>
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilderTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilderTests.java index 9bb45911..68ce7b4d 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilderTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilderTests.java @@ -10,14 +10,17 @@ import org.springframework.webflow.action.FlowDefinitionRedirectAction; import org.springframework.webflow.core.collection.LocalAttributeMap; import org.springframework.webflow.core.collection.MutableAttributeMap; import org.springframework.webflow.engine.Flow; +import org.springframework.webflow.engine.FlowExecutionExceptionHandler; import org.springframework.webflow.engine.FlowInputMappingException; import org.springframework.webflow.engine.FlowOutputMappingException; +import org.springframework.webflow.engine.RequestControlContext; import org.springframework.webflow.engine.ViewState; import org.springframework.webflow.engine.builder.FlowAssembler; import org.springframework.webflow.engine.builder.FlowBuilderException; import org.springframework.webflow.engine.impl.FlowExecutionImplFactory; import org.springframework.webflow.engine.model.AttributeModel; import org.springframework.webflow.engine.model.EndStateModel; +import org.springframework.webflow.engine.model.ExceptionHandlerModel; import org.springframework.webflow.engine.model.FlowModel; import org.springframework.webflow.engine.model.InputModel; import org.springframework.webflow.engine.model.OutputModel; @@ -34,6 +37,7 @@ import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl; import org.springframework.webflow.engine.support.ActionExecutingViewFactory; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.FlowExecution; +import org.springframework.webflow.execution.FlowExecutionException; import org.springframework.webflow.execution.ViewFactory; import org.springframework.webflow.security.SecurityRule; import org.springframework.webflow.test.MockExternalContext; @@ -336,6 +340,26 @@ public class FlowModelFlowBuilderTests extends TestCase { } } + public void testExceptionHandlers() { + FlowModel model = new FlowModel(); + model.addState(new EndStateModel("state")); + model.addExceptionHandler(new ExceptionHandlerModel("exceptionHandler")); + FlowExecutionExceptionHandler handler = new FlowExecutionExceptionHandler() { + public boolean canHandle(FlowExecutionException exception) { + return true; + } + + public void handle(FlowExecutionException exception, RequestControlContext context) { + } + }; + FlowModelFlowBuilder builder = new FlowModelFlowBuilder(new StaticFlowModelHolder(model)); + MockFlowBuilderContext context = new MockFlowBuilderContext("foo"); + context.registerBean("exceptionHandler", handler); + FlowAssembler assembler = new FlowAssembler(builder, context); + Flow flow = assembler.assembleFlow(); + assertEquals(1, flow.getExceptionHandlerSet().size()); + } + private Flow getFlow(FlowModel model) { FlowModelHolder holder = new StaticFlowModelHolder(model); FlowModelFlowBuilder builder = new FlowModelFlowBuilder(holder); diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilderTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilderTests.java index 0b54f4a0..de4bf7b4 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilderTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilderTests.java @@ -12,6 +12,7 @@ import org.springframework.webflow.engine.builder.model.FlowModelFlowBuilder; import org.springframework.webflow.engine.impl.FlowExecutionImplFactory; import org.springframework.webflow.engine.model.AbstractStateModel; import org.springframework.webflow.engine.model.AttributeModel; +import org.springframework.webflow.engine.model.ExceptionHandlerModel; import org.springframework.webflow.engine.model.FlowModel; import org.springframework.webflow.engine.model.SecuredModel; import org.springframework.webflow.engine.model.TransitionModel; @@ -268,6 +269,24 @@ public class XmlFlowModelBuilderTests extends TestCase { } } + public void testParseFlowExceptionHandler() { + ClassPathResource res = new ClassPathResource("flow-exception-handler.xml", getClass()); + XmlFlowModelBuilder builder = new XmlFlowModelBuilder(res); + DefaultFlowModelHolder holder = new DefaultFlowModelHolder(builder); + FlowModel model = holder.getFlowModel(); + assertEquals("foo1", ((ExceptionHandlerModel) model.getExceptionHandlers().get(0)).getBean()); + assertEquals("foo2", ((ExceptionHandlerModel) model.getStateById("state1").getExceptionHandlers().get(0)) + .getBean()); + assertEquals("foo3", ((ExceptionHandlerModel) model.getStateById("state2").getExceptionHandlers().get(0)) + .getBean()); + assertEquals("foo4", ((ExceptionHandlerModel) model.getStateById("state3").getExceptionHandlers().get(0)) + .getBean()); + assertEquals("foo5", ((ExceptionHandlerModel) model.getStateById("state4").getExceptionHandlers().get(0)) + .getBean()); + assertEquals("foo6", ((ExceptionHandlerModel) model.getStateById("state5").getExceptionHandlers().get(0)) + .getBean()); + } + public void testFormActionValidatorMethod() { ClassPathResource resource = new ClassPathResource("flow-formaction-validatormethod.xml", getClass()); XmlFlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry); diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-exception-handler.xml b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-exception-handler.xml new file mode 100644 index 00000000..a94ff736 --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-exception-handler.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file