Fix for bean validation messages in BindingResult

Previously Web Flow's BindingResult implementation distinguished
object from field-level errors by checking if the source of the
error is null or otherwise a String. However, class-level bean
validation errors have a field source represented by an empty
String. After this change object and field-level errors are
recognized by checking for String-based field source that is
neither null nor empty.

This commit also contains a fix for spring-faces tests where
in JSF 2.1 the presence of an unreleased FacesContext may
cause some tests to fail.
This commit is contained in:
Rossen Stoyanchev
2012-02-28 13:22:13 -05:00
parent 85d8d73c1d
commit df649084ab
4 changed files with 27 additions and 9 deletions

View File

@@ -5,8 +5,8 @@ http://www.springframework.org/webflow
Changes in version 2.3.1.RELEASE
-----------------------------------------------
Upgrade JSF Mojarra version to 2.1.7
Improve Jsf2FlowFacesContext.isValidationFailed() to check Web Flow's MessageContext for errors
Modify Jsf2FlowFacesContext.isValidationFailed() to check Web Flow's MessageContext for errors
Recognize class-level bean validation messages in BindingResult.getGlobalErrors()
Changes in version 2.3.0.RELEASE (Feb 28, 2011)
-----------------------------------------------

View File

@@ -18,6 +18,7 @@ package org.springframework.binding.message;
import java.io.Serializable;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.StringUtils;
/**
* An object of communication that provides text information. For example, a validation message may inform a web
@@ -49,7 +50,8 @@ public class Message implements Serializable {
/**
* A reference to the source element this message is associated with. This could be a field on a form in UI, or null
* if the message is not associated with a any particular element.
* (or empty "" in the case of global bean validation) if the message is not associated with a any particular
* element.
* @return the source
*/
public Object getSource() {
@@ -72,6 +74,18 @@ public class Message implements Serializable {
return severity;
}
/**
* Whether the message is associated with a field.
* @return {@code true} if the source is a String that has text; {@code false} otherwise.
*/
public boolean hasField() {
if (this.source instanceof String) {
return StringUtils.hasText((String) this.source);
} else {
return false;
}
}
public String toString() {
return new ToStringCreator(this).append("source", source).append("severity", severity).append("text", text)
.toString();

View File

@@ -113,6 +113,11 @@ public class JSFMockHelper {
public void setUp() throws Exception {
// Ensure no pre-existing FacesContext ..
if (FacesContext.getCurrentInstance() != null) {
FacesContext.getCurrentInstance().release();
}
// Set up a new thread context class loader
threadContextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(
@@ -132,8 +137,7 @@ public class JSFMockHelper {
FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY, MockBaseFacesContextFactory.class.getName());
FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY, MockLifecycleFactory.class.getName());
FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY, MockRenderKitFactory.class.getName());
FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY, MockPartialViewContextFactory.class
.getName());
FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY, MockPartialViewContextFactory.class.getName());
lifecycleFactory = (MockLifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
lifecycle = (MockLifecycle) lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);

View File

@@ -111,7 +111,7 @@ public class BindingModel extends AbstractErrors implements BindingResult {
}
public List getGlobalErrors() {
return toErrors(messageContext.getMessagesByCriteria(ERRORS_NULL_SOURCE));
return toErrors(messageContext.getMessagesByCriteria(ERRORS_WITHOUT_FIELD_SOURCE));
}
public List getFieldErrors(String field) {
@@ -318,15 +318,15 @@ public class BindingModel extends AbstractErrors implements BindingResult {
}
};
private static final MessageCriteria ERRORS_NULL_SOURCE = new MessageCriteria() {
private static final MessageCriteria ERRORS_WITHOUT_FIELD_SOURCE = new MessageCriteria() {
public boolean test(Message message) {
return message.getSource() == null && message.getSeverity() == Severity.ERROR;
return (!message.hasField() && message.getSeverity() == Severity.ERROR);
}
};
private static final MessageCriteria ERRORS_FIELD_SOURCE = new MessageCriteria() {
public boolean test(Message message) {
return message.getSeverity() == Severity.ERROR && message.getSource() instanceof String;
return (message.hasField() && message.getSeverity() == Severity.ERROR);
}
};