DATAREST-1064 - Adapt to API changes in repository interfaces.

Additional cleanups in QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver to make sure a QuerydslRepositoryInvokerAdapter is only applied if the QuerydslPredicateBuilder actually exposes a predicate. Extracted a couple of methods to make sure the mapping pipeline reads nicely.
This commit is contained in:
Oliver Gierke
2017-05-03 17:22:54 +02:00
parent 632ca25998
commit f906695e7a
26 changed files with 104 additions and 89 deletions

View File

@@ -416,7 +416,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
resourceInformation.verifySupportedMethod(HttpMethod.DELETE, ResourceType.ITEM);
RepositoryInvoker invoker = resourceInformation.getInvoker();
Optional<Object> domainObj = invoker.invokeFindOne(id);
Optional<Object> domainObj = invoker.invokeFindById(id);
return domainObj.map(it -> {
@@ -425,7 +425,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
eTag.verify(entity, it);
publisher.publishEvent(new BeforeDeleteEvent(it));
invoker.invokeDelete((Serializable) entity.getIdentifierAccessor(it).getIdentifier().orElse(null));
invoker.invokeDeleteById((Serializable) entity.getIdentifierAccessor(it).getIdentifier().orElse(null));
publisher.publishEvent(new AfterDeleteEvent(it));
return new ResponseEntity<Object>(HttpStatus.NO_CONTENT);
@@ -513,6 +513,6 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
resourceInformation.verifySupportedMethod(HttpMethod.GET, ResourceType.ITEM);
return resourceInformation.getInvoker().invokeFindOne(id);
return resourceInformation.getInvoker().invokeFindById(id);
}
}

View File

@@ -397,7 +397,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
RepositoryInvoker invoker = repositoryInvokerFactory.getInvokerFor(type);
return invoker.invokeFindOne(id);
return invoker.invokeFindById(id);
}
private Optional<ResourceSupport> doWithReferencedProperty(RootResourceInformation resourceInformation,
@@ -415,7 +415,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
resourceInformation.verifySupportedMethod(method, property);
RepositoryInvoker invoker = resourceInformation.getInvoker();
Optional<Object> domainObj = invoker.invokeFindOne(id);
Optional<Object> domainObj = invoker.invokeFindById(id);
domainObj.orElseThrow(() -> new ResourceNotFoundException());

View File

@@ -74,6 +74,15 @@ public class AlpsJsonHttpMessageConverter extends MappingJackson2HttpMessageConv
&& super.canWrite(clazz, mediaType);
}
/*
* (non-Javadoc)
* @see org.springframework.http.converter.AbstractGenericHttpMessageConverter#canWrite(java.lang.reflect.Type, java.lang.Class, org.springframework.http.MediaType)
*/
@Override
public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
return canWrite(clazz, mediaType);
}
/*
* (non-Javadoc)
* @see org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#canRead(java.lang.reflect.Type, java.lang.Class, org.springframework.http.MediaType)

View File

@@ -128,7 +128,7 @@ public class PersistentEntityResourceHandlerMethodArgumentResolver implements Ha
Optional<Serializable> id = Optional
.ofNullable(idResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory));
Optional<Object> objectToUpdate = id.flatMap(it -> resourceInformation.getInvoker().invokeFindOne(it));
Optional<Object> objectToUpdate = id.flatMap(it -> resourceInformation.getInvoker().invokeFindById(it));
Object obj = read(resourceInformation, incoming, converter, objectToUpdate);

View File

@@ -18,6 +18,7 @@ package org.springframework.data.rest.webmvc.config;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
@@ -35,6 +36,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import com.mysema.commons.lang.Pair;
import com.querydsl.core.types.Predicate;
/**
@@ -75,7 +77,6 @@ class QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver
* @see org.springframework.data.rest.webmvc.config.RootResourceInformationHandlerMethodArgumentResolver#postProcess(org.springframework.data.repository.support.RepositoryInvoker, java.lang.Class, java.util.Map)
*/
@Override
@SuppressWarnings({ "unchecked" })
protected RepositoryInvoker postProcess(MethodParameter parameter, RepositoryInvoker invoker, Class<?> domainType,
Map<String, String[]> parameters) {
@@ -85,17 +86,27 @@ class QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver
return repositories.getRepositoryFor(domainType)//
.filter(it -> QuerydslPredicateExecutor.class.isInstance(it))//
.map(it -> {
.map(it -> QuerydslPredicateExecutor.class.cast(it))//
.flatMap(it -> getRepositoryAndPredicate(it, domainType, parameters))//
.map(it -> getQuerydslAdapter(invoker, it.getFirst(), it.getSecond()))//
.orElse(invoker);
}
ClassTypeInformation<?> type = ClassTypeInformation.from(domainType);
private Optional<Pair<QuerydslPredicateExecutor<?>, Predicate>> getRepositoryAndPredicate(
QuerydslPredicateExecutor<?> repository, Class<?> domainType, Map<String, String[]> parameters) {
QuerydslBindings bindings = factory.createBindingsFor(type);
Predicate predicate = predicateBuilder.getPredicate(type, toMultiValueMap(parameters), bindings);
ClassTypeInformation<?> type = ClassTypeInformation.from(domainType);
return (RepositoryInvoker) new QuerydslRepositoryInvokerAdapter(invoker,
(QuerydslPredicateExecutor<Object>) it, predicate);
QuerydslBindings bindings = factory.createBindingsFor(type);
Predicate predicate = predicateBuilder.getPredicate(type, toMultiValueMap(parameters), bindings);
}).orElse(invoker);
return Optional.ofNullable(predicate).map(it -> Pair.of(repository, it));
}
@SuppressWarnings("unchecked")
private static RepositoryInvoker getQuerydslAdapter(RepositoryInvoker invoker,
QuerydslPredicateExecutor<?> repository, Predicate predicate) {
return new QuerydslRepositoryInvokerAdapter(invoker, (QuerydslPredicateExecutor<Object>) repository, predicate);
}
/**

View File

@@ -762,7 +762,7 @@ public class PersistentEntityJackson2Module extends SimpleModule {
*/
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return invoker.invokeFindOne(p.getValueAsString());
return invoker.invokeFindById(p.getValueAsString());
}
}

View File

@@ -80,8 +80,8 @@ public class RepositoryPropertyReferenceControllerUnitTests {
controller.setApplicationEventPublisher(publisher);
doReturn(invoker).when(invokerFactory).getInvokerFor(Reference.class);
doReturn(Optional.of(new Sample())).when(invoker).invokeFindOne(4711);
doReturn(Optional.of(new Reference())).when(invoker).invokeFindOne("some-id");
doReturn(Optional.of(new Sample())).when(invoker).invokeFindById(4711);
doReturn(Optional.of(new Reference())).when(invoker).invokeFindById("some-id");
doReturn(new Sample()).when(invoker).invokeSave(any(Object.class));
RootResourceInformation information = new RootResourceInformation(metadata, entity, invoker);
@@ -90,7 +90,7 @@ public class RepositoryPropertyReferenceControllerUnitTests {
controller.createPropertyReference(information, HttpMethod.POST, request, 4711, "references");
verify(invokerFactory).getInvokerFor(Reference.class);
verify(invoker).invokeFindOne("some-id");
verify(invoker).invokeFindById("some-id");
}
@RestResource