persistence-context element
This commit is contained in:
@@ -30,7 +30,6 @@ import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.CollectionAddingExpression;
|
||||
@@ -120,8 +119,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
|
||||
private static final String ID_ATTRIBUTE = "id";
|
||||
|
||||
private static final String IDREF_ATTRIBUTE = "idref";
|
||||
|
||||
private static final String BEAN_ATTRIBUTE = "bean";
|
||||
|
||||
private static final String FLOW_ELEMENT = "flow";
|
||||
@@ -178,12 +175,8 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
|
||||
private static final String OUTPUT_MAPPER_ELEMENT = "output-mapper";
|
||||
|
||||
private static final String OUTPUT_ATTRIBUTE_ELEMENT = "output-attribute";
|
||||
|
||||
private static final String INPUT_MAPPER_ELEMENT = "input-mapper";
|
||||
|
||||
private static final String INPUT_ATTRIBUTE_ELEMENT = "input-attribute";
|
||||
|
||||
private static final String MAPPING_ELEMENT = "mapping";
|
||||
|
||||
private static final String SOURCE_ATTRIBUTE = "source";
|
||||
@@ -413,8 +406,16 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
String flowId = getLocalContext().getFlowId();
|
||||
AttributeMap externallyAssignedAttributes = getLocalContext().getFlowAttributes();
|
||||
AttributeMap flowAttributes = parseAttributes(flowElement).union(externallyAssignedAttributes);
|
||||
return getFlowArtifactFactory().createFlow(flowId, flowAttributes);
|
||||
MutableAttributeMap flowAttributes = parseAttributes(flowElement);
|
||||
parseAndSetPersistenceContextAttribute(flowElement, flowAttributes);
|
||||
return getFlowArtifactFactory().createFlow(flowId, flowAttributes.union(externallyAssignedAttributes));
|
||||
}
|
||||
|
||||
private void parseAndSetPersistenceContextAttribute(Element flowElement, MutableAttributeMap flowAttributes) {
|
||||
Element element = DomUtils.getChildElementByTagName(flowElement, "persistence-context");
|
||||
if (element != null) {
|
||||
flowAttributes.put("persistenceContext", Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFlowElement(Element flowElement) {
|
||||
@@ -558,7 +559,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
} else {
|
||||
Element startStateElement = DomUtils.getChildElementByTagName(element, startState);
|
||||
if (startStateElement != null) {
|
||||
return startStateElement.getAttribute(IDREF_ATTRIBUTE);
|
||||
return startStateElement.getAttribute("idref");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -726,16 +727,12 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
continue;
|
||||
}
|
||||
if (DomUtils.nodeNameEquals(childNode, ACTION_ELEMENT)) {
|
||||
// parse standard action
|
||||
actions.add(parseAnnotatedAction((Element) childNode));
|
||||
} else if (DomUtils.nodeNameEquals(childNode, BEAN_ACTION_ELEMENT)) {
|
||||
// parse bean invoking action
|
||||
actions.add(parseAnnotatedBeanInvokingAction((Element) childNode));
|
||||
} else if (DomUtils.nodeNameEquals(childNode, EVALUATE_ACTION_ELEMENT)) {
|
||||
// parse evaluate action
|
||||
actions.add(parseAnnotatedEvaluateAction((Element) childNode));
|
||||
} else if (DomUtils.nodeNameEquals(childNode, SET_ELEMENT)) {
|
||||
// parse set action
|
||||
actions.add(parseAnnotatedSetAction((Element) childNode));
|
||||
}
|
||||
}
|
||||
@@ -899,7 +896,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
}
|
||||
|
||||
private AttributeMap parseAttributes(Element element) {
|
||||
private MutableAttributeMap parseAttributes(Element element) {
|
||||
LocalAttributeMap attributes = new LocalAttributeMap();
|
||||
List propertyElements = DomUtils.getChildElementsByTagName(element, ATTRIBUTE_ELEMENT);
|
||||
for (int i = 0; i < propertyElements.size(); i++) {
|
||||
@@ -982,8 +979,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
Element mapperElement = DomUtils.getChildElementByTagName(element, INPUT_MAPPER_ELEMENT);
|
||||
if (mapperElement != null) {
|
||||
DefaultAttributeMapper mapper = new DefaultAttributeMapper();
|
||||
parseSimpleInputAttributeMappings(mapper, DomUtils.getChildElementsByTagName(mapperElement,
|
||||
INPUT_ATTRIBUTE_ELEMENT));
|
||||
parseMappings(mapper, mapperElement, MutableAttributeMap.class, RequestContext.class);
|
||||
return mapper;
|
||||
} else {
|
||||
@@ -995,8 +990,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
Element mapperElement = DomUtils.getChildElementByTagName(element, INPUT_MAPPER_ELEMENT);
|
||||
if (mapperElement != null) {
|
||||
DefaultAttributeMapper mapper = new DefaultAttributeMapper();
|
||||
parseSimpleInputAttributeMappings(mapper, DomUtils.getChildElementsByTagName(mapperElement,
|
||||
INPUT_ATTRIBUTE_ELEMENT));
|
||||
parseMappings(mapper, mapperElement, RequestContext.class, MutableAttributeMap.class);
|
||||
return mapper;
|
||||
} else {
|
||||
@@ -1008,8 +1001,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
Element mapperElement = DomUtils.getChildElementByTagName(element, OUTPUT_MAPPER_ELEMENT);
|
||||
if (mapperElement != null) {
|
||||
DefaultAttributeMapper mapper = new DefaultAttributeMapper();
|
||||
parseSimpleOutputAttributeMappings(mapper, DomUtils.getChildElementsByTagName(mapperElement,
|
||||
OUTPUT_ATTRIBUTE_ELEMENT));
|
||||
parseMappings(mapper, mapperElement, RequestContext.class, MutableAttributeMap.class);
|
||||
return mapper;
|
||||
} else {
|
||||
@@ -1021,8 +1012,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
Element mapperElement = DomUtils.getChildElementByTagName(element, OUTPUT_MAPPER_ELEMENT);
|
||||
if (mapperElement != null) {
|
||||
DefaultAttributeMapper mapper = new DefaultAttributeMapper();
|
||||
parseSimpleOutputAttributeMappings(mapper, DomUtils.getChildElementsByTagName(mapperElement,
|
||||
OUTPUT_ATTRIBUTE_ELEMENT));
|
||||
parseMappings(mapper, mapperElement, MutableAttributeMap.class, RequestContext.class);
|
||||
return mapper;
|
||||
} else {
|
||||
@@ -1053,40 +1042,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
}
|
||||
|
||||
// this looks really complicated and possibly wrong
|
||||
private void parseSimpleInputAttributeMappings(DefaultAttributeMapper mapper, List elements) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
for (Iterator it = elements.iterator(); it.hasNext();) {
|
||||
Element element = (Element) it.next();
|
||||
Expression attributeExpression = parser.parseExpression(element.getAttribute(NAME_ATTRIBUTE),
|
||||
new ParserContextImpl().eval(RequestContext.class));
|
||||
Expression scopedAttributeExpression = new ScopedAttributeExpression(attributeExpression, parseScope(
|
||||
element, ScopeType.FLOW));
|
||||
if (getRequired(element, false)) {
|
||||
mapper.addMapping(new RequiredMapping(attributeExpression, scopedAttributeExpression, null));
|
||||
} else {
|
||||
mapper.addMapping(new Mapping(attributeExpression, scopedAttributeExpression, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this looks really complicated and possibly wrong
|
||||
private void parseSimpleOutputAttributeMappings(DefaultAttributeMapper mapper, List elements) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
for (Iterator it = elements.iterator(); it.hasNext();) {
|
||||
Element element = (Element) it.next();
|
||||
Expression attributeExpression = parser.parseExpression(element.getAttribute(NAME_ATTRIBUTE),
|
||||
new ParserContextImpl().eval(RequestContext.class));
|
||||
Expression scopedAttributeExpression = new ScopedAttributeExpression(attributeExpression, parseScope(
|
||||
element, ScopeType.FLOW));
|
||||
if (getRequired(element, false)) {
|
||||
mapper.addMapping(new RequiredMapping(scopedAttributeExpression, attributeExpression, null));
|
||||
} else {
|
||||
mapper.addMapping(new Mapping(scopedAttributeExpression, attributeExpression, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getRequired(Element element, boolean defaultValue) {
|
||||
if (StringUtils.hasText(element.getAttribute(REQUIRED_ATTRIBUTE))) {
|
||||
return ((Boolean) fromStringTo(Boolean.class).execute(element.getAttribute(REQUIRED_ATTRIBUTE)))
|
||||
@@ -1188,28 +1143,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
}
|
||||
|
||||
private static class ScopedAttributeExpression implements Expression {
|
||||
|
||||
private Expression scopeMapExpression;
|
||||
|
||||
private ScopeType scopeType;
|
||||
|
||||
public ScopedAttributeExpression(Expression scopeMapExpression, ScopeType scopeType) {
|
||||
this.scopeMapExpression = scopeMapExpression;
|
||||
this.scopeType = scopeType;
|
||||
}
|
||||
|
||||
public Object getValue(Object target) throws EvaluationException {
|
||||
MutableAttributeMap scopeMap = scopeType.getScope((RequestContext) target);
|
||||
return scopeMapExpression.getValue(scopeMap);
|
||||
}
|
||||
|
||||
public void setValue(Object target, Object value) throws EvaluationException {
|
||||
MutableAttributeMap scopeMap = scopeType.getScope((RequestContext) target);
|
||||
scopeMapExpression.setValue(scopeMap, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FlowRelativeResourceLoader implements ResourceLoader {
|
||||
private Resource resource;
|
||||
|
||||
|
||||
@@ -201,8 +201,11 @@ A flow may also exhibit the following characteristics:
|
||||
<ul>
|
||||
<li>Be annotated with attributes that define descriptive properties that may affect flow execution.
|
||||
(See the <attribute/> element)
|
||||
|
||||
<li>Be a persistence context for managing persistent objects during the course of flow execution.
|
||||
(See the <persistence-context/> element)
|
||||
|
||||
<li>Instantiate a set of application variables when started.
|
||||
<li>Instantiate a set of instance variables when started.
|
||||
(See the <var/> element)
|
||||
|
||||
<li>Map input provided by callers that start it
|
||||
@@ -239,6 +242,19 @@ An attribute describing this flow.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element ref="persistence-context" minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Indicates this flow manages a persistence context. The persistence context is created when a new instance of this flow starts.
|
||||
The persistence context is closed when the flow instance ends. If the flow ends by reaching a "commit" end-state, changes
|
||||
made to managed persistent entities during the course of flow execution are flushed to the database in a transaction.
|
||||
<br>
|
||||
The persistence context can be referenced from within this flow by the "entityManager" variable.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element ref="var" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -489,17 +505,6 @@ The identifier of the start state of this flow. The start state is the point wh
|
||||
<xsd:element name="input-mapper">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="input-attribute" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
A rule that maps an input attribute in a source attribute map to a target attribute map.
|
||||
This is a convenient form of the more flexible 'mapping' element for mapping attributes between
|
||||
attribute maps.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element ref="mapping" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -580,39 +585,6 @@ evaluates to null an error will be reported.
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="input-attribute">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The name of the input attribute.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="scope" type="scopeType" default="default">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The scope of the input attribute. If not specified the default scope type is used ('flow' by default).
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="required" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Whether or not this input attribute is required. If marked required and it evaluates to null
|
||||
an error will be reported.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="attribute">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
@@ -662,6 +634,9 @@ The value of this attribute; a short-cut alternative to an explicit child 'value
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="persistence-context">
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="var">
|
||||
<xsd:complexType>
|
||||
@@ -1651,18 +1626,6 @@ For the output mapper the following mapping characteristics apply:
|
||||
<li>The 'target' of each output mapping is the RequestContext, exposing access to
|
||||
internal data structures of this flow such as flowScope.
|
||||
</ul>
|
||||
<br>
|
||||
For example:
|
||||
<pre>
|
||||
<attribute-mapper>
|
||||
<input-mapper>
|
||||
<input-attribute name="myFlowAttribute"/>
|
||||
</input-mapper>
|
||||
<output-mapper>
|
||||
<output-attribute name="aSubflowOutputAttribute"/>
|
||||
</output-mapper>
|
||||
</attribute-mapper>
|
||||
</pre>
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
@@ -1925,17 +1888,6 @@ and may execute one or more actions before executing.
|
||||
<xsd:element name="output-mapper">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="output-attribute" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
A rule that maps an output attribute in a source attribute map to a target attribute map.
|
||||
This is a convenient form of the more flexible 'mapping' element for mapping attributes between
|
||||
attribute maps.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element ref="mapping" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -1951,39 +1903,6 @@ support for type conversion.
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="output-attribute">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The name of the output attribute.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="scope" type="scopeType" default="default">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The scope of the output attribute. If not specified the default scope type is used ('flow' by default).
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="required" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Whether or not this output attribute is required. If marked required and it evaluates to null
|
||||
an error will be reported.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="exception-handler">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="bean" type="xsd:string" use="required">
|
||||
|
||||
@@ -65,4 +65,21 @@ public class XmlFlowBuilderTests extends TestCase {
|
||||
assertEquals("end", flow.getStartState().getId());
|
||||
}
|
||||
|
||||
public void testCustomFlowAttribute() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-custom-attribute.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertEquals("bar", flow.getAttributes().get("foo"));
|
||||
assertEquals(new Integer(1), flow.getAttributes().get("number"));
|
||||
}
|
||||
|
||||
public void testPersistenceContextFlow() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-persistencecontext.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertNotNull(flow.getAttributes().get("persistenceContext"));
|
||||
assertTrue(((Boolean) flow.getAttributes().get("persistenceContext")).booleanValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<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">
|
||||
|
||||
<attribute name="foo" value="bar"/>
|
||||
<attribute name="number" value="1" type="integer"/>
|
||||
<end-state id="end"/>
|
||||
|
||||
</flow>
|
||||
@@ -1,7 +1,6 @@
|
||||
<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" start-state="end">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
|
||||
|
||||
<end-state id="end"/>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<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">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
|
||||
|
||||
</flow>
|
||||
@@ -0,0 +1,9 @@
|
||||
<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">
|
||||
|
||||
<persistence-context/>
|
||||
|
||||
<end-state id="end"/>
|
||||
|
||||
</flow>
|
||||
@@ -1,7 +1,6 @@
|
||||
<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" start-state="end">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd" start-state="end">
|
||||
|
||||
<end-state id="foo"/>
|
||||
<end-state id="end"/>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<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">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
|
||||
|
||||
<end-state id="end"/>
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<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">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
|
||||
|
||||
<start-state idref="end"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user