This commit is contained in:
Keith Donald
2009-03-10 03:30:21 +00:00
parent 53ee66b04e
commit 2b596db2cd
7 changed files with 51 additions and 23 deletions

View File

@@ -2,7 +2,7 @@ SPRING WEB FLOW CHANGELOG
=========================
http://www.springframework.org/webflow
Changes in version 2.0.6 (2009.02.26)
Changes in version 2.0.6 (2009.03.12)
-------------------------------------
Bug Fixes
* Fixed bug where FlowHandlerMapping could not handle null flow id scenarios (SWF-968)
@@ -14,9 +14,10 @@ Bug Fixes
* Fixed bug where form:checkbox and form:checkboxes tags did not apply type conversion properly in views rendered by Web Flows (SWF-986)
* Fixed bug where Errors nestedPath attribute was not respected in views rendered by Web Flow (SWF-973)
* Fixed bug where Errors nestedPath attribute was not respected when using Errors API programatically within a Validator called by Web Flow (SWF-973)
* Made MessageCodesResolver pluggable on MvcViewFactoryCreator; configure a DefaultMessageCodesResolver to resolve error message codes consistent with default Spring MVC behavior (SWF-977).
Improvements
* Improved FlowExecution test documentation (SWF-???, SWF-???)
* Improved FlowExecution test documentation
Changes in version 2.0.5 (14.11.2008)
-------------------------------------

View File

@@ -25,6 +25,8 @@ import org.springframework.binding.expression.beanwrapper.BeanWrapperExpressionP
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.StringUtils;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.webflow.engine.builder.BinderConfiguration;
@@ -34,6 +36,7 @@ import org.springframework.webflow.mvc.portlet.PortletMvcViewFactory;
import org.springframework.webflow.mvc.servlet.ServletMvcViewFactory;
import org.springframework.webflow.mvc.view.AbstractMvcViewFactory;
import org.springframework.webflow.mvc.view.FlowViewResolver;
import org.springframework.webflow.validation.WebFlowMessageCodesResolver;
/**
* Returns {@link ViewFactory view factories} that create native Spring MVC-based views. Used by a FlowBuilder to
@@ -66,6 +69,8 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
private String fieldMarkerPrefix;
private MessageCodesResolver messageCodesResolver;
/**
* Create a new Spring MVC View Factory Creator.
* @see #setDefaultViewSuffix(String)
@@ -74,6 +79,7 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
* @see #setUseSpringBeanBinding(boolean)
* @see #setFlowViewResolver(FlowViewResolver)
* @see #setViewResolvers(List)
* @see #setMessageCodesResolver(MessageCodesResolver)
*/
public MvcViewFactoryCreator() {
@@ -146,6 +152,16 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
this.flowViewResolver = new DelegatingFlowViewResolver(viewResolvers);
}
/**
* Sets the message codes resolver strategy to use to resolve bind and validation error message codes. If not set,
* {@link WebFlowMessageCodesResolver} is the default. Plug in a {@link DefaultMessageCodesResolver} to resolve
* message codes consistently between Spring MVC Controllers and Web Flow.
* @param messageCodesResolver the message codes resolver
*/
public void setMessageCodesResolver(MessageCodesResolver messageCodesResolver) {
this.messageCodesResolver = messageCodesResolver;
}
// implementing ApplicationContextAware
public void setApplicationContext(ApplicationContext applicationContext) {
@@ -172,10 +188,10 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
ConversionService conversionService, BinderConfiguration binderConfiguration) {
if (environment == MvcEnvironment.SERVLET) {
return new ServletMvcViewFactory(viewId, flowViewResolver, expressionParser, conversionService,
binderConfiguration);
binderConfiguration, messageCodesResolver);
} else if (environment == MvcEnvironment.PORTLET) {
return new PortletMvcViewFactory(viewId, flowViewResolver, expressionParser, conversionService,
binderConfiguration);
binderConfiguration, messageCodesResolver);
} else {
throw new IllegalStateException("Web MVC Environment " + environment + " not supported ");
}

View File

