diff --git a/doc/validation.md b/doc/validation.md
new file mode 100644
index 000000000..555b87d36
--- /dev/null
+++ b/doc/validation.md
@@ -0,0 +1,41 @@
+# Validation in Spring Data REST
+
+Integrating validation with the Spring Data REST Exporter is as easy as simply defining an instance of a [Validator](http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/validation/Validator.html). There is an ApplicationListener that that looks for these Validator instances on startup and wires them to the correct RepositoryEvent based on the bean name.
+
+For example, to validate entities before they are saved to the Repository, you only need to define a Validator instance in your ApplicationContext with a name that starts with "beforeSave".
+
+
+
+
+All the events dicussed in [Handling ApplicationEvents in the REST Exporter](wiki/Handling-ApplicationEvents-in-the-REST-Exporter) can be validated.
+
+If any errors are found during validation, a [RepositoryConstraintViolationException](blob/master/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/RepositoryConstraintViolationException.java) will be thrown, resulting in a 400 Bad Request.
+
+### Advanced Configuration
+
+If you need a little more control over how the Validators are wired, you can instantiate a [ValidatingRepositoryEventListener](blob/master/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java) yourself and use a Map of Validators to their event names:
+
+
+
+
+
+
diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java
index 965c31f39..05005f3c9 100644
--- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java
+++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java
@@ -7,6 +7,7 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.rest.repository.RepositoryConstraintViolationException;
import org.springframework.data.rest.repository.ValidationErrors;
@@ -30,18 +31,20 @@ public class ValidatingRepositoryEventListener
@Override public void afterPropertiesSet() throws Exception {
if (validators.size() == 0) {
- Map validators = applicationContext.getBeansOfType(Validator.class);
- for (Map.Entry entry : validators.entrySet()) {
- String name = entry.getKey();
+ for (Map.Entry entry : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,
+ Validator.class)
+ .entrySet()) {
+ String name = null;
Validator v = entry.getValue();
- if (name.contains("Save")) {
- name = name.substring(0, name.indexOf("Save") + 4);
- } else if (name.contains("Delete")) {
- name = name.substring(0, name.indexOf("Delete") + 6);
+ if (entry.getKey().contains("Save")) {
+ name = entry.getKey().substring(0, name.indexOf("Save") + 4);
+ } else if (entry.getKey().contains("Delete")) {
+ name = entry.getKey().substring(0, name.indexOf("Delete") + 6);
+ }
+ if (null != name) {
+ this.validators.put(name, v);
}
-
- this.validators.put(name, v);
}
}
}
diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java
index a94a53956..b1f3bc7e8 100644
--- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java
+++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java
@@ -53,7 +53,6 @@ import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.server.ServerHttpRequest;
@@ -68,7 +67,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.util.UriComponentsBuilder;
@@ -251,7 +249,7 @@ public class RepositoryRestController
RepositoryMetadata repoMeta = repositoryMetadataFor(repository);
Links links = new Links();
- Iterator iter = ((CrudRepository) repoMeta.repository()).findAll().iterator();
+ Iterator iter = repoMeta.repository().findAll().iterator();
while (iter.hasNext()) {
Object o = iter.next();
Serializable id = (Serializable) repoMeta.entityMetadata().idAttribute().get(o);
@@ -396,7 +394,7 @@ public class RepositoryRestController
URI baseUri = uriBuilder.build().toUri();
RepositoryMetadata repoMeta = repositoryMetadataFor(repository);
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
MediaType incomingMediaType = request.getHeaders().getContentType();
final Object incoming = readIncoming(request, incomingMediaType, repoMeta.entityMetadata().type());
if (null == incoming) {
@@ -441,7 +439,7 @@ public class RepositoryRestController
(Class extends Serializable>) repoMeta.entityMetadata()
.idAttribute()
.type());
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
Object entity = repo.findOne(serId);
if (null == entity) {
model.addAttribute(STATUS, HttpStatus.NOT_FOUND);
@@ -500,7 +498,7 @@ public class RepositoryRestController
(Class extends Serializable>) repoMeta.entityMetadata()
.idAttribute()
.type());
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
Object entity = null;
Class> domainType = repoMeta.entityMetadata().type();
switch (request.getMethod()) {
@@ -561,7 +559,7 @@ public class RepositoryRestController
(Class extends Serializable>) repoMeta.entityMetadata()
.idAttribute()
.type());
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
if (null != eventPublisher) {
eventPublisher.publishEvent(new BeforeDeleteEvent(serId));
@@ -596,7 +594,7 @@ public class RepositoryRestController
(Class extends Serializable>) repoMeta.entityMetadata()
.idAttribute()
.type());
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
Object entity = repo.findOne(serId);
if (null == entity) {
model.addAttribute(STATUS, HttpStatus.NOT_FOUND);
@@ -680,7 +678,7 @@ public class RepositoryRestController
(Class extends Serializable>) repoMeta.entityMetadata()
.idAttribute()
.type());
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
final Object entity = repo.findOne(serId);
if (null == entity) {
model.addAttribute(STATUS, HttpStatus.NOT_FOUND);
@@ -790,7 +788,7 @@ public class RepositoryRestController
(Class extends Serializable>) repoMeta.entityMetadata()
.idAttribute()
.type());
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
final Object entity = repo.findOne(serId);
if (null == entity) {
model.addAttribute(STATUS, HttpStatus.NOT_FOUND);
@@ -838,7 +836,7 @@ public class RepositoryRestController
(Class extends Serializable>) repoMeta.entityMetadata()
.idAttribute()
.type());
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
final Object entity = repo.findOne(serId);
if (null != entity) {
AttributeMetadata attrMeta = repoMeta.entityMetadata().attribute(property);
@@ -891,7 +889,7 @@ public class RepositoryRestController
(Class extends Serializable>) repoMeta.entityMetadata()
.idAttribute()
.type());
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
final Object entity = repo.findOne(serId);
if (null == entity) {
model.addAttribute(STATUS, HttpStatus.NOT_FOUND);
@@ -901,7 +899,7 @@ public class RepositoryRestController
// Find linked entity
RepositoryMetadata linkedRepoMeta = repositoryMetadataFor(attrMeta);
if (null != linkedRepoMeta) {
- CrudRepository linkedRepo = (CrudRepository) linkedRepoMeta.repository();
+ CrudRepository linkedRepo = linkedRepoMeta.repository();
Serializable sChildId = stringToSerializable(linkedId,
(Class extends Serializable>) linkedRepoMeta.entityMetadata()
.idAttribute()
@@ -950,13 +948,15 @@ public class RepositoryRestController
@SuppressWarnings({"unchecked"})
@ExceptionHandler(OptimisticLockingFailureException.class)
- @ResponseBody
- public ResponseEntity handleLockingFailure(OptimisticLockingFailureException ex) throws IOException {
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_JSON);
+ public Model handleLockingFailure(OptimisticLockingFailureException ex) throws IOException {
+ Model model = new ExtendedModelMap();
+ model.addAttribute(STATUS, HttpStatus.CONFLICT);
+
Map m = new HashMap();
m.put("message", ex.getMessage());
- return new ResponseEntity(objectMapper.writeValueAsBytes(m), headers, HttpStatus.CONFLICT);
+
+ model.addAttribute(RESOURCE, m);
+ return model;
}
@SuppressWarnings({"unchecked"})
@@ -1013,7 +1013,7 @@ public class RepositoryRestController
String sId = UriUtils.path(uris.get(1));
RepositoryMetadata repoMeta = repositoryMetadataFor(repoName);
- CrudRepository repo = (CrudRepository) repoMeta.repository();
+ CrudRepository repo = repoMeta.repository();
if (null == repo) {
return null;
}
@@ -1057,18 +1057,14 @@ public class RepositoryRestController
}
}
+ List links = (List) entityDto.get(LINKS);
+ if (null == links) {
+ links = new ArrayList();
+ entityDto.put(LINKS, links);
+ }
for (String attrName : entityMetadata.linkedAttributes().keySet()) {
- URI uri = UriComponentsBuilder.fromUri(baseUri)
- .pathSegment(attrName)
- .build()
- .toUri();
- Link l = new SimpleLink(repoRel + "." + entity.getClass().getSimpleName() + "." + attrName, uri);
- List links = (List) entityDto.get(LINKS);
- if (null == links) {
- links = new ArrayList();
- entityDto.put(LINKS, links);
- }
- links.add(l);
+ links.add(new SimpleLink(repoRel + "." + entity.getClass().getSimpleName() + "." + attrName,
+ buildUri(baseUri, attrName)));
}
return entityDto;