diff --git a/spring-data-rest-example/src/main/java/org/springframework/data/rest/example/RestExporterExampleRestConfig.java b/spring-data-rest-example/src/main/java/org/springframework/data/rest/example/RestExporterExampleRestConfig.java index dac711571..0266164bb 100644 --- a/spring-data-rest-example/src/main/java/org/springframework/data/rest/example/RestExporterExampleRestConfig.java +++ b/spring-data-rest-example/src/main/java/org/springframework/data/rest/example/RestExporterExampleRestConfig.java @@ -27,9 +27,9 @@ public class RestExporterExampleRestConfig extends RepositoryRestMvcConfiguratio return msgsrc; } - @Bean public PersonValidator beforeCreatePersonValidator() { - return new PersonValidator(); - } +// @Bean public PersonValidator beforeCreatePersonValidator() { +// return new PersonValidator(); +// } @Override protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.addResourceMappingForDomainType(Person.class) diff --git a/spring-data-rest-example/src/main/java/org/springframework/data/rest/example/jpa/Person.java b/spring-data-rest-example/src/main/java/org/springframework/data/rest/example/jpa/Person.java index 5c1972b4f..cdb6bc64e 100644 --- a/spring-data-rest-example/src/main/java/org/springframework/data/rest/example/jpa/Person.java +++ b/spring-data-rest-example/src/main/java/org/springframework/data/rest/example/jpa/Person.java @@ -29,6 +29,7 @@ public class Person { @Description("A person's first name") private String firstName; @Description("A person's last name") + @NotNull private String lastName; @Description("A person's siblings") private List siblings = Collections.emptyList(); @@ -65,7 +66,6 @@ public class Person { return lastName; } - @NotNull public void setLastName(String lastName) { this.lastName = lastName; } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/AbstractRepositoryRestController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/AbstractRepositoryRestController.java index 8b01146c8..d9e422844 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/AbstractRepositoryRestController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/AbstractRepositoryRestController.java @@ -9,7 +9,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; -import javax.validation.ConstraintViolationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,9 +30,9 @@ import org.springframework.data.rest.repository.RepositoryConstraintViolationExc import org.springframework.data.rest.repository.invoke.MethodParameterConversionService; import org.springframework.data.rest.repository.support.ResourceMappingUtils; import org.springframework.data.rest.webmvc.support.BaseUriLinkBuilder; -import org.springframework.data.rest.webmvc.support.ConstraintViolationExceptionMessage; import org.springframework.data.rest.webmvc.support.ExceptionMessage; import org.springframework.data.rest.webmvc.support.RepositoryConstraintViolationExceptionMessage; +import org.springframework.data.rest.webmvc.support.ValidationExceptionHandler; import org.springframework.hateoas.EntityLinks; import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkBuilder; @@ -137,14 +136,21 @@ public class AbstractRepositoryRestController implements ApplicationContextAware } @ExceptionHandler({ - ConstraintViolationException.class + RuntimeException.class }) @ResponseBody - public ResponseEntity handleConstraintViolationException(Locale locale, - ConstraintViolationException cve) { - return response(null, - new ConstraintViolationExceptionMessage(cve, applicationContext, locale), - HttpStatus.BAD_REQUEST); + public ResponseEntity maybeHandleValidationException(Locale locale, + RuntimeException ex) { + ValidationExceptionHandler handler = applicationContext.getBean(ValidationExceptionHandler.class); + if(null != handler) { + return handler.handleValidationException(ex, + applicationContext, + locale); + } else { + return response(null, + ex, + HttpStatus.BAD_REQUEST); + } } @ExceptionHandler({ diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java index 427ae3f29..9005a4663 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; +import org.springframework.context.annotation.Lazy; import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.data.repository.support.DomainClassConverter; import org.springframework.data.rest.config.RepositoryRestConfiguration; @@ -37,12 +38,14 @@ import org.springframework.data.rest.webmvc.RepositorySearchController; import org.springframework.data.rest.webmvc.ServerHttpRequestMethodArgumentResolver; import org.springframework.data.rest.webmvc.convert.UriListHttpMessageConverter; import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks; +import org.springframework.data.rest.webmvc.support.ValidationExceptionHandler; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.hateoas.EntityLinks; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor; +import org.springframework.util.ClassUtils; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; @@ -61,6 +64,11 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl @ImportResource("classpath*:META-INF/spring-data-rest/**/*.xml") public class RepositoryRestMvcConfiguration { + private static final boolean IS_JAVAX_VALIDATION_AVAILABLE = ClassUtils.isPresent( + "javax.validation.ConstraintViolationException", + RepositoryRestMvcConfiguration.class.getClassLoader() + ); + @Bean public RepositoriesFactoryBean repositories() { return new RepositoriesFactoryBean(); } @@ -91,6 +99,14 @@ public class RepositoryRestMvcConfiguration { return listener; } + @Bean @Lazy public ValidationExceptionHandler validationExceptionHandler() { + if(IS_JAVAX_VALIDATION_AVAILABLE) { + return new ValidationExceptionHandler(); + } else { + return null; + } + } + /** * Main configuration for the REST exporter. */ diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ValidationExceptionHandler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ValidationExceptionHandler.java new file mode 100644 index 000000000..7b8066cdf --- /dev/null +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ValidationExceptionHandler.java @@ -0,0 +1,29 @@ +package org.springframework.data.rest.webmvc.support; + +import java.util.Locale; +import javax.validation.ConstraintViolationException; + +import org.springframework.context.MessageSource; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.util.Assert; + +/** + * @author Jon Brisbin + */ +public class ValidationExceptionHandler { + + public ResponseEntity handleValidationException(RuntimeException ex, + MessageSource msgsrc, + Locale locale) { + Assert.isAssignable(ConstraintViolationException.class, ex.getClass()); + return new ResponseEntity( + new ConstraintViolationExceptionMessage((ConstraintViolationException)ex, + msgsrc, + locale), + HttpStatus.BAD_REQUEST + + ); + } + +}