exception handler fix and tests
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -202,7 +202,7 @@ Actions to execute when this state is entered.
|
||||
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
|
||||
<xsd:group ref="actionTypes" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="transition" type="transition" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -1438,20 +1438,10 @@ The bean id of the custom exception handler.
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Secures this flow definition element.
|
||||
The user invoking this element must meet the required attributes otherwise access to the element will be denied.
|
||||
The current user invoking this element must have the required security attributes otherwise access to the element will be denied.
|
||||
<br>
|
||||
WARNING: This element will only configure a security attribute in the definition. The flow execution must also be secured with a SecurityFlowExecutionListener.
|
||||
<br>
|
||||
For example:
|
||||
<pre>
|
||||
<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" />
|
||||
</pre>
|
||||
Note: This element configures a meta-attribute.
|
||||
For the attribute to be enforced, the flow execution must be observed by a SecurityFlowExecutionListener.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<flow xmlns="http://www.springframework.org/schema/webflow"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
|
||||
|
||||
<view-state id="state1">
|
||||
<exception-handler bean="foo2"/>
|
||||
</view-state>
|
||||
|
||||
<action-state id="state2">
|
||||
<exception-handler bean="foo3"/>
|
||||
</action-state>
|
||||
|
||||
<subflow-state id="state3">
|
||||
<exception-handler bean="foo4"/>
|
||||
</subflow-state>
|
||||
|
||||
<decision-state id="state4">
|
||||
<exception-handler bean="foo5"/>
|
||||
</decision-state>
|
||||
|
||||
<end-state id="state5">
|
||||
<exception-handler bean="foo6"/>
|
||||
</end-state>
|
||||
|
||||
<exception-handler bean="foo1"/>
|
||||
|
||||
</flow>
|
||||
Reference in New Issue
Block a user