Fix for DATAREST-69. Now inject an EntityLinks into the controller and provide the RepositoryEntityLinks as a bean in the RepositoryRestMvcConfiguration.

This commit is contained in:
Jon Brisbin
2013-03-05 08:59:13 -06:00
parent 9ac79514b7
commit 9e47346314
8 changed files with 924 additions and 932 deletions

View File

@@ -22,14 +22,11 @@ import org.springframework.web.util.UriComponentsBuilder;
*/
public class RepositoryEntityLinks extends AbstractEntityLinks {
private final URI baseUri;
private final Repositories repositories;
private final RepositoryRestConfiguration config;
public RepositoryEntityLinks(URI baseUri,
Repositories repositories,
public RepositoryEntityLinks(Repositories repositories,
RepositoryRestConfiguration config) {
this.baseUri = baseUri;
this.repositories = repositories;
this.config = config;
}
@@ -48,7 +45,7 @@ public class RepositoryEntityLinks extends AbstractEntityLinks {
if(null == persistentEntity) {
throw new IllegalArgumentException(type + " is not managed by any repository.");
}
return new PersistentEntityLinkBuilder(baseUri, repoInfo, persistentEntity);
return new PersistentEntityLinkBuilder(config.getBaseUri(), repoInfo, persistentEntity);
}
@Override public LinkBuilder linkFor(Class<?> type, Object... parameters) {

View File

@@ -34,6 +34,7 @@ import org.springframework.data.rest.webmvc.support.ConstraintViolationException
import org.springframework.data.rest.webmvc.support.ExceptionMessage;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.data.rest.webmvc.support.RepositoryConstraintViolationExceptionMessage;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.LinkBuilder;
import org.springframework.hateoas.Resource;
@@ -52,236 +53,239 @@ import org.springframework.web.bind.annotation.ResponseBody;
*/
public class AbstractRepositoryRestController implements ApplicationContextAware {
static final Resource<?> EMPTY_RESOURCE = new Resource<Object>(Collections.emptyList());
static final Resources<Resource<?>> EMPTY_RESOURCES = new Resources<Resource<?>>(Collections.<Resource<?>>emptyList());
static final Iterable<Resource<?>> EMPTY_RESOURCE_LIST = Collections.emptyList();
static final TypeDescriptor STRING_TYPE = TypeDescriptor.valueOf(String.class);
protected final Logger LOG = LoggerFactory.getLogger(getClass());
protected final Repositories repositories;
protected final RepositoryRestConfiguration config;
protected final DomainClassConverter domainClassConverter;
protected final ConversionService conversionService;
protected final MethodParameterConversionService methodParameterConversionService;
protected ApplicationContext applicationContext;
static final Resource<?> EMPTY_RESOURCE = new Resource<Object>(Collections.emptyList());
static final Resources<Resource<?>> EMPTY_RESOURCES = new Resources<Resource<?>>(Collections.<Resource<?>>emptyList());
static final Iterable<Resource<?>> EMPTY_RESOURCE_LIST = Collections.emptyList();
static final TypeDescriptor STRING_TYPE = TypeDescriptor.valueOf(String.class);
protected final Logger LOG = LoggerFactory.getLogger(getClass());
protected final Repositories repositories;
protected final RepositoryRestConfiguration config;
protected final DomainClassConverter domainClassConverter;
protected final ConversionService conversionService;
protected final MethodParameterConversionService methodParameterConversionService;
protected final EntityLinks entityLinks;
protected ApplicationContext applicationContext;
@Autowired
public AbstractRepositoryRestController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService) {
this.repositories = repositories;
this.config = config;
this.domainClassConverter = domainClassConverter;
this.conversionService = conversionService;
this.methodParameterConversionService = new MethodParameterConversionService(conversionService);
}
@Autowired
public AbstractRepositoryRestController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService,
EntityLinks entityLinks) {
this.repositories = repositories;
this.config = config;
this.domainClassConverter = domainClassConverter;
this.conversionService = conversionService;
this.entityLinks = entityLinks;
this.methodParameterConversionService = new MethodParameterConversionService(conversionService);
}
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@ExceptionHandler({
NullPointerException.class
})
@ResponseBody
public ResponseEntity<?> handleNPE(NullPointerException npe) {
return errorResponse(npe, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler({
NullPointerException.class
})
@ResponseBody
public ResponseEntity<?> handleNPE(NullPointerException npe) {
return errorResponse(npe, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler({
ResourceNotFoundException.class
})
@ResponseBody
public ResponseEntity<?> handleNotFound() {
return notFound();
}
@ExceptionHandler({
ResourceNotFoundException.class
})
@ResponseBody
public ResponseEntity<?> handleNotFound() {
return notFound();
}
@ExceptionHandler({
NoSuchMethodError.class,
HttpRequestMethodNotSupportedException.class
})
@ResponseBody
public ResponseEntity<?> handleNoSuchMethod() {
return errorResponse(null, HttpStatus.METHOD_NOT_ALLOWED);
}
@ExceptionHandler({
NoSuchMethodError.class,
HttpRequestMethodNotSupportedException.class
})
@ResponseBody
public ResponseEntity<?> handleNoSuchMethod() {
return errorResponse(null, HttpStatus.METHOD_NOT_ALLOWED);
}
@ExceptionHandler({
HttpMessageNotReadableException.class,
HttpMessageNotWritableException.class
})
@ResponseBody
public ResponseEntity<ExceptionMessage> handleNotReadable(HttpMessageNotReadableException e) {
return badRequest(e);
}
@ExceptionHandler({
HttpMessageNotReadableException.class,
HttpMessageNotWritableException.class
})
@ResponseBody
public ResponseEntity<ExceptionMessage> handleNotReadable(HttpMessageNotReadableException e) {
return badRequest(e);
}
/**
* Handle failures commonly thrown from code tries to read incoming data and convert or cast it to the right type.
*
* @param t
*
* @return
*
* @throws java.io.IOException
*/
@ExceptionHandler({
InvocationTargetException.class,
IllegalArgumentException.class,
ClassCastException.class,
ConversionFailedException.class
})
@ResponseBody
public ResponseEntity<ExceptionMessage> handleMiscFailures(Throwable t) {
return badRequest(t);
}
/**
* Handle failures commonly thrown from code tries to read incoming data and convert or cast it to the right type.
*
* @param t
*
* @return
*
* @throws java.io.IOException
*/
@ExceptionHandler({
InvocationTargetException.class,
IllegalArgumentException.class,
ClassCastException.class,
ConversionFailedException.class
})
@ResponseBody
public ResponseEntity<ExceptionMessage> handleMiscFailures(Throwable t) {
return badRequest(t);
}
@ExceptionHandler({
ConstraintViolationException.class
})
@ResponseBody
public ResponseEntity handleConstraintViolationException(ConstraintViolationException cve) {
return response(null,
new ConstraintViolationExceptionMessage(cve, applicationContext),
HttpStatus.CONFLICT);
}
@ExceptionHandler({
ConstraintViolationException.class
})
@ResponseBody
public ResponseEntity handleConstraintViolationException(ConstraintViolationException cve) {
return response(null,
new ConstraintViolationExceptionMessage(cve, applicationContext),
HttpStatus.CONFLICT);
}
@ExceptionHandler({
RepositoryConstraintViolationException.class
})
@ResponseBody
public ResponseEntity handleRepositoryConstraintViolationException(RepositoryConstraintViolationException rcve) {
return response(null,
new RepositoryConstraintViolationExceptionMessage(rcve, applicationContext),
HttpStatus.CONFLICT);
}
@ExceptionHandler({
RepositoryConstraintViolationException.class
})
@ResponseBody
public ResponseEntity handleRepositoryConstraintViolationException(RepositoryConstraintViolationException rcve) {
return response(null,
new RepositoryConstraintViolationExceptionMessage(rcve, applicationContext),
HttpStatus.CONFLICT);
}
/**
* Send a 409 Conflict in case of concurrent modification.
*
* @param ex
*
* @return
*/
@SuppressWarnings({"unchecked"})
@ExceptionHandler({
OptimisticLockingFailureException.class,
DataIntegrityViolationException.class
})
@ResponseBody
public ResponseEntity handleConflict(Exception ex) {
return errorResponse(null, ex, HttpStatus.CONFLICT);
}
/**
* Send a 409 Conflict in case of concurrent modification.
*
* @param ex
*
* @return
*/
@SuppressWarnings({"unchecked"})
@ExceptionHandler({
OptimisticLockingFailureException.class,
DataIntegrityViolationException.class
})
@ResponseBody
public ResponseEntity handleConflict(Exception ex) {
return errorResponse(null, ex, HttpStatus.CONFLICT);
}
protected <T> ResponseEntity<T> notFound() {
return notFound(null, null);
}
protected <T> ResponseEntity<T> notFound() {
return notFound(null, null);
}
protected <T> ResponseEntity<T> notFound(HttpHeaders headers, T body) {
return response(headers, body, HttpStatus.NOT_FOUND);
}
protected <T> ResponseEntity<T> notFound(HttpHeaders headers, T body) {
return response(headers, body, HttpStatus.NOT_FOUND);
}
protected <T extends Throwable> ResponseEntity<ExceptionMessage> badRequest(T throwable) {
return badRequest(null, throwable);
}
protected <T extends Throwable> ResponseEntity<ExceptionMessage> badRequest(T throwable) {
return badRequest(null, throwable);
}
protected <T extends Throwable> ResponseEntity<ExceptionMessage> badRequest(HttpHeaders headers, T throwable) {
return errorResponse(headers, throwable, HttpStatus.BAD_REQUEST);
}
protected <T extends Throwable> ResponseEntity<ExceptionMessage> badRequest(HttpHeaders headers, T throwable) {
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(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> 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);
}
public <T extends Throwable> ResponseEntity<ExceptionMessage> errorResponse(T throwable,
HttpStatus status) {
return errorResponse(null, throwable, status);
}
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);
}
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);
}
public <T> ResponseEntity<T> response(HttpHeaders headers, T body, HttpStatus status) {
HttpHeaders hdrs = new HttpHeaders();
if(null != headers) {
hdrs.putAll(headers);
}
return new ResponseEntity<T>(body, hdrs, status);
}
public <T> ResponseEntity<T> response(HttpHeaders headers, T body, HttpStatus status) {
HttpHeaders hdrs = new HttpHeaders();
if(null != headers) {
hdrs.putAll(headers);
}
return new ResponseEntity<T>(body, hdrs, status);
}
public <R extends Resource<?>> ResponseEntity<Resource<?>> resourceResponse(HttpHeaders headers,
R resource,
HttpStatus status) {
HttpHeaders hdrs = new HttpHeaders();
if(null != headers) {
hdrs.putAll(headers);
}
return new ResponseEntity<Resource<?>>(resource, hdrs, status);
}
public <R extends Resource<?>> ResponseEntity<Resource<?>> resourceResponse(HttpHeaders headers,
R resource,
HttpStatus status) {
HttpHeaders hdrs = new HttpHeaders();
if(null != headers) {
hdrs.putAll(headers);
}
return new ResponseEntity<Resource<?>>(resource, hdrs, status);
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
T response,
HttpStatus status) {
return jsonpWrapResponse(repoRequest, response, null, status);
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
T response,
HttpStatus status) {
return jsonpWrapResponse(repoRequest, response, null, status);
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
ResponseEntity<T> response) {
return jsonpWrapResponse(repoRequest,
response.getBody(),
response.getHeaders(),
response.getStatusCode());
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
ResponseEntity<T> response) {
return jsonpWrapResponse(repoRequest,
response.getBody(),
response.getHeaders(),
response.getStatusCode());
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
T response,
HttpHeaders headers,
HttpStatus status) {
String callback = repoRequest.getRequest().getParameter(config.getJsonpParamName());
String errback = (null != config.getJsonpOnErrParamName()
? repoRequest.getRequest().getParameter(config.getJsonpOnErrParamName())
: null);
ResponseEntity<T> newResponse;
if(null != headers) {
newResponse = new ResponseEntity<T>(response, headers, status);
} else {
newResponse = new ResponseEntity<T>(response, status);
}
return new JsonpResponse<T>(newResponse,
(null != callback ? callback : config.getJsonpParamName()),
(null != errback ? errback : config.getJsonpOnErrParamName()));
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
T response,
HttpHeaders headers,
HttpStatus status) {
String callback = repoRequest.getRequest().getParameter(config.getJsonpParamName());
String errback = (null != config.getJsonpOnErrParamName()
? repoRequest.getRequest().getParameter(config.getJsonpOnErrParamName())
: null);
ResponseEntity<T> newResponse;
if(null != headers) {
newResponse = new ResponseEntity<T>(response, headers, status);
} else {
newResponse = new ResponseEntity<T>(response, status);
}
return new JsonpResponse<T>(newResponse,
(null != callback ? callback : config.getJsonpParamName()),
(null != errback ? errback : config.getJsonpOnErrParamName()));
}
protected List<Link> queryMethodLinks(URI baseUri, Class<?> domainType) {
List<Link> links = new ArrayList<Link>();
RepositoryInformation repoInfo = repositories.getRepositoryInformationFor(domainType);
ResourceMapping repoMapping = ResourceMappingUtils.merge(
repoInfo.getRepositoryInterface(),
config.getResourceMappingForRepository(repoInfo.getRepositoryInterface())
);
for(Method method : repoInfo.getQueryMethods()) {
LinkBuilder linkBuilder = BaseUriLinkBuilder.create(buildUri(baseUri, repoMapping.getPath(), "search"));
ResourceMapping methodMapping = ResourceMappingUtils.merge(method,
repoMapping.getResourceMappingFor(method.getName()));
links.add(linkBuilder.slash(methodMapping.getPath())
.withRel(repoMapping.getRel() + "." + methodMapping.getRel()));
}
return links;
}
protected List<Link> queryMethodLinks(URI baseUri, Class<?> domainType) {
List<Link> links = new ArrayList<Link>();
RepositoryInformation repoInfo = repositories.getRepositoryInformationFor(domainType);
ResourceMapping repoMapping = ResourceMappingUtils.merge(
repoInfo.getRepositoryInterface(),
config.getResourceMappingForRepository(repoInfo.getRepositoryInterface())
);
for(Method method : repoInfo.getQueryMethods()) {
LinkBuilder linkBuilder = BaseUriLinkBuilder.create(buildUri(baseUri, repoMapping.getPath(), "search"));
ResourceMapping methodMapping = ResourceMappingUtils.merge(method,
repoMapping.getResourceMappingFor(method.getName()));
links.add(linkBuilder.slash(methodMapping.getPath())
.withRel(repoMapping.getRel() + "." + methodMapping.getRel()));
}
return links;
}
protected Link resourceLink(RepositoryRestRequest repoRequest, Resource resource) {
ResourceMapping repoMapping = repoRequest.getRepositoryResourceMapping();
ResourceMapping entityMapping = repoRequest.getPersistentEntityResourceMapping();
protected Link resourceLink(RepositoryRestRequest repoRequest, Resource resource) {
ResourceMapping repoMapping = repoRequest.getRepositoryResourceMapping();
ResourceMapping entityMapping = repoRequest.getPersistentEntityResourceMapping();
Link selfLink = resource.getLink("self");
String rel = repoMapping.getRel() + "." + entityMapping.getRel();
return new Link(selfLink.getHref(), rel);
}
Link selfLink = resource.getLink("self");
String rel = repoMapping.getRel() + "." + entityMapping.getRel();
return new Link(selfLink.getHref(), rel);
}
}

View File

@@ -2,11 +2,11 @@ package org.springframework.data.rest.webmvc;
import static java.util.Collections.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.repository.support.DomainClassConverter;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.config.RepositoryRestConfiguration;
import org.springframework.data.rest.repository.support.RepositoryEntityLinks;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Resource;
@@ -23,43 +23,46 @@ import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("/")
public class RepositoryController extends AbstractRepositoryRestController {
public RepositoryController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService) {
super(repositories, config, domainClassConverter, conversionService);
}
@Autowired
public RepositoryController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService,
EntityLinks entityLinks) {
super(repositories,
config,
domainClassConverter,
conversionService,
entityLinks);
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-compact+json"
}
)
@ResponseBody
public Resource<?> listRepositories(RepositoryRestRequest repoRequest)
throws ResourceNotFoundException {
EntityLinks linkBuilder = new RepositoryEntityLinks(repoRequest.getBaseUri(),
repositories,
config);
Resource<?> links = new Resource<Object>(emptyList());
for(Class<?> domainType : repositories) {
links.add(linkBuilder.linkToCollectionResource(domainType));
}
return links;
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-compact+json"
}
)
@ResponseBody
public Resource<?> listRepositories()
throws ResourceNotFoundException {
Resource<?> links = new Resource<Object>(emptyList());
for(Class<?> domainType : repositories) {
links.add(entityLinks.linkToCollectionResource(domainType));
}
return links;
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpListRepositories(RepositoryRestRequest repoRequest)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, listRepositories(repoRequest), HttpStatus.OK);
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpListRepositories(RepositoryRestRequest repoRequest)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, listRepositories(), HttpStatus.OK);
}
}

