Fixing a bug with property reference deletion.

This commit is contained in:
Jon Brisbin
2013-04-03 00:09:54 +02:00
parent 8fcf5681ab
commit 2d3ebe50ec
5 changed files with 92 additions and 48 deletions

View File

@@ -165,26 +165,26 @@ public class AbstractRepositoryRestController implements ApplicationContextAware
return badRequest(t);
}
@ExceptionHandler({
RuntimeException.class
})
@ResponseBody
public ResponseEntity maybeHandleValidationException(Locale locale,
RuntimeException ex) {
if(ResourceNotFoundException.class.isAssignableFrom(ex.getClass())) {
return handleNotFound();
}
if(null != handler) {
return handler.handleValidationException(ex,
applicationContext,
locale);
} else {
return response(null,
ex,
HttpStatus.BAD_REQUEST);
}
}
// @ExceptionHandler({
// RuntimeException.class
// })
// @ResponseBody
// public ResponseEntity maybeHandleValidationException(Locale locale,
// RuntimeException ex) {
// if(ResourceNotFoundException.class.isAssignableFrom(ex.getClass())) {
// return handleNotFound();
// }
//
// if(null != handler) {
// return handler.handleValidationException(ex,
// applicationContext,
// locale);
// } else {
// return response(null,
// ex,
// HttpStatus.BAD_REQUEST);
// }
// }
@ExceptionHandler({
RepositoryConstraintViolationException.class
@@ -230,14 +230,6 @@ public class AbstractRepositoryRestController implements ApplicationContextAware
return errorResponse(headers, throwable, HttpStatus.BAD_REQUEST);
}
public <T extends Throwable> ResponseEntity<ExceptionMessage> internalServerError(T throwable) {
return internalServerError(null, throwable);
}
public <T extends Throwable> ResponseEntity<ExceptionMessage> internalServerError(HttpHeaders headers, T throwable) {
return errorResponse(headers, throwable, HttpStatus.INTERNAL_SERVER_ERROR);
}
public <T extends Throwable> ResponseEntity<ExceptionMessage> errorResponse(T throwable,
HttpStatus status) {
return errorResponse(null, throwable, status);
@@ -246,8 +238,12 @@ public class AbstractRepositoryRestController implements ApplicationContextAware
public <T extends Throwable> ResponseEntity<ExceptionMessage> errorResponse(HttpHeaders headers,
T throwable,
HttpStatus status) {
LOG.error(throwable.getMessage(), throwable);
return response(headers, new ExceptionMessage(throwable), status);
if(null != throwable && null != throwable.getMessage()) {
LOG.error(throwable.getMessage(), throwable);
return response(headers, new ExceptionMessage(throwable), status);
} else {
return response(headers, null, status);
}
}
public <T> ResponseEntity<T> response(HttpHeaders headers, T body, HttpStatus status) {

View File

@@ -41,6 +41,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -315,11 +316,15 @@ public class RepositoryEntityController extends AbstractRepositoryRestController
@ResponseBody
public ResponseEntity<?> deleteEntity(final RepositoryRestRequest repoRequest,
@PathVariable final String id)
throws ResourceNotFoundException {
throws ResourceNotFoundException, HttpRequestMethodNotSupportedException {
final RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(null == repoMethodInvoker || (!repoMethodInvoker.hasFindOne()
&& !(repoMethodInvoker.hasDeleteOne() || repoMethodInvoker.hasDeleteOneById()))) {
throw new NoSuchMethodError();
throw new HttpRequestMethodNotSupportedException("DELETE");
}
ResourceMapping methodMapping = repoRequest.getRepositoryResourceMapping().getResourceMappingFor("delete");
if(null != methodMapping && !methodMapping.isExported()) {
throw new HttpRequestMethodNotSupportedException("DELETE");
}
final Object domainObj = domainClassConverter.convert(id,

View File

@@ -34,6 +34,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -75,6 +76,9 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
final HttpHeaders headers = new HttpHeaders();
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(null == prop.propertyValue) {
throw new ResourceNotFoundException();
}
if(prop.property.isCollectionLike()) {
List<Resource<?>> resources = new ArrayList<Resource<?>>();
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
@@ -127,6 +131,53 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
return resourceResponse(headers, responseResource, HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.DELETE
)
@ResponseBody
public ResponseEntity<Resource<?>> deletePropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException, HttpRequestMethodNotSupportedException {
final RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(!repoMethodInvoker.hasDeleteOne()) {
throw new NoSuchMethodException();
}
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(null == prop.propertyValue) {
return null;
}
if(prop.property.isCollectionLike()) {
throw new IllegalArgumentException(new HttpRequestMethodNotSupportedException("DELETE"));
} else if(prop.property.isMap()) {
throw new IllegalArgumentException(new HttpRequestMethodNotSupportedException("DELETE"));
} else {
prop.wrapper.setProperty(prop.property, null);
}
applicationContext.publishEvent(new BeforeLinkDeleteEvent(prop.wrapper.getBean(), prop.propertyValue));
Object result = repoMethodInvoker.save(prop.wrapper.getBean());
applicationContext.publishEvent(new AfterLinkDeleteEvent(result, prop.propertyValue));
return null;
}
};
try {
doWithReferencedProperty(repoRequest,
id,
property,
handler);
} catch(IllegalArgumentException iae) {
if(iae.getCause() instanceof HttpRequestMethodNotSupportedException) {
throw (HttpRequestMethodNotSupportedException)iae.getCause();
}
}
return resourceResponse(null, EMPTY_RESOURCE, HttpStatus.NO_CONTENT);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
@@ -147,6 +198,9 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
final HttpHeaders headers = new HttpHeaders();
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(null == prop.propertyValue) {
throw new ResourceNotFoundException();
}
if(prop.property.isCollectionLike()) {
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Object obj : ((Iterable)prop.propertyValue)) {
@@ -324,10 +378,10 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
method = RequestMethod.DELETE
)
@ResponseBody
public ResponseEntity<Resource<?>> deletePropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
public ResponseEntity<Resource<?>> deletePropertyReferenceId(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
final RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(!repoMethodInvoker.hasDeleteOne()) {
@@ -419,9 +473,6 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
BeanWrapper wrapper = BeanWrapper.create(domainObj, conversionService);
Object propVal = wrapper.getProperty(prop);
if(null == propVal) {
throw new ResourceNotFoundException();
}
return handler.apply(new ReferencedProperty(prop,
propVal,

View File

@@ -70,14 +70,6 @@ public class RepositoryRestHandlerMapping extends RequestMappingHandlerMapping {
HttpServletRequest request = new DefaultAcceptTypeHttpServletRequest(origRequest, acceptType);
if(acceptType.contains("javascript")) {
if(null != request.getParameter(config.getJsonpParamName())
|| null != request.getParameter(config.getJsonpOnErrParamName())) {
return super.lookupHandlerMethod(lookupPath, request);
} else {
return null;
}
}
String requestUri = lookupPath;
if(requestUri.startsWith("/")) {
requestUri = requestUri.substring(1);

View File

@@ -5,7 +5,7 @@ package org.springframework.data.rest.webmvc;
*
* @author Jon Brisbin
*/
public class ResourceNotFoundException extends Exception {
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException() {
super("Resource not found");
}