diff --git a/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java b/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java
index 2eaeab25..e9b391d9 100644
--- a/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java
+++ b/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2012 the original author or authors.
+ * Copyright 2004-2014 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.
@@ -28,7 +28,7 @@ import org.w3c.dom.Element;
/**
* Parser for the flow-builder-services tag.
- *
+ *
* @author Jeremy Grelle
* @author Christian Dupuis
*/
@@ -48,12 +48,16 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle
private static final String ENABLE_MANAGED_BEANS_ATTR = "enable-managed-beans";
private static final String EXPRESSION_PARSER_ATTR = "expression-parser";
private static final String VIEW_FACTORY_CREATOR_ATTR = "view-factory-creator";
+ private static final String VALIDATOR_ATTR = "validator";
+ private static final String VALIDATION_HINT_RESOLVER_ATTR = "validation-hint-resolver";
// --------------------------- Bean Configuration Properties --------------------- //
private static final String CONVERSION_SERVICE_PROPERTY = "conversionService";
private static final String DEVELOPMENT_PROPERTY = "development";
private static final String EXPRESSION_PARSER_PROPERTY = "expressionParser";
private static final String VIEW_FACTORY_CREATOR_PROPERTY = "viewFactoryCreator";
+ private static final String VALIDATOR_PROPERTY = "validator";
+ private static final String VALIDATION_HINT_RESOLVER_PROPERTY = "validationHintResolver";
protected String getBeanClassName(Element element) {
return FLOW_BUILDER_SERVICES_CLASS_NAME;
@@ -68,6 +72,8 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle
parseExpressionParser(element, parserContext, definitionBuilder,
parseEnableManagedBeans(element, definitionBuilder));
parseViewFactoryCreator(element, parserContext, definitionBuilder);
+ parseValidator(element, parserContext, definitionBuilder);
+ parseValidationHintResolver(element, parserContext, definitionBuilder);
parseDevelopment(element, definitionBuilder);
parserContext.popAndRegisterContainingComponent();
@@ -102,6 +108,20 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle
definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, viewFactoryCreator);
}
+ private void parseValidator(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) {
+ String validator = element.getAttribute(VALIDATOR_ATTR);
+ if (StringUtils.hasText(validator)) {
+ definitionBuilder.addPropertyReference(VALIDATOR_PROPERTY, validator);
+ }
+ }
+
+ private void parseValidationHintResolver(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) {
+ String resolver = element.getAttribute(VALIDATION_HINT_RESOLVER_ATTR);
+ if (StringUtils.hasText(resolver)) {
+ definitionBuilder.addPropertyReference(VALIDATION_HINT_RESOLVER_PROPERTY, resolver);
+ }
+ }
+
private void parseExpressionParser(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder,
boolean enableManagedBeans) {
diff --git a/spring-faces/src/main/java/org/springframework/faces/config/FlowBuilderServicesBuilder.java b/spring-faces/src/main/java/org/springframework/faces/config/FlowBuilderServicesBuilder.java
index 4a633e7f..c0ce07ba 100644
--- a/spring-faces/src/main/java/org/springframework/faces/config/FlowBuilderServicesBuilder.java
+++ b/spring-faces/src/main/java/org/springframework/faces/config/FlowBuilderServicesBuilder.java
@@ -23,9 +23,12 @@ import org.springframework.faces.model.converter.FacesConversionService;
import org.springframework.faces.webflow.FacesSpringELExpressionParser;
import org.springframework.faces.webflow.JsfViewFactoryCreator;
import org.springframework.util.Assert;
+import org.springframework.validation.Validator;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
+import org.springframework.webflow.validation.BeanValidationHintResolver;
+import org.springframework.webflow.validation.ValidationHintResolver;
/**
* A builder for {@link FlowBuilderServices} instances for use in JSF applications.
@@ -46,6 +49,10 @@ public class FlowBuilderServicesBuilder {
private ViewFactoryCreator viewFactoryCreator = new JsfViewFactoryCreator();
+ private Validator validator;
+
+ private ValidationHintResolver validationHintResolver;
+
private boolean enableDevelopmentMode;
@@ -89,6 +96,26 @@ public class FlowBuilderServicesBuilder {
return this;
}
+ /**
+ * Set the {@link Validator} to use for validating a model declared on a view state.
+ * By default no validator is set.
+ * @param validator the validator to use
+ */
+ public FlowBuilderServicesBuilder setValidator(Validator validator) {
+ this.validator = validator;
+ return this;
+ }
+
+ /**
+ * The {@link ValidationHintResolver} to use to resolve validation hints such as bean validation groups.
+ * By default a {@link BeanValidationHintResolver} is used.
+ * @param resolver the resolver to use
+ */
+ public FlowBuilderServicesBuilder setValidationHintResolver(ValidationHintResolver resolver) {
+ this.validationHintResolver = resolver;
+ return this;
+ }
+
/**
* Put all flows in development mode. When set to {@code true}, changes to a flow
* definition are auto-detected and result in a flow refresh.
@@ -108,6 +135,8 @@ public class FlowBuilderServicesBuilder {
flowBuilderServices.setConversionService(this.conversionService);
flowBuilderServices.setExpressionParser(getExpressionParser());
flowBuilderServices.setViewFactoryCreator(this.viewFactoryCreator);
+ flowBuilderServices.setValidator(this.validator);
+ flowBuilderServices.setValidationHintResolver(this.validationHintResolver);
flowBuilderServices.setDevelopment(this.enableDevelopmentMode);
return flowBuilderServices;
}
diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowActionListener.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowActionListener.java
index dd051472..0c2f6ba9 100644
--- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowActionListener.java
+++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowActionListener.java
@@ -30,7 +30,9 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.binding.expression.Expression;
import org.springframework.util.StringUtils;
import org.springframework.validation.MessageCodesResolver;
+import org.springframework.validation.Validator;
import org.springframework.webflow.definition.TransitionDefinition;
+import org.springframework.webflow.engine.builder.model.FlowModelFlowBuilder;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.execution.View;
@@ -60,21 +62,10 @@ public class FlowActionListener implements ActionListener {
private final MessageCodesResolver messageCodesResolver = new WebFlowMessageCodesResolver();
- private ValidationHintResolver validationHintResolver = new BeanValidationHintResolver();
-
-
public FlowActionListener(ActionListener delegate) {
this.delegate = delegate;
}
- public void setValidationHintResolver(ValidationHintResolver validationHintResolver) {
- this.validationHintResolver = validationHintResolver;
- }
-
- public ValidationHintResolver getValidationHintResolver() {
- return validationHintResolver;
- }
-
public void processAction(ActionEvent actionEvent) throws AbortProcessingException {
if (!JsfUtils.isFlowRequest()) {
this.delegate.processAction(actionEvent);
@@ -167,8 +158,21 @@ public class FlowActionListener implements ActionListener {
String modelName = getModelExpression(requestContext).getExpressionString();
- new ValidationHelper(model, requestContext,
- eventId, modelName, null, this.messageCodesResolver, null, this.validationHintResolver).validate();
+ String attr = FlowModelFlowBuilder.VALIDATOR_FLOW_ATTR;
+ Validator validator = (Validator) requestContext.getActiveFlow().getAttributes().get(attr);
+
+ ValidationHelper helper = new ValidationHelper(model, requestContext, eventId,
+ modelName, null, this.messageCodesResolver, null, getHintResolver(requestContext));
+ helper.setValidator(validator);
+ helper.validate();
+ }
+
+ private ValidationHintResolver getHintResolver(RequestContext requestContext) {
+
+ ValidationHintResolver hintResolver = (ValidationHintResolver) requestContext.getActiveFlow()
+ .getAttributes().get(FlowModelFlowBuilder.VALIDATION_HINT_RESOLVER_FLOW_ATTR);
+
+ return (hintResolver != null ? hintResolver : new BeanValidationHintResolver());
}
}
diff --git a/spring-faces/src/main/resources/org/springframework/faces/config/spring-faces-2.4.xsd b/spring-faces/src/main/resources/org/springframework/faces/config/spring-faces-2.4.xsd
index 24fde4b9..02261301 100644
--- a/spring-faces/src/main/resources/org/springframework/faces/config/spring-faces-2.4.xsd
+++ b/spring-faces/src/main/resources/org/springframework/faces/config/spring-faces-2.4.xsd
@@ -45,6 +45,26 @@ The custom ExpressionParser implementation to use to compile expression strings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-faces/src/test/java/org/springframework/faces/config/AbstractFacesFlowBuilderServicesConfigurationTests.java b/spring-faces/src/test/java/org/springframework/faces/config/AbstractFacesFlowBuilderServicesConfigurationTests.java
index d2cf0351..fe1c8b3e 100644
--- a/spring-faces/src/test/java/org/springframework/faces/config/AbstractFacesFlowBuilderServicesConfigurationTests.java
+++ b/spring-faces/src/test/java/org/springframework/faces/config/AbstractFacesFlowBuilderServicesConfigurationTests.java
@@ -11,12 +11,13 @@ import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.expression.spel.SpringELExpressionParser;
import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.faces.model.converter.FacesConversionService;
import org.springframework.faces.webflow.FacesSpringELExpressionParser;
import org.springframework.faces.webflow.JSFMockHelper;
import org.springframework.faces.webflow.JsfViewFactoryCreator;
import org.springframework.validation.Validator;
+import org.springframework.faces.config.EmptySpringValidator;
+import org.springframework.faces.config.MyBeanValidationHintResolver;
import org.springframework.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
@@ -68,6 +69,8 @@ public abstract class AbstractFacesFlowBuilderServicesConfigurationTests extends
assertTrue(this.builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
assertTrue(this.builderServices.getViewFactoryCreator() instanceof TestViewFactoryCreator);
assertTrue(this.builderServices.getConversionService() instanceof TestConversionService);
+ assertTrue(builderServices.getValidator() instanceof EmptySpringValidator);
+ assertTrue(builderServices.getValidationHintResolver() instanceof MyBeanValidationHintResolver);
assertTrue(this.builderServices.getDevelopment());
}
diff --git a/spring-faces/src/test/java/org/springframework/faces/config/EmptySpringValidator.java b/spring-faces/src/test/java/org/springframework/faces/config/EmptySpringValidator.java
new file mode 100644
index 00000000..8ef3eaa1
--- /dev/null
+++ b/spring-faces/src/test/java/org/springframework/faces/config/EmptySpringValidator.java
@@ -0,0 +1,15 @@
+package org.springframework.faces.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-faces/src/test/java/org/springframework/faces/config/FacesFlowBuilderServicesJavaConfigTests.java b/spring-faces/src/test/java/org/springframework/faces/config/FacesFlowBuilderServicesJavaConfigTests.java
index 04d8de0b..36961040 100644
--- a/spring-faces/src/test/java/org/springframework/faces/config/FacesFlowBuilderServicesJavaConfigTests.java
+++ b/spring-faces/src/test/java/org/springframework/faces/config/FacesFlowBuilderServicesJavaConfigTests.java
@@ -8,6 +8,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
+import org.springframework.webflow.validation.BeanValidationHintResolver;
public class FacesFlowBuilderServicesJavaConfigTests extends AbstractFacesFlowBuilderServicesConfigurationTests {
@@ -36,6 +37,8 @@ public class FacesFlowBuilderServicesJavaConfigTests extends AbstractFacesFlowBu
.setExpressionParser(customExpressionParser())
.setViewFactoryCreator(customViewFactoryCreator())
.setConversionService(customConversionService())
+ .setValidator(new EmptySpringValidator())
+ .setValidationHintResolver(new MyBeanValidationHintResolver())
.setDevelopmentMode(true)
.build();
}
diff --git a/spring-faces/src/test/java/org/springframework/faces/config/MyBeanValidationHintResolver.java b/spring-faces/src/test/java/org/springframework/faces/config/MyBeanValidationHintResolver.java
new file mode 100644
index 00000000..5847eba6
--- /dev/null
+++ b/spring-faces/src/test/java/org/springframework/faces/config/MyBeanValidationHintResolver.java
@@ -0,0 +1,7 @@
+package org.springframework.faces.config;
+
+import org.springframework.webflow.validation.BeanValidationHintResolver;
+
+public class MyBeanValidationHintResolver extends BeanValidationHintResolver {
+
+}
diff --git a/spring-faces/src/test/java/org/springframework/faces/config/flow-builder-services.xml b/spring-faces/src/test/java/org/springframework/faces/config/flow-builder-services.xml
index ab97d5aa..1f85ccf0 100644
--- a/spring-faces/src/test/java/org/springframework/faces/config/flow-builder-services.xml
+++ b/spring-faces/src/test/java/org/springframework/faces/config/flow-builder-services.xml
@@ -6,7 +6,7 @@
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/faces
- http://www.springframework.org/schema/faces/spring-faces-2.2.xsd">
+ http://www.springframework.org/schema/faces/spring-faces-2.4.xsd">
@@ -15,7 +15,10 @@
+ conversion-service="customConversionService"
+ validator="customValidator"
+ validation-hint-resolver="customValidationHintResolver"
+ development="true" />
@@ -32,4 +35,8 @@
+
+
+
+
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 97d1577f..9bf9002d 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2012 the original author or authors.
+ * Copyright 2004-2014 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.
@@ -119,6 +119,13 @@ import org.springframework.webflow.security.SecurityRule;
*/
public class FlowModelFlowBuilder extends AbstractFlowBuilder {
+ private static final boolean IS_SPRING_FACES_PRESENT = ClassUtils.isPresent(
+ "org.springframework.faces.webflow.FlowActionListener", FlowModelFlowBuilder.class.getClassLoader());
+
+ public static final String VALIDATOR_FLOW_ATTR = FlowModelFlowBuilder.class.getSimpleName() + ".validator";
+
+ public static final String VALIDATION_HINT_RESOLVER_FLOW_ATTR = FlowModelFlowBuilder.class.getSimpleName() + ".validationHintResolver";
+
private FlowModelHolder flowModelHolder;
private FlowModel flowModel;
@@ -155,6 +162,10 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
String flowId = getContext().getFlowId();
AttributeMap