View File

@@ -27,6 +27,7 @@ import org.springframework.data.rest.repository.json.JsonSchema;
import org.springframework.data.rest.repository.json.PersistentEntityToJsonSchemaConverter;
import org.springframework.data.rest.repository.support.DomainObjectMerger;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
import org.springframework.hateoas.Resources;
@@ -54,8 +55,13 @@ public class RepositoryEntityController extends AbstractRepositoryRestController
public RepositoryEntityController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService) {
super(repositories, config, domainClassConverter, conversionService);
ConversionService conversionService,
EntityLinks entityLinks) {
super(repositories,
config,
domainClassConverter,
conversionService,
entityLinks);
}
@RequestMapping(

View File

@@ -1,42 +0,0 @@
package org.springframework.data.rest.webmvc;
import java.net.URI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.data.rest.repository.support.RepositoryEntityLinks;
import org.springframework.data.rest.repository.support.RepositoryInformationSupport;
import org.springframework.hateoas.EntityLinks;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* @author Jon Brisbin
*/
public class RepositoryEntityLinksMethodArgumentResolver
extends RepositoryInformationSupport
implements HandlerMethodArgumentResolver {
@Autowired
private BaseUriMethodArgumentResolver baseUriResolver;
@Override public boolean supportsParameter(MethodParameter parameter) {
return EntityLinks.class.isAssignableFrom(parameter.getParameterType());
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory)
throws Exception {
URI baseUri = (URI)baseUriResolver.resolveArgument(parameter,
mavContainer,
webRequest,
binderFactory);
return new RepositoryEntityLinks(baseUri, repositories, config);
}
}

View File

@@ -28,6 +28,7 @@ import org.springframework.data.rest.repository.context.BeforeLinkDeleteEvent;
import org.springframework.data.rest.repository.context.BeforeLinkSaveEvent;
import org.springframework.data.rest.repository.invoke.RepositoryMethodInvoker;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
import org.springframework.http.HttpHeaders;
@@ -47,485 +48,490 @@ import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("/{repository}/{id}/{property}")
public class RepositoryPropertyReferenceController extends AbstractRepositoryRestController {
public RepositoryPropertyReferenceController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService) {
super(repositories, config, domainClassConverter, conversionService);
}
public RepositoryPropertyReferenceController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService,
EntityLinks entityLinks) {
super(repositories,
config,
domainClassConverter,
conversionService,
entityLinks);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-verbose+json"
}
)
@ResponseBody
public ResponseEntity<Resource<?>> followPropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
final HttpHeaders headers = new HttpHeaders();
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(prop.property.isCollectionLike()) {
List<Resource<?>> resources = new ArrayList<Resource<?>>();
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Object obj : ((Iterable)prop.propertyValue)) {
PersistentEntityResource per = PersistentEntityResource.wrap(entity, obj, repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(obj, conversionService);
per.add(selfLink);
resources.add(per);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-verbose+json"
}
)
@ResponseBody
public ResponseEntity<Resource<?>> followPropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
final HttpHeaders headers = new HttpHeaders();
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(prop.property.isCollectionLike()) {
List<Resource<?>> resources = new ArrayList<Resource<?>>();
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Object obj : ((Iterable)prop.propertyValue)) {
PersistentEntityResource per = PersistentEntityResource.wrap(entity, obj, repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(obj, conversionService);
per.add(selfLink);
resources.add(per);
}
return new Resource<Object>(resources);
} else if(prop.property.isMap()) {
Map<Object, Resource<?>> resources = new HashMap<Object, Resource<?>>();
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Map.Entry<Object, Object> entry : ((Map<Object, Object>)prop.propertyValue).entrySet()) {
PersistentEntityResource per = PersistentEntityResource.wrap(entity,
entry.getValue(),
repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(entry.getValue(), conversionService);
per.add(selfLink);
resources.put(entry.getKey(), per);
}
return new Resource<Object>(resources);
} else if(prop.property.isMap()) {
Map<Object, Resource<?>> resources = new HashMap<Object, Resource<?>>();
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Map.Entry<Object, Object> entry : ((Map<Object, Object>)prop.propertyValue).entrySet()) {
PersistentEntityResource per = PersistentEntityResource.wrap(entity,
entry.getValue(),
repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(entry.getValue(), conversionService);
per.add(selfLink);
resources.put(entry.getKey(), per);
}
return new Resource<Object>(resources);
} else {
PersistentEntityResource per = PersistentEntityResource.wrap(repositories.getPersistentEntity(prop.propertyType),
prop.propertyValue,
repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(prop.propertyValue, conversionService);
per.add(selfLink);
return new Resource<Object>(resources);
} else {
PersistentEntityResource per = PersistentEntityResource.wrap(repositories.getPersistentEntity(prop.propertyType),
prop.propertyValue,
repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(prop.propertyValue, conversionService);
per.add(selfLink);
headers.set("Content-Location", selfLink.getHref());
headers.set("Content-Location", selfLink.getHref());
return new Resource<Object>(per);
}
}
};
Resource<?> responseResource = doWithReferencedProperty(repoRequest,
id,
property,
handler);
return resourceResponse(headers, responseResource, HttpStatus.OK);
}
return new Resource<Object>(per);
}
}
};
Resource<?> responseResource = doWithReferencedProperty(repoRequest,
id,
property,
handler);
return resourceResponse(headers, responseResource, HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-verbose+json",
"application/x-spring-data-compact+json",
"text/uri-list"
}
)
@ResponseBody
public ResponseEntity<Resource<?>> followPropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
final HttpHeaders headers = new HttpHeaders();
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(prop.property.isCollectionLike()) {
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Object obj : ((Iterable)prop.propertyValue)) {
BeanWrapper propValWrapper = BeanWrapper.create(obj, conversionService);
String sId = propValWrapper.getProperty(prop.entity.getIdProperty()).toString();
if(propertyId.equals(sId)) {
PersistentEntityResource per = PersistentEntityResource.wrap(entity, obj, repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(obj, conversionService);
per.add(selfLink);
headers.set("Content-Location", selfLink.getHref());
return per;
}
}
} else if(prop.property.isMap()) {
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Map.Entry<Object, Object> entry : ((Map<Object, Object>)prop.propertyValue).entrySet()) {
BeanWrapper propValWrapper = BeanWrapper.create(entry.getValue(), conversionService);
String sId = propValWrapper.getProperty(prop.entity.getIdProperty()).toString();
if(propertyId.equals(sId)) {
PersistentEntityResource per = PersistentEntityResource.wrap(entity,
entry.getValue(),
repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(entry.getValue(), conversionService);
per.add(selfLink);
headers.set("Content-Location", selfLink.getHref());
return per;
}
}
} else {
return new Resource<Object>(prop.propertyValue);
}
throw new IllegalArgumentException(new ResourceNotFoundException());
}
};
Resource<?> responseResource = doWithReferencedProperty(repoRequest,
id,
property,
handler);
return resourceResponse(headers, responseResource, HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-verbose+json",
"application/x-spring-data-compact+json",
"text/uri-list"
}
)
@ResponseBody
public ResponseEntity<Resource<?>> followPropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
final HttpHeaders headers = new HttpHeaders();
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(prop.property.isCollectionLike()) {
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Object obj : ((Iterable)prop.propertyValue)) {
BeanWrapper propValWrapper = BeanWrapper.create(obj, conversionService);
String sId = propValWrapper.getProperty(prop.entity.getIdProperty()).toString();
if(propertyId.equals(sId)) {
PersistentEntityResource per = PersistentEntityResource.wrap(entity, obj, repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(obj, conversionService);
per.add(selfLink);
headers.set("Content-Location", selfLink.getHref());
return per;
}
}
} else if(prop.property.isMap()) {
PersistentEntity entity = repositories.getPersistentEntity(prop.propertyType);
for(Map.Entry<Object, Object> entry : ((Map<Object, Object>)prop.propertyValue).entrySet()) {
BeanWrapper propValWrapper = BeanWrapper.create(entry.getValue(), conversionService);
String sId = propValWrapper.getProperty(prop.entity.getIdProperty()).toString();
if(propertyId.equals(sId)) {
PersistentEntityResource per = PersistentEntityResource.wrap(entity,
entry.getValue(),
repoRequest.getBaseUri());
Link selfLink = repoRequest.buildEntitySelfLink(entry.getValue(), conversionService);
per.add(selfLink);
headers.set("Content-Location", selfLink.getHref());
return per;
}
}
} else {
return new Resource<Object>(prop.propertyValue);
}
throw new IllegalArgumentException(new ResourceNotFoundException());
}
};
Resource<?> responseResource = doWithReferencedProperty(repoRequest,
id,
property,
handler);
return resourceResponse(headers, responseResource, HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/x-spring-data-compact+json",
"text/uri-list"
}
)
@ResponseBody
public ResponseEntity<Resource<?>> followPropertyReferenceCompact(RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
ResponseEntity<Resource<?>> response = followPropertyReference(repoRequest, id, property);
if(response.getStatusCode() != HttpStatus.OK) {
return response;
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/x-spring-data-compact+json",
"text/uri-list"
}
)
@ResponseBody
public ResponseEntity<Resource<?>> followPropertyReferenceCompact(RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
ResponseEntity<Resource<?>> response = followPropertyReference(repoRequest, id, property);
if(response.getStatusCode() != HttpStatus.OK) {
return response;
}
ResourceMapping repoMapping = repoRequest.getRepositoryResourceMapping();
ResourceMapping entityMapping = repoRequest.getPersistentEntityResourceMapping();
String propName = entityMapping.getNameForPath(property);
ResourceMapping propMapping = entityMapping.getResourceMappingFor(entityMapping.getNameForPath(property));
PersistentProperty persistentProp = repoRequest.getPersistentEntity().getPersistentProperty(propName);
Class<?> propType = (persistentProp.isCollectionLike() || persistentProp.isMap()
? persistentProp.getComponentType()
: persistentProp.getType());
ResourceMapping propRepoMapping = getResourceMapping(config, repositories.getRepositoryInformationFor(propType));
String propRel = String.format("%s.%s.%s.%s",
repoMapping.getRel(),
entityMapping.getRel(),
(null != propMapping ? propMapping.getRel() : property),
propRepoMapping.getRel());
ResourceMapping repoMapping = repoRequest.getRepositoryResourceMapping();
ResourceMapping entityMapping = repoRequest.getPersistentEntityResourceMapping();
String propName = entityMapping.getNameForPath(property);
ResourceMapping propMapping = entityMapping.getResourceMappingFor(entityMapping.getNameForPath(property));
PersistentProperty persistentProp = repoRequest.getPersistentEntity().getPersistentProperty(propName);
Class<?> propType = (persistentProp.isCollectionLike() || persistentProp.isMap()
? persistentProp.getComponentType()
: persistentProp.getType());
ResourceMapping propRepoMapping = getResourceMapping(config, repositories.getRepositoryInformationFor(propType));
String propRel = String.format("%s.%s.%s.%s",
repoMapping.getRel(),
entityMapping.getRel(),
(null != propMapping ? propMapping.getRel() : property),
propRepoMapping.getRel());
Resource<?> resource = response.getBody();
Resource<?> resource = response.getBody();
List<Link> links = new ArrayList<Link>();
List<Link> links = new ArrayList<Link>();
URI entityBaseUri = buildUri(repoRequest.getBaseUri(),
repoMapping.getPath(),
id,
property);
URI entityBaseUri = buildUri(repoRequest.getBaseUri(),
repoMapping.getPath(),
id,
property);
if(resource.getContent() instanceof Iterable) {
for(Resource<?> res : (Iterable<Resource<?>>)resource.getContent()) {
Link propLink = propertyReferenceLink(res, entityBaseUri, propRel);
links.add(propLink);
}
} else if(resource.getContent() instanceof Map) {
for(Map.Entry<Object, Resource<?>> entry : ((Map<Object, Resource<?>>)resource.getContent()).entrySet()) {
Link l = new Link(entry.getValue().getLink("self").getHref(), conversionService.convert(entry.getKey(),
String.class));
links.add(l);
}
} else {
links.add(new Link(entityBaseUri.toString(), propRel));
}
if(resource.getContent() instanceof Iterable) {
for(Resource<?> res : (Iterable<Resource<?>>)resource.getContent()) {
Link propLink = propertyReferenceLink(res, entityBaseUri, propRel);
links.add(propLink);
}
} else if(resource.getContent() instanceof Map) {
for(Map.Entry<Object, Resource<?>> entry : ((Map<Object, Resource<?>>)resource.getContent()).entrySet()) {
Link l = new Link(entry.getValue().getLink("self").getHref(), conversionService.convert(entry.getKey(),
String.class));
links.add(l);
}
} else {
links.add(new Link(entityBaseUri.toString(), propRel));
}
return resourceResponse(null, new Resource<Object>(EMPTY_RESOURCE_LIST, links), HttpStatus.OK);
}
return resourceResponse(null, new Resource<Object>(EMPTY_RESOURCE_LIST, links), HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpFollowPropertyReference(RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest,
followPropertyReference(repoRequest,
id,
property),
HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpFollowPropertyReference(RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest,
followPropertyReference(repoRequest,
id,
property),
HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpFollowPropertyReference(RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
@PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest,
followPropertyReference(repoRequest,
id,
property,
propertyId),
HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpFollowPropertyReference(RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
@PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest,
followPropertyReference(repoRequest,
id,
property,
propertyId),
HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = {
RequestMethod.POST,
RequestMethod.PUT
},
consumes = {
"application/json",
"application/x-spring-data-compact+json",
"text/uri-list"
}
)
@ResponseBody
public ResponseEntity<Resource<?>> createPropertyReference(final RepositoryRestRequest repoRequest,
final @RequestBody Resource<Object> incoming,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
final RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(!repoMethodInvoker.hasSaveOne()) {
throw new NoSuchMethodException();
}
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(prop.property.isCollectionLike()) {
Collection coll = new ArrayList();
if("POST".equals(repoRequest.getRequest().getMethod())) {
coll.addAll((Collection)prop.propertyValue);
}
for(Link l : incoming.getLinks()) {
Object propVal = loadPropertyValue(prop.propertyType, l.getHref());
coll.add(propVal);
}
prop.wrapper.setProperty(prop.property, coll);
} else if(prop.property.isMap()) {
Map m = new HashMap();
if("POST".equals(repoRequest.getRequest().getMethod())) {
m.putAll((Map)prop.propertyValue);
}
for(Link l : incoming.getLinks()) {
Object propVal = loadPropertyValue(prop.propertyType, l.getHref());
m.put(l.getRel(), propVal);
}
prop.wrapper.setProperty(prop.property, m);
} else {
if("POST".equals(repoRequest.getRequest().getMethod())) {
throw new IllegalStateException(
"Cannot POST a reference to this singular property since the property type is not a List or a Map.");
}
if(incoming.getLinks().size() != 1) {
throw new IllegalArgumentException(
"Must send only 1 link to update a property reference that isn't a List or a Map.");
}
Object propVal = loadPropertyValue(prop.propertyType, incoming.getLinks().get(0).getHref());
prop.wrapper.setProperty(prop.property, propVal);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = {
RequestMethod.POST,
RequestMethod.PUT
},
consumes = {
"application/json",
"application/x-spring-data-compact+json",
"text/uri-list"
}
)
@ResponseBody
public ResponseEntity<Resource<?>> createPropertyReference(final RepositoryRestRequest repoRequest,
final @RequestBody Resource<Object> incoming,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
final RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(!repoMethodInvoker.hasSaveOne()) {
throw new NoSuchMethodException();
}
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(prop.property.isCollectionLike()) {
Collection coll = new ArrayList();
if("POST".equals(repoRequest.getRequest().getMethod())) {
coll.addAll((Collection)prop.propertyValue);
}
for(Link l : incoming.getLinks()) {
Object propVal = loadPropertyValue(prop.propertyType, l.getHref());
coll.add(propVal);
}
prop.wrapper.setProperty(prop.property, coll);
} else if(prop.property.isMap()) {
Map m = new HashMap();
if("POST".equals(repoRequest.getRequest().getMethod())) {
m.putAll((Map)prop.propertyValue);
}
for(Link l : incoming.getLinks()) {
Object propVal = loadPropertyValue(prop.propertyType, l.getHref());
m.put(l.getRel(), propVal);
}
prop.wrapper.setProperty(prop.property, m);
} else {
if("POST".equals(repoRequest.getRequest().getMethod())) {
throw new IllegalStateException(
"Cannot POST a reference to this singular property since the property type is not a List or a Map.");
}
if(incoming.getLinks().size() != 1) {
throw new IllegalArgumentException(
"Must send only 1 link to update a property reference that isn't a List or a Map.");
}
Object propVal = loadPropertyValue(prop.propertyType, incoming.getLinks().get(0).getHref());
prop.wrapper.setProperty(prop.property, propVal);
}
applicationContext.publishEvent(new BeforeLinkSaveEvent(prop.wrapper.getBean(), prop.propertyValue));
Object result = repoMethodInvoker.save(prop.wrapper.getBean());
applicationContext.publishEvent(new AfterLinkSaveEvent(result, prop.propertyValue));
return null;
}
};
doWithReferencedProperty(repoRequest,
id,
property,
handler);
return resourceResponse(null, EMPTY_RESOURCE, HttpStatus.CREATED);
}
applicationContext.publishEvent(new BeforeLinkSaveEvent(prop.wrapper.getBean(), prop.propertyValue));
Object result = repoMethodInvoker.save(prop.wrapper.getBean());
applicationContext.publishEvent(new AfterLinkSaveEvent(result, prop.propertyValue));
return null;
}
};
doWithReferencedProperty(repoRequest,
id,
property,
handler);
return resourceResponse(null, EMPTY_RESOURCE, HttpStatus.CREATED);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = {
RequestMethod.POST,
RequestMethod.PUT
},
consumes = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpCreatePropertyReference(final RepositoryRestRequest repoRequest,
final @RequestBody Resource<Object> incoming,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest, createPropertyReference(repoRequest,
incoming,
id,
property));
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = {
RequestMethod.POST,
RequestMethod.PUT
},
consumes = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpCreatePropertyReference(final RepositoryRestRequest repoRequest,
final @RequestBody Resource<Object> incoming,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest, createPropertyReference(repoRequest,
incoming,
id,
property));
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.DELETE
)
@ResponseBody
public ResponseEntity<Resource<?>> deletePropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
final RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(!repoMethodInvoker.hasDeleteOne()) {
throw new NoSuchMethodException();
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.DELETE
)
@ResponseBody
public ResponseEntity<Resource<?>> deletePropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
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()) {
Collection coll = new ArrayList();
for(Object obj : (Collection)prop.propertyValue) {
BeanWrapper propValWrapper = BeanWrapper.create(obj, conversionService);
String s = (String)propValWrapper.getProperty(prop.entity.getIdProperty(), String.class, false);
if(!propertyId.equals(s)) {
coll.add(obj);
}
}
prop.wrapper.setProperty(prop.property, coll);
} else if(prop.property.isMap()) {
Map m = new HashMap();
for(Map.Entry<Object, Object> entry : ((Map<Object, Object>)prop.propertyValue).entrySet()) {
BeanWrapper propValWrapper = BeanWrapper.create(entry.getValue(), conversionService);
String s = (String)propValWrapper.getProperty(prop.entity.getIdProperty(), String.class, false);
if(!propertyId.equals(s)) {
m.put(entry.getKey(), entry.getValue());
}
}
prop.wrapper.setProperty(prop.property, m);
} else {
prop.wrapper.setProperty(prop.property, null);
}
Function<ReferencedProperty, Resource<?>> handler = new Function<ReferencedProperty, Resource<?>>() {
@Override public Resource<?> apply(ReferencedProperty prop) {
if(null == prop.propertyValue) {
return null;
}
if(prop.property.isCollectionLike()) {
Collection coll = new ArrayList();
for(Object obj : (Collection)prop.propertyValue) {
BeanWrapper propValWrapper = BeanWrapper.create(obj, conversionService);
String s = (String)propValWrapper.getProperty(prop.entity.getIdProperty(), String.class, false);
if(!propertyId.equals(s)) {
coll.add(obj);
}
}
prop.wrapper.setProperty(prop.property, coll);
} else if(prop.property.isMap()) {
Map m = new HashMap();
for(Map.Entry<Object, Object> entry : ((Map<Object, Object>)prop.propertyValue).entrySet()) {
BeanWrapper propValWrapper = BeanWrapper.create(entry.getValue(), conversionService);
String s = (String)propValWrapper.getProperty(prop.entity.getIdProperty(), String.class, false);
if(!propertyId.equals(s)) {
m.put(entry.getKey(), entry.getValue());
}
}
prop.wrapper.setProperty(prop.property, m);
} 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;
}
};
doWithReferencedProperty(repoRequest,
id,
property,
handler);
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;
}
};
doWithReferencedProperty(repoRequest,
id,
property,
handler);
return resourceResponse(null, EMPTY_RESOURCE, HttpStatus.NO_CONTENT);
}
return resourceResponse(null, EMPTY_RESOURCE, HttpStatus.NO_CONTENT);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.DELETE,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpDeletePropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest, deletePropertyReference(repoRequest,
id,
property,
propertyId));
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.DELETE,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpDeletePropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest, deletePropertyReference(repoRequest,
id,
property,
propertyId));
}
private Link propertyReferenceLink(Resource<?> resource,
URI baseUri,
String rel) {
Link selfLink = resource.getLink("self");
String objId = selfLink.getHref().substring(selfLink.getHref().lastIndexOf('/') + 1);
return new Link(buildUri(baseUri, objId).toString(), rel);
}
private Link propertyReferenceLink(Resource<?> resource,
URI baseUri,
String rel) {
Link selfLink = resource.getLink("self");
String objId = selfLink.getHref().substring(selfLink.getHref().lastIndexOf('/') + 1);
return new Link(buildUri(baseUri, objId).toString(), rel);
}
private Object loadPropertyValue(Class<?> type, String href) {
String id = href.substring(href.lastIndexOf('/') + 1);
return domainClassConverter.convert(id,
STRING_TYPE,
TypeDescriptor.valueOf(type));
}
private Object loadPropertyValue(Class<?> type, String href) {
String id = href.substring(href.lastIndexOf('/') + 1);
return domainClassConverter.convert(id,
STRING_TYPE,
TypeDescriptor.valueOf(type));
}
@SuppressWarnings({"unchecked"})
private Resource<?> doWithReferencedProperty(RepositoryRestRequest repoRequest,
String id,
String propertyPath,
Function<ReferencedProperty, Resource<?>> handler)
throws ResourceNotFoundException, NoSuchMethodException {
RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(!repoMethodInvoker.hasFindOne()) {
throw new NoSuchMethodException();
}
@SuppressWarnings({"unchecked"})
private Resource<?> doWithReferencedProperty(RepositoryRestRequest repoRequest,
String id,
String propertyPath,
Function<ReferencedProperty, Resource<?>> handler)
throws ResourceNotFoundException, NoSuchMethodException {
RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(!repoMethodInvoker.hasFindOne()) {
throw new NoSuchMethodException();
}
Object domainObj = domainClassConverter.convert(id,
STRING_TYPE,
TypeDescriptor.valueOf(repoRequest.getPersistentEntity()
.getType()));
if(null == domainObj) {
throw new ResourceNotFoundException();
}
Object domainObj = domainClassConverter.convert(id,
STRING_TYPE,
TypeDescriptor.valueOf(repoRequest.getPersistentEntity()
.getType()));
if(null == domainObj) {
throw new ResourceNotFoundException();
}
String propertyName = repoRequest.getPersistentEntityResourceMapping().getNameForPath(propertyPath);
PersistentProperty prop = repoRequest.getPersistentEntity().getPersistentProperty(propertyName);
if(null == prop) {
throw new ResourceNotFoundException();
}
String propertyName = repoRequest.getPersistentEntityResourceMapping().getNameForPath(propertyPath);
PersistentProperty prop = repoRequest.getPersistentEntity().getPersistentProperty(propertyName);
if(null == prop) {
throw new ResourceNotFoundException();
}
BeanWrapper wrapper = BeanWrapper.create(domainObj, conversionService);
Object propVal = wrapper.getProperty(prop);
if(null == propVal) {
throw new ResourceNotFoundException();
}
BeanWrapper wrapper = BeanWrapper.create(domainObj, conversionService);
Object propVal = wrapper.getProperty(prop);
if(null == propVal) {
throw new ResourceNotFoundException();
}
return handler.apply(new ReferencedProperty(prop,
propVal,
wrapper));
}
return handler.apply(new ReferencedProperty(prop,
propVal,
wrapper));
}
private class ReferencedProperty {
final PersistentEntity entity;
final PersistentProperty property;
final Class<?> propertyType;
final Object propertyValue;
final BeanWrapper wrapper;
final RepositoryInformation propertyRepoInfo;
final Object propertyRepo;
final RepositoryMethodInvoker repoMethodInvoker;
private class ReferencedProperty {
final PersistentEntity entity;
final PersistentProperty property;
final Class<?> propertyType;
final Object propertyValue;
final BeanWrapper wrapper;
final RepositoryInformation propertyRepoInfo;
final Object propertyRepo;
final RepositoryMethodInvoker repoMethodInvoker;
private ReferencedProperty(PersistentProperty property,
Object propertyValue,
BeanWrapper wrapper) {
this.property = property;
this.propertyValue = propertyValue;
this.wrapper = wrapper;
if(property.isCollectionLike()) {
this.propertyType = property.getComponentType();
} else if(property.isMap()) {
this.propertyType = property.getMapValueType();
} else {
this.propertyType = property.getType();
}
this.propertyRepoInfo = repositories.getRepositoryInformationFor(propertyType);
this.entity = repositories.getPersistentEntity(propertyType);
this.propertyRepo = repositories.getRepositoryFor(entity.getType());
this.repoMethodInvoker = new RepositoryMethodInvoker(propertyRepo, propertyRepoInfo, entity);
}
}
private ReferencedProperty(PersistentProperty property,
Object propertyValue,
BeanWrapper wrapper) {
this.property = property;
this.propertyValue = propertyValue;
this.wrapper = wrapper;
if(property.isCollectionLike()) {
this.propertyType = property.getComponentType();
} else if(property.isMap()) {
this.propertyType = property.getMapValueType();
} else {
this.propertyType = property.getType();
}
this.propertyRepoInfo = repositories.getRepositoryInformationFor(propertyType);
this.entity = repositories.getPersistentEntity(propertyType);
this.propertyRepo = repositories.getRepositoryFor(entity.getType());
this.repoMethodInvoker = new RepositoryMethodInvoker(propertyRepo, propertyRepoInfo, entity);
}
}
}