@@ -18,6 +18,7 @@ package org.springframework.webflow.mvc.portlet;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.web.servlet.View;
import org.springframework.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.execution.RequestContext;
@@ -40,10 +41,12 @@ public class PortletMvcViewFactory extends AbstractMvcViewFactory {
* @param expressionParser the expression parser
* @param conversionService the conversion service
* @param binderConfiguration the model binding configuration
* @param messageCodesResolver
*/
public PortletMvcViewFactory(Expression viewId, FlowViewResolver viewResolver, ExpressionParser expressionParser,
ConversionService conversionService, BinderConfiguration binderConfiguration) {
super(viewId, viewResolver, expressionParser, conversionService, binderConfiguration);
ConversionService conversionService, BinderConfiguration binderConfiguration,
MessageCodesResolver messageCodesResolver) {
super(viewId, viewResolver, expressionParser, conversionService, binderConfiguration, messageCodesResolver);
}
protected AbstractMvcView createMvcView(View view, RequestContext context) {

View File

@@ -18,6 +18,7 @@ package org.springframework.webflow.mvc.servlet;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.web.servlet.View;
import org.springframework.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.execution.RequestContext;
@@ -41,8 +42,9 @@ public class ServletMvcViewFactory extends AbstractMvcViewFactory {
* @param binderConfiguration the model binding configuration
*/
public ServletMvcViewFactory(Expression viewId, FlowViewResolver viewResolver, ExpressionParser expressionParser,
ConversionService conversionService, BinderConfiguration binderConfiguration) {
super(viewId, viewResolver, expressionParser, conversionService, binderConfiguration);
ConversionService conversionService, BinderConfiguration binderConfiguration,
MessageCodesResolver messageCodesResolver) {
super(viewId, viewResolver, expressionParser, conversionService, binderConfiguration, messageCodesResolver);
}
protected AbstractMvcView createMvcView(View view, RequestContext context) {

View File

@@ -88,7 +88,7 @@ public abstract class AbstractMvcView implements View {
private BinderConfiguration binderConfiguration;
private MessageCodesResolver bindingErrorMessageCodesResolver = new WebFlowMessageCodesResolver();
private MessageCodesResolver messageCodesResolver = new WebFlowMessageCodesResolver();
/**
* Creates a new MVC view.
@@ -126,10 +126,10 @@ public abstract class AbstractMvcView implements View {
/**
* Set the message codes resolver to use to resolve bind and validation failure message codes.
* @param bindingErrorMessageCodesResolver the binding error message code resolver to use
* @param messageCodesResolver the binding error message code resolver to use
*/
public void setBindingErrorMessageCodesResolver(MessageCodesResolver bindingErrorMessageCodesResolver) {
this.bindingErrorMessageCodesResolver = bindingErrorMessageCodesResolver;
public void setMessageCodesResolver(MessageCodesResolver messageCodesResolver) {
this.messageCodesResolver = messageCodesResolver;
}
/**
@@ -498,7 +498,7 @@ public abstract class AbstractMvcView implements View {
String model = getModelExpression().getExpressionString();
String field = error.getMapping().getTargetExpression().getExpressionString();
Class fieldType = error.getMapping().getTargetExpression().getValueType(getModelObject());
String[] messageCodes = bindingErrorMessageCodesResolver.resolveMessageCodes(error.getCode(), model, field,
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();
@@ -517,7 +517,7 @@ public abstract class AbstractMvcView implements View {
logger.debug("Validating model");
}
new ValidationHelper(model, requestContext, eventId, getModelExpression().getExpressionString(),
expressionParser, bindingErrorMessageCodesResolver, mappingResults).validate();
expressionParser, messageCodesResolver, mappingResults).validate();
}
private static class PropertyNotFoundError implements MappingResultsCriteria {

View File

@@ -19,6 +19,7 @@ import org.springframework.binding.convert.ConversionService;
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.webflow.engine.builder.BinderConfiguration;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.View;
@@ -45,6 +46,8 @@ public abstract class AbstractMvcViewFactory implements ViewFactory {
private String fieldMarkerPrefix;
private MessageCodesResolver messageCodesResolver;
/**
* Creates a new MVC view factory.
* @param viewId the id of the view as an expression
@@ -54,12 +57,14 @@ public abstract class AbstractMvcViewFactory implements ViewFactory {
* @param binderConfiguration the model binding configuration
*/
public AbstractMvcViewFactory(Expression viewId, FlowViewResolver viewResolver, ExpressionParser expressionParser,
ConversionService conversionService, BinderConfiguration binderConfiguration) {
ConversionService conversionService, BinderConfiguration binderConfiguration,
MessageCodesResolver messageCodesResolver) {
this.viewId = viewId;
this.viewResolver = viewResolver;
this.expressionParser = expressionParser;
this.conversionService = conversionService;
this.binderConfiguration = binderConfiguration;
this.messageCodesResolver = messageCodesResolver;
}
public void setEventIdParameterName(String eventIdParameterName) {
@@ -77,6 +82,7 @@ public abstract class AbstractMvcViewFactory implements ViewFactory {
mvcView.setExpressionParser(expressionParser);
mvcView.setConversionService(conversionService);
mvcView.setBinderConfiguration(binderConfiguration);
mvcView.setMessageCodesResolver(messageCodesResolver);
if (StringUtils.hasText(eventIdParameterName)) {
mvcView.setEventIdParameterName(eventIdParameterName);
}

View File

@@ -54,7 +54,7 @@ public class ValidationHelper {
private final ExpressionParser expressionParser;
private final MessageCodesResolver bindingErrorMessageCodesResolver;
private final MessageCodesResolver messageCodesResolver;
private final MappingResults mappingResults;
@@ -76,7 +76,7 @@ public class ValidationHelper {
* @param mappingResults object mapping results
*/
public ValidationHelper(Object model, RequestContext requestContext, String eventId, String modelName,
ExpressionParser expressionParser, MessageCodesResolver bindingErrorMessageCodesResolver,
ExpressionParser expressionParser, MessageCodesResolver messageCodesResolver,
MappingResults mappingResults) {
Assert.notNull(model, "The model to validate is required");
Assert.notNull(requestContext, "The request context for the validator is required");
@@ -85,7 +85,7 @@ public class ValidationHelper {
this.eventId = eventId;
this.modelName = modelName;
this.expressionParser = expressionParser;
this.bindingErrorMessageCodesResolver = bindingErrorMessageCodesResolver;
this.messageCodesResolver = messageCodesResolver;
this.mappingResults = mappingResults;
}
@@ -128,7 +128,7 @@ public class ValidationHelper {
validateMethod = ReflectionUtils.findMethod(model.getClass(), methodName, new Class[] { Errors.class });
if (validateMethod != null) {
MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), modelName,
model, expressionParser, bindingErrorMessageCodesResolver, mappingResults);
model, expressionParser, messageCodesResolver, mappingResults);
if (logger.isDebugEnabled()) {
logger.debug("Invoking current state model validation method '" + methodName + "(Errors)'");
}
@@ -157,7 +157,7 @@ public class ValidationHelper {
logger.debug("Invoking default model validation method 'validate(Errors)'");
}
MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), modelName,
model, expressionParser, bindingErrorMessageCodesResolver, mappingResults);
model, expressionParser, messageCodesResolver, mappingResults);
ReflectionUtils.invokeMethod(validateMethod, model, new Object[] { errors });
return true;
}
@@ -205,7 +205,7 @@ public class ValidationHelper {
+ ClassUtils.getShortName(model.getClass()) + ", Errors)'");
}
MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), modelName,
model, expressionParser, bindingErrorMessageCodesResolver, mappingResults);
model, expressionParser, messageCodesResolver, mappingResults);
ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model, errors });
return true;
}
@@ -227,7 +227,7 @@ public class ValidationHelper {
logger.debug("Invoking Spring Validator '" + ClassUtils.getShortName(validator.getClass()) + "'");
}
MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), modelName,
model, expressionParser, bindingErrorMessageCodesResolver, mappingResults);
model, expressionParser, messageCodesResolver, mappingResults);
((Validator) validator).validate(model, errors);
return true;
}
@@ -252,7 +252,7 @@ public class ValidationHelper {
+ ".validate(" + ClassUtils.getShortName(model.getClass()) + ", Errors)'");
}
MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), modelName,
model, expressionParser, bindingErrorMessageCodesResolver, mappingResults);
model, expressionParser, messageCodesResolver, mappingResults);
ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model, errors });
return true;
}