diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.3.xsd b/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.3.xsd
new file mode 100644
index 00000000..74b5ff4a
--- /dev/null
+++ b/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.3.xsd
@@ -0,0 +1,448 @@
+
+
+
+
+
+
+A XML-based DSL for configuring the Spring Web Flow 2.0 system.
+]]>
+
+
+
+
+
+
+
+
+
+Each flow definition registered in this registry is assigned a unique identifier. By default,
+this identifier is the name of the externalized resource minus its file extension. For example,
+a registry containing flow definitions built from the files "orderitem-flow.xml" and "shipping-flow.xml"
+would index those definitions by "orderitem-flow" and "shipping-flow" by default.
+]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderContext.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderContext.java
index dae6da6c..ec9131b9 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderContext.java
@@ -18,6 +18,7 @@ package org.springframework.webflow.engine.builder;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.context.ApplicationContext;
+import org.springframework.validation.Validator;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
@@ -70,6 +71,12 @@ public interface FlowBuilderContext {
*/
public ExpressionParser getExpressionParser();
+ /**
+ * Returns the Validator instance to use for validating a model.
+ * @return the validator
+ */
+ public Validator getValidator();
+
/**
* Returns the application context hosting the flow system.
* @return the application context
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/ViewFactoryCreator.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/ViewFactoryCreator.java
index 4424ec6f..5bc7480a 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/ViewFactoryCreator.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/ViewFactoryCreator.java
@@ -18,6 +18,7 @@ package org.springframework.webflow.engine.builder;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
+import org.springframework.validation.Validator;
import org.springframework.webflow.execution.View;
import org.springframework.webflow.execution.ViewFactory;
@@ -34,10 +35,11 @@ public interface ViewFactoryCreator {
* @param expressionParser an optional expression parser to use to resolve view expressions
* @param conversionService an optional conversion service to use to format text values
* @param binderConfiguration information on how the rendered view binds to a model that provides its data
+ * @param validator a global validator to invoke
* @return the view factory
*/
public ViewFactory createViewFactory(Expression viewId, ExpressionParser expressionParser,
- ConversionService conversionService, BinderConfiguration binderConfiguration);
+ ConversionService conversionService, BinderConfiguration binderConfiguration, Validator validator);
/**
* Get the default id of the view to render in the provided view state by convention.
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 5fac5d14..1609d946 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
@@ -68,9 +68,9 @@ import org.springframework.webflow.engine.TransitionCriteria;
import org.springframework.webflow.engine.VariableValueFactory;
import org.springframework.webflow.engine.ViewVariable;
import org.springframework.webflow.engine.builder.BinderConfiguration;
+import org.springframework.webflow.engine.builder.BinderConfiguration.Binding;
import org.springframework.webflow.engine.builder.FlowBuilderContext;
import org.springframework.webflow.engine.builder.FlowBuilderException;
-import org.springframework.webflow.engine.builder.BinderConfiguration.Binding;
import org.springframework.webflow.engine.builder.support.AbstractFlowBuilder;
import org.springframework.webflow.engine.model.AbstractActionModel;
import org.springframework.webflow.engine.model.AbstractMappingModel;
@@ -372,8 +372,8 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
if (isFlowInDevelopment()) {
builder.addPropertyValue("cacheSeconds", "0");
}
- flowContext.registerBeanDefinition(AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, builder
- .getBeanDefinition());
+ flowContext.registerBeanDefinition(AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME,
+ builder.getBeanDefinition());
}
}
}
@@ -537,8 +537,10 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
}
MutableAttributeMap attributes = parseMetaAttributes(state.getAttributes());
if (state.getModel() != null) {
- attributes.put("model", getLocalContext().getExpressionParser().parseExpression(state.getModel(),
- new FluentParserContext().evaluate(RequestContext.class)));
+ attributes.put(
+ "model",
+ getLocalContext().getExpressionParser().parseExpression(state.getModel(),
+ new FluentParserContext().evaluate(RequestContext.class)));
}
parseAndPutSecured(state.getSecured(), attributes);
getLocalContext().getFlowArtifactFactory().createViewState(state.getId(), flow,
@@ -626,7 +628,8 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
private ViewFactory createViewFactory(Expression viewId, BinderModel binderModel) {
BinderConfiguration binderConfiguration = createBinderConfiguration(binderModel);
return getLocalContext().getViewFactoryCreator().createViewFactory(viewId,
- getLocalContext().getExpressionParser(), getLocalContext().getConversionService(), binderConfiguration);
+ getLocalContext().getExpressionParser(), getLocalContext().getConversionService(), binderConfiguration,
+ getLocalContext().getValidator());
}
private BinderConfiguration createBinderConfiguration(BinderModel binderModel) {
@@ -868,8 +871,8 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
private Action parseRenderAction(RenderModel render) {
String[] fragmentExpressionStrings = StringUtils.commaDelimitedListToStringArray(render.getFragments());
fragmentExpressionStrings = StringUtils.trimArrayElements(fragmentExpressionStrings);
- ParserContext context = new FluentParserContext().template().evaluate(RequestContext.class).expectResult(
- String.class);
+ ParserContext context = new FluentParserContext().template().evaluate(RequestContext.class)
+ .expectResult(String.class);
Expression[] fragments = new Expression[fragmentExpressionStrings.length];
for (int i = 0; i < fragmentExpressionStrings.length; i++) {
String fragment = fragmentExpressionStrings[i];
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/LocalFlowBuilderContext.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/LocalFlowBuilderContext.java
index 23da90b3..bd55c800 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/LocalFlowBuilderContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/LocalFlowBuilderContext.java
@@ -19,6 +19,7 @@ import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.validation.Validator;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
import org.springframework.webflow.engine.builder.FlowArtifactFactory;
@@ -55,7 +56,7 @@ class LocalFlowBuilderContext implements FlowBuilderContext {
public FlowDefinitionLocator getFlowDefinitionLocator() {
if (localFlowContext.containsLocalBean("flowRegistry")) {
- return (FlowDefinitionLocator) localFlowContext.getBean("flowRegistry", FlowDefinitionLocator.class);
+ return localFlowContext.getBean("flowRegistry", FlowDefinitionLocator.class);
} else {
return parent.getFlowDefinitionLocator();
}
@@ -63,7 +64,7 @@ class LocalFlowBuilderContext implements FlowBuilderContext {
public FlowArtifactFactory getFlowArtifactFactory() {
if (localFlowContext.containsLocalBean("flowArtifactFactory")) {
- return (FlowArtifactFactory) localFlowContext.getBean("flowArtifactFactory", FlowArtifactFactory.class);
+ return localFlowContext.getBean("flowArtifactFactory", FlowArtifactFactory.class);
} else {
return parent.getFlowArtifactFactory();
}
@@ -71,7 +72,7 @@ class LocalFlowBuilderContext implements FlowBuilderContext {
public ConversionService getConversionService() {
if (localFlowContext.containsLocalBean("conversionService")) {
- return (ConversionService) localFlowContext.getBean("conversionService", ConversionService.class);
+ return localFlowContext.getBean("conversionService", ConversionService.class);
} else {
return parent.getConversionService();
}
@@ -79,7 +80,7 @@ class LocalFlowBuilderContext implements FlowBuilderContext {
public ViewFactoryCreator getViewFactoryCreator() {
if (localFlowContext.containsLocalBean("viewFactoryCreator")) {
- return (ViewFactoryCreator) localFlowContext.getBean("viewFactoryCreator", ViewFactoryCreator.class);
+ return localFlowContext.getBean("viewFactoryCreator", ViewFactoryCreator.class);
} else {
return parent.getViewFactoryCreator();
}
@@ -87,10 +88,18 @@ class LocalFlowBuilderContext implements FlowBuilderContext {
public ExpressionParser getExpressionParser() {
if (localFlowContext.containsLocalBean("expressionParser")) {
- return (ExpressionParser) localFlowContext.getBean("expressionParser", ExpressionParser.class);
+ return localFlowContext.getBean("expressionParser", ExpressionParser.class);
} else {
return parent.getExpressionParser();
}
}
+ public Validator getValidator() {
+ if (localFlowContext.containsLocalBean("validator")) {
+ return localFlowContext.getBean("validator", Validator.class);
+ } else {
+ return parent.getValidator();
+ }
+ }
+
}
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java
index d2566a86..60fd08b0 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java
@@ -24,6 +24,7 @@ import org.springframework.binding.convert.service.GenericConversionService;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
+import org.springframework.validation.Validator;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.CollectionUtils;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
@@ -104,6 +105,10 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
return flowBuilderServices.getApplicationContext();
}
+ public Validator getValidator() {
+ return flowBuilderServices.getValidator();
+ }
+
/**
* Factory method that creates the conversion service the flow builder will use. Subclasses may override. The
* default implementation registers Web Flow-specific converters thought to be useful for most builder
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderServices.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderServices.java
index d080f19e..8252f8c1 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderServices.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderServices.java
@@ -22,6 +22,7 @@ import org.springframework.binding.expression.ExpressionParser;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
+import org.springframework.validation.Validator;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.State;
import org.springframework.webflow.engine.builder.FlowArtifactFactory;
@@ -65,6 +66,12 @@ public class FlowBuilderServices implements ApplicationContextAware, Initializin
*/
private ExpressionParser expressionParser;
+ /**
+ * A Validator instance to use for validating a model declared on a view state. A JSR-303 validation adapter is
+ * installed by default if a JSR-303 provider is present on the classpath.
+ */
+ private Validator validator;
+
/**
* The Spring application context that provides access to the services of the application.
*/
@@ -107,6 +114,14 @@ public class FlowBuilderServices implements ApplicationContextAware, Initializin
this.expressionParser = expressionParser;
}
+ public Validator getValidator() {
+ return validator;
+ }
+
+ public void setValidator(Validator validator) {
+ this.validator = validator;
+ }
+
public boolean getDevelopment() {
return development;
}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.java
index 76423064..c7c4f374 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.java
@@ -27,6 +27,7 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.util.StringUtils;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.MessageCodesResolver;
+import org.springframework.validation.Validator;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.webflow.engine.builder.BinderConfiguration;
@@ -169,7 +170,7 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
}
public ViewFactory createViewFactory(Expression viewId, ExpressionParser expressionParser,
- ConversionService conversionService, BinderConfiguration binderConfiguration) {
+ ConversionService conversionService, BinderConfiguration binderConfiguration, Validator validator) {
if (useSpringBeanBinding) {
expressionParser = new BeanWrapperExpressionParser(conversionService);
}
@@ -181,6 +182,7 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
if (StringUtils.hasText(fieldMarkerPrefix)) {
viewFactory.setFieldMarkerPrefix(fieldMarkerPrefix);
}
+ viewFactory.setValidator(validator);
return viewFactory;
}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcView.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcView.java
index 3709d768..6307466b 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcView.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcView.java
@@ -45,6 +45,7 @@ import org.springframework.core.style.ToStringCreator;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.validation.MessageCodesResolver;
+import org.springframework.validation.Validator;
import org.springframework.web.util.WebUtils;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.ParameterMap;
@@ -78,6 +79,8 @@ public abstract class AbstractMvcView implements View {
private ConversionService conversionService;
+ private Validator validator;
+
private String fieldMarkerPrefix = "_";
private String eventIdParameterName = "_eventId";
@@ -118,6 +121,10 @@ public abstract class AbstractMvcView implements View {
this.conversionService = conversionService;
}
+ public void setValidator(Validator validator) {
+ this.validator = validator;
+ }
+
/**
* Sets the configuration describing how this view should bind to its model to access data for rendering.
* @param binderConfiguration the model binder configuration
@@ -534,12 +541,12 @@ public abstract class AbstractMvcView implements View {
private Map flowScopes() {
if (requestContext.getCurrentState().isViewState()) {
- return requestContext.getConversationScope().union(requestContext.getFlowScope()).union(
- requestContext.getViewScope()).union(requestContext.getFlashScope()).union(
- requestContext.getRequestScope()).asMap();
+ return requestContext.getConversationScope().union(requestContext.getFlowScope())
+ .union(requestContext.getViewScope()).union(requestContext.getFlashScope())
+ .union(requestContext.getRequestScope()).asMap();
} else {
- return requestContext.getConversationScope().union(requestContext.getFlowScope()).union(
- requestContext.getFlashScope()).union(requestContext.getRequestScope()).asMap();
+ return requestContext.getConversationScope().union(requestContext.getFlowScope())
+ .union(requestContext.getFlashScope()).union(requestContext.getRequestScope()).asMap();
}
}
@@ -605,8 +612,8 @@ public abstract class AbstractMvcView implements View {
String field = error.getMapping().getTargetExpression().getExpressionString();
Class fieldType = error.getMapping().getTargetExpression().getValueType(getModelObject());
String[] messageCodes = messageCodesResolver.resolveMessageCodes(error.getCode(), model, field, fieldType);
- return new MessageBuilder().error().source(field).codes(messageCodes).resolvableArg(field).defaultText(
- error.getCode() + " on " + field).build();
+ return new MessageBuilder().error().source(field).codes(messageCodes).resolvableArg(field)
+ .defaultText(error.getCode() + " on " + field).build();
}
private Boolean getValidateAttribute(TransitionDefinition transition) {
@@ -621,8 +628,10 @@ public abstract class AbstractMvcView implements View {
if (logger.isDebugEnabled()) {
logger.debug("Validating model");
}
- new ValidationHelper(model, requestContext, eventId, getModelExpression().getExpressionString(),
- expressionParser, messageCodesResolver, mappingResults).validate();
+ ValidationHelper helper = new ValidationHelper(model, requestContext, eventId, getModelExpression()
+ .getExpressionString(), expressionParser, messageCodesResolver, mappingResults);
+ helper.setValidator(validator);
+ helper.validate();
}
private static class PropertyNotFoundError implements MappingResultsCriteria {
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcViewFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcViewFactory.java
index c3dfd139..58defb58 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcViewFactory.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcViewFactory.java
@@ -20,6 +20,7 @@ import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.util.StringUtils;
import org.springframework.validation.MessageCodesResolver;
+import org.springframework.validation.Validator;
import org.springframework.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.View;
@@ -40,6 +41,8 @@ public abstract class AbstractMvcViewFactory implements ViewFactory {
private ConversionService conversionService;
+ private Validator validator;
+
private BinderConfiguration binderConfiguration;
private String eventIdParameterName;
@@ -75,6 +78,10 @@ public abstract class AbstractMvcViewFactory implements ViewFactory {
this.fieldMarkerPrefix = fieldMarkerPrefix;
}
+ public void setValidator(Validator validator) {
+ this.validator = validator;
+ }
+
public View getView(RequestContext context) {
String viewId = (String) this.viewId.getValue(context);
org.springframework.web.servlet.View view = viewResolver.resolveView(viewId, context);
@@ -83,6 +90,7 @@ public abstract class AbstractMvcViewFactory implements ViewFactory {
mvcView.setConversionService(conversionService);
mvcView.setBinderConfiguration(binderConfiguration);
mvcView.setMessageCodesResolver(messageCodesResolver);
+ mvcView.setValidator(validator);
if (StringUtils.hasText(eventIdParameterName)) {
mvcView.setEventIdParameterName(eventIdParameterName);
}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/MockViewFactoryCreator.java b/spring-webflow/src/main/java/org/springframework/webflow/test/MockViewFactoryCreator.java
index ee81c6d6..c2cbfd3c 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/test/MockViewFactoryCreator.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/test/MockViewFactoryCreator.java
@@ -22,6 +22,7 @@ import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.core.style.ToStringCreator;
+import org.springframework.validation.Validator;
import org.springframework.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.execution.Event;
@@ -38,7 +39,7 @@ import org.springframework.webflow.execution.ViewFactory;
class MockViewFactoryCreator implements ViewFactoryCreator {
public ViewFactory createViewFactory(Expression viewId, ExpressionParser expressionParser,
- ConversionService conversionService, BinderConfiguration binderConfiguration) {
+ ConversionService conversionService, BinderConfiguration binderConfiguration, Validator validator) {
return new MockViewFactory(viewId);
}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/validation/ValidationHelper.java b/spring-webflow/src/main/java/org/springframework/webflow/validation/ValidationHelper.java
index 3d45f384..adb363de 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/validation/ValidationHelper.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/validation/ValidationHelper.java
@@ -64,6 +64,8 @@ public class ValidationHelper {
private final MappingResults mappingResults;
+ private Validator validator;
+
/**
* Create a throwaway validation helper object. Validation is invoked by the {@link #validate()} method.
*
@@ -94,14 +96,24 @@ public class ValidationHelper {
this.mappingResults = mappingResults;
}
+ /**
+ * Configure a {@link Validator} to apply to the model.
+ */
+ public void setValidator(Validator validator) {
+ this.validator = validator;
+ }
+
/**
* Invoke the validators available by convention.
*/
public void validate() {
+ if (this.validator != null) {
+ invokeValidatorDefaultValidateMethod(model, this.validator);
+ }
invokeModelValidationMethod(model);
- Object validator = getModelValidator();
- if (validator != null) {
- invokeModelValidator(model, validator);
+ Object modelValidator = getModelValidator();
+ if (modelValidator != null) {
+ invokeModelValidator(model, modelValidator);
}
}
@@ -215,8 +227,8 @@ public class ValidationHelper {
// web flow 2.0.0 to 2.0.3 compatibility only [to remove in web flow 3]
validateMethod = findValidationMethod(model, validator, methodName, MessageContext.class);
if (validateMethod != null) {
- ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model,
- requestContext.getMessageContext() });
+ ReflectionUtils.invokeMethod(validateMethod, validator,
+ new Object[] { model, requestContext.getMessageContext() });
return true;
}
return false;
@@ -224,13 +236,21 @@ public class ValidationHelper {
private boolean invokeValidatorDefaultValidateMethod(Object model, Object validator) {
if (validator instanceof Validator) {
- // supports existing validators
+ // Spring Framework Validator type
+ Validator springValidator = (Validator) validator;
if (logger.isDebugEnabled()) {
logger.debug("Invoking Spring Validator '" + ClassUtils.getShortName(validator.getClass()) + "'");
}
- MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), modelName,
- model, expressionParser, messageCodesResolver, mappingResults);
- ((Validator) validator).validate(model, errors);
+ if (springValidator.supports(model.getClass())) {
+ MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), modelName,
+ model, expressionParser, messageCodesResolver, mappingResults);
+ springValidator.validate(model, errors);
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Spring Validator '" + ClassUtils.getShortName(validator.getClass())
+ + "' doesn't support model class " + model.getClass());
+ }
+ }
return true;
}
// preferred
diff --git a/spring-webflow/src/main/resources/META-INF/spring.schemas b/spring-webflow/src/main/resources/META-INF/spring.schemas
index e4fce8cd..d7334c4c 100644
--- a/spring-webflow/src/main/resources/META-INF/spring.schemas
+++ b/spring-webflow/src/main/resources/META-INF/spring.schemas
@@ -1 +1,3 @@
-http\://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd=org/springframework/webflow/config/spring-webflow-config-2.0.xsd
\ No newline at end of file
+http\://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd=org/springframework/webflow/config/spring-webflow-config-2.0.xsd
+http\://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd=org/springframework/webflow/config/spring-webflow-config-2.3.xsd
+http\://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd=org/springframework/webflow/config/spring-webflow-config-2.3.xsd
\ No newline at end of file
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/EmptySpringValidator.java b/spring-webflow/src/test/java/org/springframework/webflow/config/EmptySpringValidator.java
new file mode 100644
index 00000000..3a6fec69
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/config/EmptySpringValidator.java
@@ -0,0 +1,15 @@
+package org.springframework.webflow.config;
+
+import org.springframework.validation.Errors;
+import org.springframework.validation.Validator;
+
+public class EmptySpringValidator implements Validator {
+
+ public boolean supports(Class> clazz) {
+ return false;
+ }
+
+ public void validate(Object target, Errors errors) {
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParserTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParserTests.java
index 0841e7c4..11b2034c 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParserTests.java
+++ b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParserTests.java
@@ -14,6 +14,7 @@ import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.expression.spel.SpringELExpressionParser;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.validation.Validator;
import org.springframework.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
@@ -35,6 +36,7 @@ public class FlowBuilderServicesBeanDefinitionParserTests extends TestCase {
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
assertTrue(builderServices.getViewFactoryCreator() instanceof MvcViewFactoryCreator);
assertTrue(builderServices.getConversionService() instanceof DefaultConversionService);
+ assertNull(builderServices.getValidator());
assertFalse(builderServices.getDevelopment());
}
@@ -44,6 +46,7 @@ public class FlowBuilderServicesBeanDefinitionParserTests extends TestCase {
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
assertTrue(builderServices.getViewFactoryCreator() instanceof TestViewFactoryCreator);
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
+ assertTrue(builderServices.getValidator() instanceof EmptySpringValidator);
assertTrue(builderServices.getDevelopment());
}
@@ -54,13 +57,14 @@ public class FlowBuilderServicesBeanDefinitionParserTests extends TestCase {
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
assertTrue(((SpringELExpressionParser) builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
assertTrue(builderServices.getViewFactoryCreator() instanceof MvcViewFactoryCreator);
+ assertNull(builderServices.getValidator());
assertFalse(builderServices.getDevelopment());
}
public static class TestViewFactoryCreator implements ViewFactoryCreator {
public ViewFactory createViewFactory(Expression viewIdExpression, ExpressionParser expressionParser,
- ConversionService conversionService, BinderConfiguration binderConfiguration) {
+ ConversionService conversionService, BinderConfiguration binderConfiguration, Validator validator) {
throw new UnsupportedOperationException("Auto-generated method stub");
}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-builder-services.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-builder-services.xml
index 505fb3e2..51df5ef9 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-builder-services.xml
+++ b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-builder-services.xml
@@ -4,16 +4,18 @@
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+ http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/webflow-config
- http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
+ http://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd">
+ conversion-service="customConversionService"
+ validator="customValidator"
+ development="true" />
@@ -28,4 +30,6 @@
+
+
\ No newline at end of file
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor.xml
index 3e3dfc8c..76015639 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor.xml
+++ b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor.xml
@@ -4,9 +4,9 @@
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+ http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/webflow-config
- http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
+ http://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd">
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-registry.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-registry.xml
index 14255bf9..797e322a 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-registry.xml
+++ b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-registry.xml
@@ -4,9 +4,9 @@
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+ http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/webflow-config
- http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
+ http://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd">