diff --git a/spring-binding/src/main/java/org/springframework/binding/validation/ValidationContext.java b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationContext.java new file mode 100644 index 00000000..ccc646cf --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/validation/ValidationContext.java @@ -0,0 +1,46 @@ +/* + * Copyright 2008 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.binding.validation; + +import java.security.Principal; + +import org.springframework.binding.message.MessageContext; + +/** + * A context for validation events. + * + * @author Scott Andrews + * @since 2.0.4 + */ +public interface ValidationContext { + + /** + * Get the context for recording messages + */ + public MessageContext getMessageContext(); + + /** + * Get the current user principal + */ + public Principal getUserPrincipal(); + + /** + * Get the event that triggered validation + */ + public String getUserEvent(); + +} 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 c1cbfc07..bd5e7e87 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 @@ -15,7 +15,6 @@ */ package org.springframework.faces.webflow; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; @@ -28,17 +27,13 @@ import javax.faces.event.ActionListener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.BeanFactory; import org.springframework.binding.expression.Expression; -import org.springframework.binding.message.MessageContext; -import org.springframework.binding.message.MessageContextErrors; -import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; -import org.springframework.validation.Errors; import org.springframework.webflow.definition.TransitionDefinition; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.RequestContextHolder; import org.springframework.webflow.execution.View; +import org.springframework.webflow.validation.ValidationHelper; /** * The default {@link ActionListener} implementation to be used with Web Flow. @@ -104,7 +99,7 @@ public class FlowActionListener implements ActionListener { RequestContext requestContext = RequestContextHolder.getRequestContext(); Object model = getModelObject(requestContext); if (shouldValidate(requestContext, model, eventId)) { - validate(requestContext, model); + validate(requestContext, model, eventId); if (requestContext.getMessageContext().hasErrorMessages()) { isValid = false; if (requestContext.getExternalContext().isAjaxRequest()) { @@ -155,34 +150,8 @@ public class FlowActionListener implements ActionListener { return true; } - private void validate(RequestContext requestContext, Object model) { - String validateMethodName = "validate" + StringUtils.capitalize(requestContext.getCurrentState().getId()); - Method validateMethod = ReflectionUtils.findMethod(model.getClass(), validateMethodName, - new Class[] { MessageContext.class }); - if (validateMethod != null) { - ReflectionUtils.invokeMethod(validateMethod, model, new Object[] { requestContext.getMessageContext() }); - } - BeanFactory beanFactory = requestContext.getActiveFlow().getApplicationContext(); - if (beanFactory != null) { - String validatorName = getModelExpression(requestContext).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, - requestContext.getMessageContext() }); - } else { - validateMethod = ReflectionUtils.findMethod(validator.getClass(), validateMethodName, new Class[] { - model.getClass(), Errors.class }); - if (validateMethod != null) { - String objectName = getModelExpression(requestContext).getExpressionString(); - MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), - objectName, model, null, null); - ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model, errors }); - } - } - } - } + private void validate(RequestContext requestContext, Object model, String eventId) { + new ValidationHelper(model, requestContext, eventId, getModelExpression(requestContext).getExpressionString(), + null, null).validate(); } } diff --git a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/Booking.java b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/Booking.java index 9b153f2a..8dbdaef2 100755 --- a/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/Booking.java +++ b/spring-webflow-samples/booking-faces/src/main/java/org/springframework/webflow/samples/booking/Booking.java @@ -17,7 +17,7 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; import org.springframework.binding.message.MessageBuilder; -import org.springframework.binding.message.MessageContext; +import org.springframework.binding.validation.ValidationContext; /** * A Hotel Booking made by a User. @@ -189,13 +189,15 @@ public class Booking implements Serializable { this.amenities = amenities; } - public void validateEnterBookingDetails(MessageContext context) { + public void validateEnterBookingDetails(ValidationContext context) { + context.getUserEvent(); if (checkinDate.before(today())) { - context.addMessage(new MessageBuilder().error().source("checkinDate").code( - "booking.checkinDate.beforeToday").build()); + context.getMessageContext().addMessage( + new MessageBuilder().error().source("checkinDate").code("booking.checkinDate.beforeToday").build()); } else if (checkoutDate.before(checkinDate)) { - context.addMessage(new MessageBuilder().error().source("checkoutDate").code( - "booking.checkoutDate.beforeCheckinDate").build()); + context.getMessageContext().addMessage( + new MessageBuilder().error().source("checkoutDate").code("booking.checkoutDate.beforeCheckinDate") + .build()); } } diff --git a/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/Booking.java b/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/Booking.java index 75c0dbf2..30e3fe83 100755 --- a/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/Booking.java +++ b/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/Booking.java @@ -18,7 +18,7 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; import org.springframework.binding.message.MessageBuilder; -import org.springframework.binding.message.MessageContext; +import org.springframework.binding.validation.ValidationContext; /** * A Hotel Booking made by a User. @@ -188,13 +188,14 @@ public class Booking implements Serializable { this.amenities = amenities; } - public void validateEnterBookingDetails(MessageContext context) { + public void validateEnterBookingDetails(ValidationContext context) { if (checkinDate.before(today())) { - context.addMessage(new MessageBuilder().error().source("checkinDate").code( - "booking.checkinDate.beforeToday").build()); + context.getMessageContext().addMessage( + new MessageBuilder().error().source("checkinDate").code("booking.checkinDate.beforeToday").build()); } else if (checkoutDate.before(checkinDate)) { - context.addMessage(new MessageBuilder().error().source("checkoutDate").code( - "booking.checkoutDate.beforeCheckinDate").build()); + context.getMessageContext().addMessage( + new MessageBuilder().error().source("checkoutDate").code("booking.checkoutDate.beforeCheckinDate") + .build()); } } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcView.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcView.java index 5bc7709b..2e473dd9 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcView.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AbstractMvcView.java @@ -17,7 +17,6 @@ package org.springframework.webflow.mvc.view; import java.io.IOException; import java.lang.reflect.Array; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -26,7 +25,6 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.BeanFactory; import org.springframework.binding.convert.ConversionExecutor; import org.springframework.binding.convert.ConversionService; import org.springframework.binding.expression.EvaluationException; @@ -41,13 +39,8 @@ import org.springframework.binding.mapping.MappingResultsCriteria; import org.springframework.binding.mapping.impl.DefaultMapper; import org.springframework.binding.mapping.impl.DefaultMapping; import org.springframework.binding.message.MessageBuilder; -import org.springframework.binding.message.MessageContext; -import org.springframework.binding.message.MessageContextErrors; 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.web.util.WebUtils; import org.springframework.webflow.core.collection.ParameterMap; import org.springframework.webflow.definition.TransitionDefinition; @@ -57,6 +50,7 @@ import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.FlowExecutionKey; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.View; +import org.springframework.webflow.validation.ValidationHelper; /** * Base view implementation for the Spring Web MVC Servlet and Spring Web MVC Portlet frameworks. @@ -414,34 +408,8 @@ public abstract class AbstractMvcView implements View { } private void validate(Object model) { - String validateMethodName = "validate" + StringUtils.capitalize(requestContext.getCurrentState().getId()); - Method validateMethod = ReflectionUtils.findMethod(model.getClass(), validateMethodName, - new Class[] { MessageContext.class }); - if (validateMethod != null) { - ReflectionUtils.invokeMethod(validateMethod, model, new Object[] { requestContext.getMessageContext() }); - } - BeanFactory beanFactory = requestContext.getActiveFlow().getApplicationContext(); - if (beanFactory != null) { - 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, - requestContext.getMessageContext() }); - } else { - validateMethod = ReflectionUtils.findMethod(validator.getClass(), validateMethodName, new Class[] { - model.getClass(), Errors.class }); - if (validateMethod != null) { - String objectName = getModelExpression().getExpressionString(); - MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), - objectName, model, expressionParser, mappingResults); - ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model, errors }); - } - } - } - } + new ValidationHelper(model, requestContext, eventId, getModelExpression().getExpressionString(), + expressionParser, mappingResults).validate(); } private void determineEventId(RequestContext context) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/validation/DefaultValidationContext.java b/spring-webflow/src/main/java/org/springframework/webflow/validation/DefaultValidationContext.java new file mode 100644 index 00000000..92c8a451 --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/validation/DefaultValidationContext.java @@ -0,0 +1,37 @@ +package org.springframework.webflow.validation; + +import java.security.Principal; + +import org.springframework.binding.message.MessageContext; +import org.springframework.binding.validation.ValidationContext; +import org.springframework.webflow.execution.RequestContext; + +public class DefaultValidationContext implements ValidationContext { + + private RequestContext requestContext; + private String eventId; + + public DefaultValidationContext(RequestContext requestContext, String eventId) { + this.requestContext = requestContext; + this.eventId = eventId; + } + + public MessageContext getMessageContext() { + return requestContext.getMessageContext(); + } + + public String getUserEvent() { + if (eventId != null) { + return eventId; + } else if (requestContext.getCurrentEvent() != null) { + return requestContext.getCurrentEvent().getId(); + } else { + return null; + } + } + + public Principal getUserPrincipal() { + return requestContext.getExternalContext().getCurrentUser(); + } + +} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/validation/ValidationHelper.java b/spring-webflow/src/main/java/org/springframework/webflow/validation/ValidationHelper.java new file mode 100644 index 00000000..1fabbfde --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/validation/ValidationHelper.java @@ -0,0 +1,155 @@ +/* + * Copyright 2008 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.webflow.validation; + +import java.lang.reflect.Method; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.binding.expression.ExpressionParser; +import org.springframework.binding.mapping.MappingResults; +import org.springframework.binding.message.MessageContext; +import org.springframework.binding.message.MessageContextErrors; +import org.springframework.binding.validation.ValidationContext; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; +import org.springframework.validation.Errors; +import org.springframework.webflow.execution.RequestContext; + +/** + * A helper class the encapsulates conventions to invoke validation logic. + * + * @author Scott Andrews + */ +public class ValidationHelper { + + private final Object model; + private final RequestContext requestContext; + private final String eventId; + private final String modelName; + private final ExpressionParser expressionParser; + private final MappingResults mappingResults; + + /** + * Create a throwaway validation helper object. Validation is invoked by the {@link #validate()} method. + *
+ * Validation methods invoked include a validation method on the model object or a validator bean. The method name + * on either object is in the form of validate[viewStateId]. A ValidationContext is passed in the method signature + * along with the model object for validator beans. A MessageContext can be substituted for the ValidationContext. + *
+ * For example: model.validateEnterBookingDetails(VaticationContext) or
+ * context.getBean("modelValidator").validateEnterBookingDetails(model, VaticationContext)
+ *
+ * @param model the object to validate
+ * @param requestContext the context for the request
+ * @param eventId the event triggering validation
+ * @param modelName the name of the model object
+ * @param expressionParser the expression parser
+ * @param mappingResults object mapping results
+ */
+ public ValidationHelper(Object model, RequestContext requestContext, String eventId, String modelName,
+ ExpressionParser expressionParser, MappingResults mappingResults) {
+ this.model = model;
+ this.requestContext = requestContext;
+ this.eventId = eventId;
+ this.modelName = modelName;
+ this.expressionParser = expressionParser;
+ this.mappingResults = mappingResults;
+ }
+
+ /**
+ * Invoke the validators available by convention.
+ */
+ public void validate() {
+ String validateMethodName = "validate" + StringUtils.capitalize(requestContext.getCurrentState().getId());
+ validateWithContext(model, validateMethodName);
+ BeanFactory beanFactory = requestContext.getActiveFlow().getApplicationContext();
+ if (beanFactory != null) {
+ String validatorName = modelName + "Validator";
+ if (beanFactory.containsBean(validatorName)) {
+ Object validator = beanFactory.getBean(validatorName);
+ if (!validateWithModelAndContext(model, validator, validateMethodName)) {
+ validateWithModelAndErrors(model, validator, validateMethodName);
+ }
+ }
+ }
+ }
+
+ /*
+ * Invoke validate method on the model for the current state passing either a MessageContext or ValidationContext.
+ * Preference is given to the ValidationContext method.
+ */
+ private boolean validateWithContext(Object model, String validateMethodName) {
+ boolean validationInvoked = false;
+ Method validateMethod = ReflectionUtils.findMethod(model.getClass(), validateMethodName,
+ new Class[] { ValidationContext.class });
+ if (validateMethod != null) {
+ ReflectionUtils.invokeMethod(validateMethod, model, new Object[] { new DefaultValidationContext(
+ requestContext, eventId) });
+ validationInvoked = true;
+ } else {
+ validateMethod = ReflectionUtils.findMethod(model.getClass(), validateMethodName,
+ new Class[] { MessageContext.class });
+ if (validateMethod != null) {
+ ReflectionUtils
+ .invokeMethod(validateMethod, model, new Object[] { requestContext.getMessageContext() });
+ validationInvoked = true;
+ }
+ }
+ return validationInvoked;
+ }
+
+ /*
+ * Invoke validate method on a distinct validator providing the model to validate and either a MessageContext or
+ * ValidationContext. Preference is given to the ValidationContext method.
+ */
+ private boolean validateWithModelAndContext(Object model, Object validator, String validateMethodName) {
+ boolean validationInvoked = false;
+ Method validateMethod = ReflectionUtils.findMethod(validator.getClass(), validateMethodName, new Class[] {
+ model.getClass(), ValidationContext.class });
+ if (validateMethod != null) {
+ ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model,
+ new DefaultValidationContext(requestContext, eventId) });
+ validationInvoked = true;
+ } else {
+ validateMethod = ReflectionUtils.findMethod(validator.getClass(), validateMethodName, new Class[] {
+ model.getClass(), MessageContext.class });
+ if (validateMethod != null) {
+ ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model,
+ requestContext.getMessageContext() });
+ validationInvoked = true;
+ }
+ }
+ return validationInvoked;
+ }
+
+ /*
+ * Invoke validate method on a distinct validator providing the model to validate and an Errors object.
+ */
+ private boolean validateWithModelAndErrors(Object model, Object validator, String validateMethodName) {
+ boolean validationInvoked = false;
+ Method validateMethod = ReflectionUtils.findMethod(validator.getClass(), validateMethodName, new Class[] {
+ model.getClass(), Errors.class });
+ if (validateMethod != null) {
+ MessageContextErrors errors = new MessageContextErrors(requestContext.getMessageContext(), modelName,
+ model, expressionParser, mappingResults);
+ ReflectionUtils.invokeMethod(validateMethod, validator, new Object[] { model, errors });
+ validationInvoked = true;
+ }
+ return validationInvoked;
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelErrors.java b/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelErrors.java
new file mode 100644
index 00000000..adc27a59
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelErrors.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.webflow.validation;
+
+import org.springframework.validation.Errors;
+
+/**
+ * Support class for {@link ValidationHelperTest}
+ */
+public class StubModelErrors {
+
+ public void validateMockState(Object model, Errors errors) {
+ errors.rejectValue("errors-external", "", "");
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelErrorsOverridden.java b/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelErrorsOverridden.java
new file mode 100644
index 00000000..830379a1
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelErrorsOverridden.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.webflow.validation;
+
+import org.springframework.validation.Errors;
+
+/**
+ * Support class for {@link ValidationHelperTest}
+ */
+public class StubModelErrorsOverridden extends StubModelValidationContext {
+
+ public void validateMockState(Object model, Errors errors) {
+ errors.rejectValue("errors-context", "", "");
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelMessageContext.java b/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelMessageContext.java
new file mode 100644
index 00000000..299fc750
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelMessageContext.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.webflow.validation;
+
+import org.springframework.binding.message.MessageBuilder;
+import org.springframework.binding.message.MessageContext;
+
+/**
+ * Support class for {@link ValidationHelperTest}
+ */
+public class StubModelMessageContext {
+
+ public void validateMockState(MessageContext context) {
+ context.addMessage(new MessageBuilder().source("messagecontext").defaultText("").build());
+ }
+
+ public void validateMockState(Object model, MessageContext context) {
+ context.addMessage(new MessageBuilder().source("messagecontext-external").defaultText("").build());
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelValidationContext.java b/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelValidationContext.java
new file mode 100644
index 00000000..ec9c3c44
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/validation/StubModelValidationContext.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.webflow.validation;
+
+import org.springframework.binding.message.MessageBuilder;
+import org.springframework.binding.validation.ValidationContext;
+
+/**
+ * Support class for {@link ValidationHelperTest}
+ */
+public class StubModelValidationContext {
+
+ public void validateMockState(ValidationContext context) {
+ context.getMessageContext()
+ .addMessage(new MessageBuilder().source("validationcontext").defaultText("").build());
+ }
+
+ public void validateMockState(Object model, ValidationContext context) {
+ context.getMessageContext().addMessage(
+ new MessageBuilder().source("validationcontext-external").defaultText("").build());
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/validation/ValidationHelperTests.java b/spring-webflow/src/test/java/org/springframework/webflow/validation/ValidationHelperTests.java
new file mode 100644
index 00000000..202958ab
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/validation/ValidationHelperTests.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.webflow.validation;
+
+import junit.framework.TestCase;
+
+import org.springframework.binding.message.MessageContext;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.webflow.engine.Flow;
+import org.springframework.webflow.test.MockRequestContext;
+
+/**
+ * Unit test for {@link ValidationHelper}
+ */
+public class ValidationHelperTests extends TestCase {
+
+ private MockRequestContext requestContext;
+ private String eventId;
+ private String modelName;
+
+ protected void setUp() throws Exception {
+ requestContext = new MockRequestContext();
+ eventId = "userEvent";
+ modelName = "model";
+ }
+
+ public void testValidateWithMessageContext() {
+ Object model = new StubModelMessageContext();
+ ValidationHelper helper = new ValidationHelper(model, requestContext, eventId, modelName, null, null);
+ helper.validate();
+ MessageContext messages = requestContext.getMessageContext();
+ assertEquals(1, messages.getAllMessages().length);
+ assertEquals(1, messages.getMessagesBySource("messagecontext").length);
+ assertEquals(0, messages.getMessagesBySource("validationcontext").length);
+ }
+
+ public void testValidateWithValidatioContext() {
+ Object model = new StubModelValidationContext();
+ ValidationHelper helper = new ValidationHelper(model, requestContext, eventId, modelName, null, null);
+ helper.validate();
+ MessageContext messages = requestContext.getMessageContext();
+ assertEquals(1, messages.getAllMessages().length);
+ assertEquals(1, messages.getMessagesBySource("validationcontext").length);
+ }
+
+ public void testValidateWithMessageContextForBeanValidator() {
+ StaticApplicationContext applicationContext = new StaticApplicationContext();
+ applicationContext.registerSingleton("modelValidator", StubModelMessageContext.class);
+ ((Flow) requestContext.getActiveFlow()).setApplicationContext(applicationContext);
+ ValidationHelper helper = new ValidationHelper(new Object(), requestContext, eventId, modelName, null, null);
+ helper.validate();
+ MessageContext messages = requestContext.getMessageContext();
+ assertEquals(1, messages.getAllMessages().length);
+ assertEquals(1, messages.getMessagesBySource("messagecontext-external").length);
+ }
+
+ public void testValidateWithValidationContextForBeanValidator() {
+ StaticApplicationContext applicationContext = new StaticApplicationContext();
+ applicationContext.registerSingleton("modelValidator", StubModelValidationContext.class);
+ ((Flow) requestContext.getActiveFlow()).setApplicationContext(applicationContext);
+ ValidationHelper helper = new ValidationHelper(new Object(), requestContext, eventId, modelName, null, null);
+ helper.validate();
+ MessageContext messages = requestContext.getMessageContext();
+ assertEquals(1, messages.getAllMessages().length);
+ assertEquals(1, messages.getMessagesBySource("validationcontext-external").length);
+ }
+
+ public void testValidateWithErrorsForBeanValidator() {
+ StaticApplicationContext applicationContext = new StaticApplicationContext();
+ applicationContext.registerSingleton("modelValidator", StubModelErrors.class);
+ ((Flow) requestContext.getActiveFlow()).setApplicationContext(applicationContext);
+ ValidationHelper helper = new ValidationHelper(new Object(), requestContext, eventId, modelName, null, null);
+ helper.validate();
+ MessageContext messages = requestContext.getMessageContext();
+ assertEquals(1, messages.getAllMessages().length);
+ assertEquals(1, messages.getMessagesBySource("errors-external").length);
+ }
+
+ public void testValidateWithErrorsForBeanValidatorOverridden() {
+ StaticApplicationContext applicationContext = new StaticApplicationContext();
+ applicationContext.registerSingleton("modelValidator", StubModelErrorsOverridden.class);
+ ((Flow) requestContext.getActiveFlow()).setApplicationContext(applicationContext);
+ ValidationHelper helper = new ValidationHelper(new Object(), requestContext, eventId, modelName, null, null);
+ helper.validate();
+ MessageContext messages = requestContext.getMessageContext();
+ assertEquals(1, messages.getAllMessages().length);
+ assertEquals(1, messages.getMessagesBySource("validationcontext-external").length);
+ }
+
+}