From c8abdf0139a935e4cf92b82853aa62925f640a06 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Sun, 10 Apr 2016 23:09:13 +0200 Subject: [PATCH] DATAREST-805 - ValidationError nor exposes rejected value as is. Previously ValidationError captured the toString() variant of the rejected value. We now return the rejected value as is. --- ...ryConstraintViolationExceptionMessage.java | 56 +++++------- ...intViolationExceptionMessageUnitTests.java | 90 +++++++++++++++++++ 2 files changed, 111 insertions(+), 35 deletions(-) create mode 100644 spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessageUnitTests.java diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessage.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessage.java index b9c64575c..8f10efb3c 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessage.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2016 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. @@ -15,11 +15,14 @@ */ package org.springframework.data.rest.webmvc.support; +import lombok.Value; + import java.util.ArrayList; import java.util.List; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.data.rest.core.RepositoryConstraintViolationException; +import org.springframework.util.Assert; import org.springframework.validation.FieldError; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,15 +35,22 @@ public class RepositoryConstraintViolationExceptionMessage { private final List errors = new ArrayList(); - public RepositoryConstraintViolationExceptionMessage(RepositoryConstraintViolationException violationException, + /** + * Creates a new {@link RepositoryConstraintViolationExceptionMessage} for the given + * {@link RepositoryConstraintViolationException} and {@link MessageSourceAccessor}. + * + * @param exception must not be {@literal null}. + * @param accessor must not be {@literal null}. + */ + public RepositoryConstraintViolationExceptionMessage(RepositoryConstraintViolationException exception, MessageSourceAccessor accessor) { - for (FieldError fieldError : violationException.getErrors().getFieldErrors()) { + Assert.notNull(exception, "RepositoryConstraintViolationException must not be null!"); + Assert.notNull(accessor, "MessageSourceAccessor must not be null!"); - String message = accessor.getMessage(fieldError); - - this.errors.add(new ValidationError(fieldError.getObjectName(), message, - String.format("%s", fieldError.getRejectedValue()), fieldError.getField())); + for (FieldError fieldError : exception.getErrors().getFieldErrors()) { + this.errors.add(ValidationError.of(fieldError.getObjectName(), fieldError.getField(), + fieldError.getRejectedValue(), accessor.getMessage(fieldError))); } } @@ -49,34 +59,10 @@ public class RepositoryConstraintViolationExceptionMessage { return errors; } + @Value(staticConstructor = "of") public static class ValidationError { - - private final String entity; - private final String message; - private final String invalidValue; - private final String property; - - public ValidationError(String entity, String message, String invalidValue, String property) { - this.entity = entity; - this.message = message; - this.invalidValue = invalidValue; - this.property = property; - } - - public String getEntity() { - return entity; - } - - public String getMessage() { - return message; - } - - public String getInvalidValue() { - return invalidValue; - } - - public String getProperty() { - return property; - } + String entity, property; + Object invalidValue; + String message; } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessageUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessageUnitTests.java new file mode 100644 index 000000000..a8c2a9272 --- /dev/null +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessageUnitTests.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016 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.data.rest.webmvc.support; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.support.MessageSourceAccessor; +import org.springframework.context.support.StaticMessageSource; +import org.springframework.data.rest.core.RepositoryConstraintViolationException; +import org.springframework.data.rest.webmvc.support.RepositoryConstraintViolationExceptionMessage.ValidationError; +import org.springframework.validation.Errors; +import org.springframework.validation.MapBindingResult; + +/** + * Unit tests for {@link RepositoryConstraintViolationExceptionMessage} + * + * @author Oliver Gierke + */ +public class RepositoryConstraintViolationExceptionMessageUnitTests { + + MessageSourceAccessor accessor; + RepositoryConstraintViolationException exception; + + @Before + public void setUp() { + + StaticMessageSource messageSource = new StaticMessageSource(); + messageSource.addMessage("code", Locale.ENGLISH, "message"); + + this.accessor = new MessageSourceAccessor(messageSource, Locale.ENGLISH); + this.exception = new RepositoryConstraintViolationException(new MapBindingResult(Collections.emptyMap(), "object")); + } + + @Test(expected = IllegalArgumentException.class) + public void rejectsNullException() { + new RepositoryConstraintViolationExceptionMessage(null, accessor); + } + + @Test(expected = IllegalArgumentException.class) + public void rejectsNullAccessor() { + new RepositoryConstraintViolationExceptionMessage(exception, null); + } + + @Test + public void calidationErrorsCaptureRejectedValueAsIs() { + + assertRejectedValue("stringValue", "string"); + assertRejectedValue("intValue", 1); + assertRejectedValue("nullValue", null); + } + + private void assertRejectedValue(String key, Object value) { + + Map map = new HashMap(); + map.put(key, value); + + Errors errors = new MapBindingResult(map, "object"); + errors.rejectValue(key, "code"); + + RepositoryConstraintViolationExceptionMessage message = new RepositoryConstraintViolationExceptionMessage( + new RepositoryConstraintViolationException(errors), accessor); + + List result = message.getErrors(); + + assertThat(result, hasSize(1)); + assertThat(result.get(0).getInvalidValue(), is(value)); + } +}