several bug fixes
This commit is contained in:
@@ -52,9 +52,8 @@ class DefaultMessageContext implements StateManageableMessageContext {
|
||||
|
||||
public Message[] getAllMessages() {
|
||||
List messages = new ArrayList();
|
||||
Iterator it = objectMessages.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
messages.addAll((List) objectMessages.get(it.next()));
|
||||
for (Iterator it = objectMessages.values().iterator(); it.hasNext();) {
|
||||
messages.addAll((List) it.next());
|
||||
}
|
||||
return (Message[]) messages.toArray(new Message[messages.size()]);
|
||||
}
|
||||
@@ -80,6 +79,20 @@ class DefaultMessageContext implements StateManageableMessageContext {
|
||||
return (Message[]) messages.toArray(new Message[messages.size()]);
|
||||
}
|
||||
|
||||
public boolean hasErrorMessages() {
|
||||
Iterator it = objectMessages.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
List sourceMessages = (List) it.next();
|
||||
for (Iterator it2 = sourceMessages.iterator(); it2.hasNext();) {
|
||||
Message message = (Message) it2.next();
|
||||
if (message.getSeverity() == Severity.ERROR) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addMessage(MessageResolver messageResolver) {
|
||||
Locale currentLocale = LocaleContextHolder.getLocale();
|
||||
Message message = messageResolver.resolveMessage(messageSource, currentLocale);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.springframework.binding.message;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -84,6 +85,18 @@ public class MessageBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that the message being built should try and resolve its text using the codes provided. Adds the codes to
|
||||
* the codes list. Successive calls to this method add additional codes. Codes are applied in the order they are
|
||||
* added.
|
||||
* @param codes the message codes
|
||||
* @return this, for fluent API usage
|
||||
*/
|
||||
public MessageBuilder codes(String[] codes) {
|
||||
this.codes.add(Arrays.asList(codes));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that the message being built has a variable argument. Adds the arg to the args list. Successive calls to
|
||||
* this method add additional args. Args are applied in the order they are added.
|
||||
@@ -95,6 +108,17 @@ public class MessageBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that the message being built has variable arguments. Adds the args to the args list. Successive calls to
|
||||
* this method add additional args. Args are applied in the order they are added.
|
||||
* @param arg the message argument value
|
||||
* @return this, for fluent API usage
|
||||
*/
|
||||
public MessageBuilder args(Object[] args) {
|
||||
this.args.add(Arrays.asList(args));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that the message being built has a variable argument, whose display value is also
|
||||
* {@link MessageSourceResolvable}. Adds the arg to the args list. Successive calls to this method add additional
|
||||
@@ -107,6 +131,20 @@ public class MessageBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that the message being built has variable arguments, whose display values are also
|
||||
* {@link MessageSourceResolvable} instances. Adds the args to the args list. Successive calls to this method add
|
||||
* additional resolvable args. Args are applied in the order they are added.
|
||||
* @param args the resolvable message arguments
|
||||
* @return this, for fluent API usage
|
||||
*/
|
||||
public MessageBuilder resolvableArgs(Object[] args) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
this.args.add(new ResolvableArgument(args[i]));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the fallback text of the message being built. If the message has no codes, this will always be used as
|
||||
* the text. If the message has codes but none can be resolved, this will alway be used as the text.
|
||||
|
||||
@@ -24,6 +24,12 @@ public interface MessageContext {
|
||||
*/
|
||||
public Message[] getMessagesByCriteria(MessageCriteria criteria);
|
||||
|
||||
/**
|
||||
* Returns true if there are error messages in this context.
|
||||
* @return error messages
|
||||
*/
|
||||
public boolean hasErrorMessages();
|
||||
|
||||
/**
|
||||
* Add a new message to this context.
|
||||
* @param messageResolver the resolver that will resolve the message to be added
|
||||
|
||||
@@ -118,6 +118,10 @@ public class FlowFacesContextTests extends TestCase {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public boolean hasErrorMessages() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public void clearMessages() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
@@ -150,6 +154,10 @@ public class FlowFacesContextTests extends TestCase {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public boolean hasErrorMessages() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public void clearMessages() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ public class Booking implements Serializable {
|
||||
this.creditCardExpiryYear = creditCardExpiryYear;
|
||||
}
|
||||
|
||||
public boolean validate(MessageContext context) {
|
||||
public boolean validateEnterBookingDetails(MessageContext context) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
boolean valid = true;
|
||||
|
||||
@@ -176,7 +176,7 @@ public class Booking implements Serializable {
|
||||
this.creditCardExpiryYear = creditCardExpiryYear;
|
||||
}
|
||||
|
||||
public boolean validate(MessageContext context) {
|
||||
public boolean validateEnterBookingDetails(MessageContext context) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
boolean valid = true;
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
</on-start>
|
||||
|
||||
<view-state id="enterBookingDetails" model="booking">
|
||||
<transition on="proceed" to="reviewBooking">
|
||||
<evaluate expression="booking.validate(messageContext)"/>
|
||||
</transition>
|
||||
<transition on="proceed" to="reviewBooking" />
|
||||
<transition on="cancel" to="cancel" bind="false" />
|
||||
</view-state>
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.springframework.webflow.mvc.view;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.binding.message.MessageBuilder;
|
||||
import org.springframework.binding.message.MessageContext;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
|
||||
public class MessageContextErrors implements Errors {
|
||||
|
||||
private MessageContext messageContext;
|
||||
|
||||
public MessageContextErrors(MessageContext messageContext) {
|
||||
this.messageContext = messageContext;
|
||||
}
|
||||
|
||||
public void reject(String errorCode) {
|
||||
messageContext.addMessage(new MessageBuilder().error().code(errorCode).build());
|
||||
}
|
||||
|
||||
public void reject(String errorCode, String defaultMessage) {
|
||||
messageContext.addMessage(new MessageBuilder().error().code(errorCode).defaultText(defaultMessage).build());
|
||||
}
|
||||
|
||||
public void reject(String errorCode, Object[] errorArgs, String defaultMessage) {
|
||||
messageContext.addMessage(new MessageBuilder().error().code(errorCode).defaultText(defaultMessage).build());
|
||||
}
|
||||
|
||||
public void rejectValue(String field, String errorCode) {
|
||||
messageContext.addMessage(new MessageBuilder().error().source(field).code(errorCode).build());
|
||||
}
|
||||
|
||||
public void rejectValue(String field, String errorCode, String defaultMessage) {
|
||||
messageContext.addMessage(new MessageBuilder().error().source(field).code(errorCode)
|
||||
.defaultText(defaultMessage).build());
|
||||
}
|
||||
|
||||
public void rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage) {
|
||||
messageContext.addMessage(new MessageBuilder().error().source(field).code(errorCode).args(errorArgs)
|
||||
.defaultText(defaultMessage).build());
|
||||
}
|
||||
|
||||
public void addAllErrors(Errors errors) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public List getAllErrors() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public int getErrorCount() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public FieldError getFieldError() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public FieldError getFieldError(String field) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public int getFieldErrorCount() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public int getFieldErrorCount(String field) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public List getFieldErrors() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public List getFieldErrors(String field) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public Class getFieldType(String field) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public Object getFieldValue(String field) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public ObjectError getGlobalError() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public int getGlobalErrorCount() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public List getGlobalErrors() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public String getNestedPath() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public String getObjectName() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public boolean hasErrors() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public boolean hasFieldErrors() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public boolean hasFieldErrors(String field) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public boolean hasGlobalErrors() {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public void popNestedPath() throws IllegalStateException {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public void pushNestedPath(String subPath) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
public void setNestedPath(String nestedPath) {
|
||||
throw new UnsupportedOperationException("Should not be called by a validator");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.webflow.mvc.view;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -24,6 +25,7 @@ import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.binding.collection.MapAdaptable;
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
@@ -41,8 +43,12 @@ import org.springframework.binding.mapping.impl.DefaultMapper;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapping;
|
||||
import org.springframework.binding.mapping.impl.DefaultMappingContext;
|
||||
import org.springframework.binding.message.MessageBuilder;
|
||||
import org.springframework.binding.message.MessageContext;
|
||||
import org.springframework.binding.message.MessageResolver;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.webflow.core.collection.ParameterMap;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
import org.springframework.webflow.definition.TransitionableStateDefinition;
|
||||
@@ -115,9 +121,14 @@ class MvcView implements View {
|
||||
}
|
||||
if (shouldBind(model)) {
|
||||
mappingResults = bind(model);
|
||||
if (mappingResults.hasErrorResults() && !onlyPropertyNotFoundErrorsPresent(mappingResults)) {
|
||||
if (hasMappingErrors(mappingResults)) {
|
||||
viewErrors = true;
|
||||
addErrorMessages(mappingResults);
|
||||
} else {
|
||||
validate(model);
|
||||
if (context.getMessageContext().hasErrorMessages()) {
|
||||
viewErrors = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,6 +202,10 @@ class MvcView implements View {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasMappingErrors(MappingResults results) {
|
||||
return results.hasErrorResults() && !onlyPropertyNotFoundErrorsPresent(results);
|
||||
}
|
||||
|
||||
private boolean onlyPropertyNotFoundErrorsPresent(MappingResults results) {
|
||||
return results.getResults(PROPERTY_NOT_FOUND_ERROR).size() == mappingResults.getErrorResults().size();
|
||||
}
|
||||
@@ -212,6 +227,33 @@ class MvcView implements View {
|
||||
.defaultText(errorCode + " on " + field).build();
|
||||
}
|
||||
|
||||
private void validate(Object model) {
|
||||
String validateMethodName = "validate" + StringUtils.capitalize(context.getCurrentState().getId());
|
||||
Method validateMethod = ReflectionUtils.findMethod(model.getClass(), validateMethodName,
|
||||
new Class[] { MessageContext.class });
|
||||
if (validateMethod != null) {
|
||||
ReflectionUtils.invokeMethod(validateMethod, model, new Object[] { context.getMessageContext() });
|
||||
}
|
||||
BeanFactory beanFactory = context.getActiveFlow().getBeanFactory();
|
||||
String validatorName = getModelExpression().getExpressionString() + "Validator";
|
||||
if (beanFactory.containsBean(validatorName)) {
|
||||
Object validator = beanFactory.getBean(validatorName);
|
||||
validateMethod = ReflectionUtils.findMethod(validator.getClass(), validateMethodName, new Class[] {
|
||||
model.getClass(), MessageContext.class });
|
||||
if (validateMethod != null) {
|
||||
ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model,
|
||||
context.getMessageContext() });
|
||||
} else {
|
||||
validateMethod = ReflectionUtils.findMethod(validator.getClass(), validateMethodName, new Class[] {
|
||||
model.getClass(), Errors.class });
|
||||
if (validateMethod != null) {
|
||||
ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model,
|
||||
new MessageContextErrors(context.getMessageContext()) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void determineEventId(RequestContext context) {
|
||||
eventId = findParameter("_eventId", context.getRequestParameters());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user