Support providing validator in faces builder serivces
Issue: SWF-1494
This commit is contained in:
@@ -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) {
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,6 +45,26 @@ The custom ExpressionParser implementation to use to compile expression strings
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The custom ViewFactoryCreator implementation to use produce ViewFactories capable of rendering Views.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="validator">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.validation.Validator">
|
||||
<![CDATA[
|
||||
The bean name of the Validator that is to be used for validating a model declared on a view state.
|
||||
This is an optional attribute. By default it is not set.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="validation-hint-resolver">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.webflow.validation.ValidationHintResolver">
|
||||
<![CDATA[
|
||||
The bean name of a ValidationHintResolver used to resolve String-based validation hints.
|
||||
This is an optional attribute. The default an instance of BeanValidationHintResolver is used.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import org.springframework.webflow.validation.BeanValidationHintResolver;
|
||||
|
||||
public class MyBeanValidationHintResolver extends BeanValidationHintResolver {
|
||||
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
<faces:flow-builder-services id="flowBuilderServicesDefault"/>
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
<faces:flow-builder-services id="flowBuilderServicesAllCustom"
|
||||
expression-parser="customExpressionParser"
|
||||
view-factory-creator="customViewFactoryCreator"
|
||||
conversion-service="customConversionService" development="true" />
|
||||
conversion-service="customConversionService"
|
||||
validator="customValidator"
|
||||
validation-hint-resolver="customValidationHintResolver"
|
||||
development="true" />
|
||||
|
||||
<faces:flow-builder-services id="flowBuilderServicesConversionServiceCustom"
|
||||
conversion-service="customConversionService"/>
|
||||
@@ -32,4 +35,8 @@
|
||||
<bean id="customConversionService"
|
||||
class="org.springframework.faces.config.AbstractFacesFlowBuilderServicesConfigurationTests$TestConversionService"/>
|
||||
|
||||
<bean id="customValidator" class="org.springframework.faces.config.EmptySpringValidator" />
|
||||
|
||||
<bean id="customValidationHintResolver" class="org.springframework.faces.config.MyBeanValidationHintResolver" />
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -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<Object> flowAttributes = parseFlowMetaAttributes(flowModel);
|
||||
flowAttributes = getContext().getFlowAttributes().union(flowAttributes);
|
||||
if (IS_SPRING_FACES_PRESENT) {
|
||||
flowAttributes.asMap().put(VALIDATOR_FLOW_ATTR, getLocalContext().getValidator());
|
||||
flowAttributes.asMap().put(VALIDATION_HINT_RESOLVER_FLOW_ATTR, getLocalContext().getValidationHintResolver());
|
||||
}
|
||||
Flow flow = getLocalContext().getFlowArtifactFactory().createFlow(flowId, flowAttributes);
|
||||
flow.setApplicationContext(getLocalContext().getApplicationContext());
|
||||
return flow;
|
||||
|
||||
@@ -529,14 +529,6 @@ private String name;
|
||||
<webflow:flow-builder-services id="flowBuilderServices" validator=".." validationHintResolver=".." />
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The above configuration example works in applications not using JSF.
|
||||
For JSF applications that rely on Web Flow-based validation,
|
||||
you will need to register a
|
||||
custom extension of Web Flow's <emphasis>FlowActionListener</emphasis>
|
||||
via faces-config.xml configured with the custom
|
||||
<classname>ValidationHintResolver</classname>.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
</sect2>
|
||||
|
||||
Reference in New Issue
Block a user