View File

@@ -22,6 +22,7 @@ import org.springframework.data.rest.repository.PersistentEntityResource;
import org.springframework.data.rest.repository.invoke.RepositoryMethod;
import org.springframework.data.rest.repository.invoke.RepositoryMethodInvoker;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
import org.springframework.http.HttpStatus;
@@ -38,204 +39,209 @@ import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("/{repository}/search")
public class RepositorySearchController extends AbstractRepositoryRestController {
public RepositorySearchController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService) {
super(repositories, config, domainClassConverter, conversionService);
}
public RepositorySearchController(Repositories repositories,
RepositoryRestConfiguration config,
DomainClassConverter domainClassConverter,
ConversionService conversionService,
EntityLinks entityLinks) {
super(repositories,
config,
domainClassConverter,
conversionService,
entityLinks);
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-compact+json"
}
)
@ResponseBody
public Resource<?> list(RepositoryRestRequest repoRequest) {
List<Link> links = new ArrayList<Link>();
links.addAll(queryMethodLinks(repoRequest.getBaseUri(),
repoRequest.getPersistentEntity().getType()));
return new Resource<Object>(Collections.emptyList(), links);
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-compact+json"
}
)
@ResponseBody
public Resource<?> list(RepositoryRestRequest repoRequest) {
List<Link> links = new ArrayList<Link>();
links.addAll(queryMethodLinks(repoRequest.getBaseUri(),
repoRequest.getPersistentEntity().getType()));
return new Resource<Object>(Collections.emptyList(), links);
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpList(RepositoryRestRequest repoRequest) {
return jsonpWrapResponse(repoRequest, list(repoRequest), HttpStatus.OK);
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpList(RepositoryRestRequest repoRequest) {
return jsonpWrapResponse(repoRequest, list(repoRequest), HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{method}",
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-verbose+json"
}
)
@ResponseBody
public Resource<?> query(RepositoryRestRequest repoRequest,
@PathVariable String method)
throws ResourceNotFoundException {
RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(repoMethodInvoker.getQueryMethods().isEmpty()) {
throw new ResourceNotFoundException();
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{method}",
method = RequestMethod.GET,
produces = {
"application/json",
"application/x-spring-data-verbose+json"
}
)
@ResponseBody
public Resource<?> query(RepositoryRestRequest repoRequest,
@PathVariable String method)
throws ResourceNotFoundException {
RepositoryMethodInvoker repoMethodInvoker = repoRequest.getRepositoryMethodInvoker();
if(repoMethodInvoker.getQueryMethods().isEmpty()) {
throw new ResourceNotFoundException();
}
ResourceMapping repoMapping = repoRequest.getRepositoryResourceMapping();
String methodName = repoMapping.getNameForPath(method);
RepositoryMethod repoMethod = repoMethodInvoker.getQueryMethods().get(methodName);
if(null == repoMethod) {
for(RepositoryMethod queryMethod : repoMethodInvoker.getQueryMethods().values()) {
String path = findPath(queryMethod.getMethod());
if(path.equals(method)) {
repoMethod = queryMethod;
break;
}
}
if(null == repoMethod) {
throw new ResourceNotFoundException();
}
}
ResourceMapping repoMapping = repoRequest.getRepositoryResourceMapping();
String methodName = repoMapping.getNameForPath(method);
RepositoryMethod repoMethod = repoMethodInvoker.getQueryMethods().get(methodName);
if(null == repoMethod) {
for(RepositoryMethod queryMethod : repoMethodInvoker.getQueryMethods().values()) {
String path = findPath(queryMethod.getMethod());
if(path.equals(method)) {
repoMethod = queryMethod;
break;
}
}
if(null == repoMethod) {
throw new ResourceNotFoundException();
}
}
List<MethodParameter> methodParams = repoMethod.getParameters();
Object[] paramValues = new Object[methodParams.size()];
if(!methodParams.isEmpty()) {
for(int i = 0; i < paramValues.length; i++) {
MethodParameter param = methodParams.get(i);
if(Pageable.class.isAssignableFrom(param.getParameterType())) {
paramValues[i] = new PageRequest(repoRequest.getPagingAndSorting().getPageNumber(),
repoRequest.getPagingAndSorting().getPageSize(),
repoRequest.getPagingAndSorting().getSort());
} else if(Sort.class.isAssignableFrom(param.getParameterType())) {
paramValues[i] = repoRequest.getPagingAndSorting().getSort();
} else {
String paramName = repoMethod.getParameterNames().get(i);
String[] queryParamVals = repoRequest.getRequest().getParameterValues(paramName);
if(null == queryParamVals) {
if(paramName.startsWith("arg")) {
throw new IllegalArgumentException("No @Param annotation found on query method "
+ repoMethod.getMethod().getName()
+ " for parameter " + param.getParameterName());
} else {
throw new IllegalArgumentException("No query parameter specified for "
+ repoMethod.getMethod().getName() + " param '"
+ paramName + "'");
}
}
paramValues[i] = methodParameterConversionService.convert(queryParamVals, param);
}
}
}
List<MethodParameter> methodParams = repoMethod.getParameters();
Object[] paramValues = new Object[methodParams.size()];
if(!methodParams.isEmpty()) {
for(int i = 0; i < paramValues.length; i++) {
MethodParameter param = methodParams.get(i);
if(Pageable.class.isAssignableFrom(param.getParameterType())) {
paramValues[i] = new PageRequest(repoRequest.getPagingAndSorting().getPageNumber(),
repoRequest.getPagingAndSorting().getPageSize(),
repoRequest.getPagingAndSorting().getSort());
} else if(Sort.class.isAssignableFrom(param.getParameterType())) {
paramValues[i] = repoRequest.getPagingAndSorting().getSort();
} else {
String paramName = repoMethod.getParameterNames().get(i);
String[] queryParamVals = repoRequest.getRequest().getParameterValues(paramName);
if(null == queryParamVals) {
if(paramName.startsWith("arg")) {
throw new IllegalArgumentException("No @Param annotation found on query method "
+ repoMethod.getMethod().getName()
+ " for parameter " + param.getParameterName());
} else {
throw new IllegalArgumentException("No query parameter specified for "
+ repoMethod.getMethod().getName() + " param '"
+ paramName + "'");
}
}
paramValues[i] = methodParameterConversionService.convert(queryParamVals, param);
}
}
}
BaseUriAwareResource resources;
List<Link> links = new ArrayList<Link>();
Object result = repoMethodInvoker.invokeQueryMethod(repoMethod, paramValues);
if(result instanceof Page) {
Page page = (Page)result;
if(page.hasPreviousPage()) {
repoRequest.addPrevLink(page, links);
}
if(page.hasNextPage()) {
repoRequest.addNextLink(page, links);
}
if(page.hasContent()) {
resources = entitiesToResource(repoRequest, page.getContent());
} else {
resources = new BaseUriAwareResource(EMPTY_RESOURCE_LIST);
}
} else if(result instanceof Iterable) {
resources = entitiesToResource(repoRequest, (Iterable)result);
} else if(null == result) {
resources = new BaseUriAwareResource(EMPTY_RESOURCE_LIST);
} else {
PersistentEntityResource per = PersistentEntityResource.wrap(repoRequest.getPersistentEntity(),
result,
repoRequest.getBaseUri());
per.add(repoRequest.buildEntitySelfLink(result, conversionService));
resources = per;
}
resources.setBaseUri(repoRequest.getBaseUri())
.add(links);
BaseUriAwareResource resources;
List<Link> links = new ArrayList<Link>();
Object result = repoMethodInvoker.invokeQueryMethod(repoMethod, paramValues);
if(result instanceof Page) {
Page page = (Page)result;
if(page.hasPreviousPage()) {
repoRequest.addPrevLink(page, links);
}
if(page.hasNextPage()) {
repoRequest.addNextLink(page, links);
}
if(page.hasContent()) {
resources = entitiesToResource(repoRequest, page.getContent());
} else {
resources = new BaseUriAwareResource(EMPTY_RESOURCE_LIST);
}
} else if(result instanceof Iterable) {
resources = entitiesToResource(repoRequest, (Iterable)result);
} else if(null == result) {
resources = new BaseUriAwareResource(EMPTY_RESOURCE_LIST);
} else {
PersistentEntityResource per = PersistentEntityResource.wrap(repoRequest.getPersistentEntity(),
result,
repoRequest.getBaseUri());
per.add(repoRequest.buildEntitySelfLink(result, conversionService));
resources = per;
}
resources.setBaseUri(repoRequest.getBaseUri())
.add(links);
return resources;
}
return resources;
}
@RequestMapping(
value = "/{method}",
method = RequestMethod.GET,
produces = {
"application/x-spring-data-compact+json"
}
)
@ResponseBody
public Resource<?> queryCompact(RepositoryRestRequest repoRequest,
@PathVariable String method)
throws ResourceNotFoundException {
List<Link> links = new ArrayList<Link>();
@RequestMapping(
value = "/{method}",
method = RequestMethod.GET,
produces = {
"application/x-spring-data-compact+json"
}
)
@ResponseBody
public Resource<?> queryCompact(RepositoryRestRequest repoRequest,
@PathVariable String method)
throws ResourceNotFoundException {
List<Link> links = new ArrayList<Link>();
Resource<?> resource = query(repoRequest, method);
links.addAll(resource.getLinks());
Resource<?> resource = query(repoRequest, method);
links.addAll(resource.getLinks());
if(resource.getContent() instanceof Iterable) {
Iterable iter = (Iterable)resource.getContent();
for(Object obj : iter) {
if(null != obj && obj instanceof Resource) {
Resource res = (Resource)obj;
links.add(resourceLink(repoRequest, res));
}
}
} else if(resource.getContent() instanceof Resource) {
Resource res = (Resource)resource.getContent();
links.add(resourceLink(repoRequest, res));
}
if(resource.getContent() instanceof Iterable) {
Iterable iter = (Iterable)resource.getContent();
for(Object obj : iter) {
if(null != obj && obj instanceof Resource) {
Resource res = (Resource)obj;
links.add(resourceLink(repoRequest, res));
}
}
} else if(resource.getContent() instanceof Resource) {
Resource res = (Resource)resource.getContent();
links.add(resourceLink(repoRequest, res));
}
return new Resource<Object>(EMPTY_RESOURCE_LIST, links);
}
return new Resource<Object>(EMPTY_RESOURCE_LIST, links);
}
@RequestMapping(
value = "/{method}",
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpQuery(RepositoryRestRequest repoRequest,
@PathVariable String method)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, query(repoRequest, method), HttpStatus.OK);
}
@RequestMapping(
value = "/{method}",
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpQuery(RepositoryRestRequest repoRequest,
@PathVariable String method)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, query(repoRequest, method), HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
private BaseUriAwareResource entitiesToResource(RepositoryRestRequest repoRequest, Iterable entities) {
List<Resource<?>> resources = new ArrayList<Resource<?>>();
for(Object obj : entities) {
if(null == obj) {
resources.add(null);
break;
}
@SuppressWarnings({"unchecked"})
private BaseUriAwareResource entitiesToResource(RepositoryRestRequest repoRequest, Iterable entities) {
List<Resource<?>> resources = new ArrayList<Resource<?>>();
for(Object obj : entities) {
if(null == obj) {
resources.add(null);
break;
}
PersistentEntity persistentEntity = repositories.getPersistentEntity(obj.getClass());
if(null == persistentEntity) {
resources.add(new BaseUriAwareResource<Object>(obj)
.setBaseUri(repoRequest.getBaseUri()));
continue;
}
PersistentEntity persistentEntity = repositories.getPersistentEntity(obj.getClass());
if(null == persistentEntity) {
resources.add(new BaseUriAwareResource<Object>(obj)
.setBaseUri(repoRequest.getBaseUri()));
continue;
}
PersistentEntityResource per = PersistentEntityResource.wrap(persistentEntity, obj, repoRequest.getBaseUri());
per.add(repoRequest.buildEntitySelfLink(obj, conversionService));
resources.add(per);
}
return new BaseUriAwareResource(resources)
.setBaseUri(repoRequest.getBaseUri());
}
PersistentEntityResource per = PersistentEntityResource.wrap(persistentEntity, obj, repoRequest.getBaseUri());
per.add(repoRequest.buildEntitySelfLink(obj, conversionService));
resources.add(per);
}
return new BaseUriAwareResource(resources)
.setBaseUri(repoRequest.getBaseUri());
}
}

View File

@@ -23,12 +23,12 @@ import org.springframework.data.rest.repository.json.Jackson2DatatypeHelper;
import org.springframework.data.rest.repository.json.PersistentEntityJackson2Module;
import org.springframework.data.rest.repository.json.PersistentEntityToJsonSchemaConverter;
import org.springframework.data.rest.repository.support.DomainObjectMerger;
import org.springframework.data.rest.repository.support.RepositoryEntityLinks;
import org.springframework.data.rest.webmvc.BaseUriMethodArgumentResolver;
import org.springframework.data.rest.webmvc.PagingAndSortingMethodArgumentResolver;
import org.springframework.data.rest.webmvc.PersistentEntityResourceHandlerMethodArgumentResolver;
import org.springframework.data.rest.webmvc.RepositoryController;
import org.springframework.data.rest.webmvc.RepositoryEntityController;
import org.springframework.data.rest.webmvc.RepositoryEntityLinksMethodArgumentResolver;
import org.springframework.data.rest.webmvc.RepositoryInformationHandlerMethodArgumentResolver;
import org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController;
import org.springframework.data.rest.webmvc.RepositoryRestHandlerAdapter;
@@ -39,6 +39,7 @@ import org.springframework.data.rest.webmvc.ServerHttpRequestMethodArgumentResol
import org.springframework.data.rest.webmvc.convert.JsonpResponseHttpMessageConverter;
import org.springframework.data.rest.webmvc.convert.UriListHttpMessageConverter;
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;
@@ -145,7 +146,8 @@ public class RepositoryRestMvcConfiguration {
repositories().getObject(),
config(),
domainClassConverter(),
defaultConversionService()
defaultConversionService(),
entityLinks()
);
}
@@ -161,7 +163,8 @@ public class RepositoryRestMvcConfiguration {
repositories().getObject(),
config(),
domainClassConverter(),
defaultConversionService()
defaultConversionService(),
entityLinks()
);
}
@@ -177,7 +180,8 @@ public class RepositoryRestMvcConfiguration {
repositories().getObject(),
config(),
domainClassConverter(),
defaultConversionService()
defaultConversionService(),
entityLinks()
);
}
@@ -193,7 +197,8 @@ public class RepositoryRestMvcConfiguration {
repositories().getObject(),
config(),
domainClassConverter(),
defaultConversionService()
defaultConversionService(),
entityLinks()
);
}
@@ -242,8 +247,16 @@ public class RepositoryRestMvcConfiguration {
return new RepositoryRestRequestHandlerMethodArgumentResolver();
}
@Bean public RepositoryEntityLinksMethodArgumentResolver entityLinksMethodArgumentResolver() {
return new RepositoryEntityLinksMethodArgumentResolver();
/**
* A special {@link org.springframework.hateoas.EntityLinks} implementation that takes repository and current
* configuration into account when generating links.
*
* @return
*
* @throws Exception
*/
@Bean public EntityLinks entityLinks() throws Exception {
return new RepositoryEntityLinks(repositories().getObject(), config());
}
/**
@@ -387,8 +400,7 @@ public class RepositoryRestMvcConfiguration {
serverHttpRequestMethodArgumentResolver(),
repoInfoMethodArgumentResolver(),
repoRequestArgumentResolver(),
persistentEntityArgumentResolver(),
entityLinksMethodArgumentResolver());
persistentEntityArgumentResolver());
}
/**