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

@@ -123,6 +123,6 @@ public class UriToEntityConverter implements ConditionalGenericConverter {
"Cannot resolve URI " + uri + ". Is it local or remote? Only local URIs are resolvable."));
}
return invokerFactory.getInvokerFor(targetType.getType()).invokeFindOne(parts[parts.length - 1]).orElse(null);
return invokerFactory.getInvokerFor(targetType.getType()).invokeFindById(parts[parts.length - 1]).orElse(null);
}
}

View File

@@ -19,7 +19,6 @@ import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -31,6 +30,7 @@ import org.springframework.data.repository.core.support.AbstractRepositoryMetada
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.core.config.EntityLookupRegistrar.LookupRegistrar.Lookup;
import org.springframework.data.rest.core.support.EntityLookup;
import org.springframework.data.util.StreamUtils;
import org.springframework.util.Assert;
/**
@@ -42,16 +42,16 @@ import org.springframework.util.Assert;
*/
class EntityLookupConfiguration implements EntityLookupRegistrar {
private final List<LookupInformation<Object, Serializable, Repository<? extends Object, ?>>> lookupInformation = new ArrayList<LookupInformation<Object, Serializable, Repository<?, ?>>>();
private final List<Class<?>> lookupTypes = new ArrayList<Class<?>>();
private final List<LookupInformation<Object, Object, Repository<? extends Object, ?>>> lookupInformation = new ArrayList<>();
private final List<Class<?>> lookupTypes = new ArrayList<>();
/*
* (non-Javadoc)
* @see org.springframework.data.rest.core.config.EntityLookupRegistrar#forRepository(java.lang.Class, org.springframework.core.convert.converter.Converter, org.springframework.data.rest.core.config.EntityLookupRegistrar.LookupRegistrar.Lookup)
*/
@Override
public <T, ID extends Serializable, R extends Repository<T, ?>> EntityLookupRegistrar forRepository(
Class<R> repositoryType, Converter<T, ID> converter, Lookup<R, ID> lookup) {
public <T, ID, R extends Repository<T, ?>> EntityLookupRegistrar forRepository(Class<R> repositoryType,
Converter<T, ID> converter, Lookup<R, ID> lookup) {
new MappingBuilder<T, ID, R>(repositoryType).withIdMapping(converter).withLookup(lookup);
return this;
@@ -62,8 +62,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
* @see org.springframework.data.rest.core.config.EntityLookupRegistrar#forValueRepository(java.lang.Class)
*/
@Override
public <T, ID extends Serializable, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forLookupRepository(
Class<R> type) {
public <T, ID, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forLookupRepository(Class<R> type) {
this.lookupTypes.add(AbstractRepositoryMetadata.getMetadata(type).getDomainType());
return forRepository(type);
}
@@ -73,8 +72,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
* @see org.springframework.data.rest.core.config.EntityLookupRegistrar#forRepository(java.lang.Class)
*/
@Override
public <T, ID extends Serializable, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forRepository(
Class<R> type) {
public <T, ID, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forRepository(Class<R> type) {
return new MappingBuilder<T, ID, R>(type);
}
@@ -83,8 +81,8 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
* @see org.springframework.data.rest.core.config.EntityLookupRegistrar#forValueRepository(java.lang.Class, org.springframework.core.convert.converter.Converter, org.springframework.data.rest.core.config.EntityLookupRegistrar.LookupRegistrar.Lookup)
*/
@Override
public <T, ID extends Serializable, R extends Repository<T, ?>> EntityLookupRegistrar forValueRepository(
Class<R> type, Converter<T, ID> identifierMapping, Lookup<R, ID> lookup) {
public <T, ID, R extends Repository<T, ?>> EntityLookupRegistrar forValueRepository(Class<R> type,
Converter<T, ID> identifierMapping, Lookup<R, ID> lookup) {
this.lookupTypes.add(AbstractRepositoryMetadata.getMetadata(type).getDomainType());
return forRepository(type, identifierMapping, lookup);
@@ -96,7 +94,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
* @author Oliver Gierke
*/
@RequiredArgsConstructor
private class MappingBuilder<T, ID extends Serializable, R extends Repository<T, ?>>
private class MappingBuilder<T, ID, R extends Repository<T, ?>>
implements LookupRegistrar<T, ID, R>, IdMappingRegistrar<T, R> {
private @NonNull final Class<R> repositoryType;
@@ -125,8 +123,8 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
@SuppressWarnings("unchecked")
public EntityLookupRegistrar withLookup(Lookup<R, ID> lookup) {
EntityLookupConfiguration.this.lookupInformation.add(
(LookupInformation<Object, Serializable, Repository<? extends Object, ?>>) new LookupInformation<T, ID, R>(
EntityLookupConfiguration.this.lookupInformation
.add((LookupInformation<Object, Object, Repository<? extends Object, ?>>) new LookupInformation<T, ID, R>(
repositoryType, idMapping, lookup));
return EntityLookupConfiguration.this;
@@ -137,7 +135,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
* @see org.springframework.data.rest.core.config.EntityLookupRegistrar.IdMappingRegistrar#withIdMapping(org.springframework.core.convert.converter.Converter)
*/
@Override
public <ID2 extends Serializable> LookupRegistrar<T, ID2, R> withIdMapping(Converter<T, ID2> idMapping) {
public <ID2> LookupRegistrar<T, ID2, R> withIdMapping(Converter<T, ID2> idMapping) {
return new MappingBuilder<T, ID2, R>(repositoryType, idMapping);
}
}
@@ -152,13 +150,9 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
Assert.notNull(repositories, "Repositories must not be null!");
List<EntityLookup<?>> lookups = new ArrayList<EntityLookup<?>>(lookupInformation.size());
for (LookupInformation<Object, Serializable, Repository<? extends Object, ?>> information : lookupInformation) {
lookups.add(new RepositoriesEntityLookup<Object>(repositories, information));
}
return lookups;
return lookupInformation.stream()//
.map(it -> new RepositoriesEntityLookup<>(repositories, it))//
.collect(StreamUtils.toUnmodifiableList());
}
public boolean isLookupType(Class<?> type) {
@@ -172,7 +166,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
*/
private static class RepositoriesEntityLookup<T> implements EntityLookup<T> {
private final LookupInformation<Object, Serializable, Repository<? extends T, ?>> lookupInfo;
private final LookupInformation<Object, Object, Repository<? extends T, ?>> lookupInfo;
private final Repository<? extends T, ?> repository;
private final Class<?> domainType;
@@ -184,7 +178,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
*/
@SuppressWarnings("unchecked")
public RepositoriesEntityLookup(Repositories repositories,
LookupInformation<Object, Serializable, Repository<? extends T, ?>> lookupInformation) {
LookupInformation<Object, Object, Repository<? extends T, ?>> lookupInformation) {
Assert.notNull(repositories, "Repositories must not be null!");
Assert.notNull(lookupInformation, "LookupInformation must not be null!");
@@ -205,7 +199,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
* @see org.springframework.data.rest.core.support.EntityLookup#getResourceIdentifier(java.lang.Object)
*/
@Override
public Serializable getResourceIdentifier(T entity) {
public Object getResourceIdentifier(T entity) {
return lookupInfo.getIdentifierMapping().convert(entity);
}
@@ -214,7 +208,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
* @see org.springframework.data.rest.core.support.EntityLookup#lookupEntity(java.io.Serializable)
*/
@Override
public Optional<Object> lookupEntity(Serializable id) {
public Optional<Object> lookupEntity(Object id) {
return Optional.ofNullable(lookupInfo.getLookup().lookup(repository, id));
}
@@ -229,7 +223,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
}
@Value
private static class LookupInformation<T, ID extends Serializable, R extends Repository<? extends T, ?>> {
private static class LookupInformation<T, ID, R extends Repository<? extends T, ?>> {
private final Class<R> repositoryType;
private final Converter<T, ID> identifierMapping;

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.data.rest.core.config;
import java.io.Serializable;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.repository.Repository;
import org.springframework.data.rest.core.config.EntityLookupRegistrar.LookupRegistrar.Lookup;
@@ -36,7 +34,7 @@ public interface EntityLookupRegistrar {
* @param type must not be {@literal null}.
* @return
*/
<T, ID extends Serializable, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forRepository(Class<R> type);
<T, ID, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forRepository(Class<R> type);
/**
* Starts building a custom {@link EntityLookup} for the given repository type and registers the domain type of the
@@ -45,7 +43,7 @@ public interface EntityLookupRegistrar {
* @param type must not be {@literal null}.
* @return
*/
<T, ID extends Serializable, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forLookupRepository(Class<R> type);
<T, ID, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forLookupRepository(Class<R> type);
interface IdMappingRegistrar<T, R extends Repository<T, ?>> {
@@ -55,7 +53,7 @@ public interface EntityLookupRegistrar {
* @param mapping must not be {@literal null}.
* @return
*/
<ID extends Serializable> LookupRegistrar<T, ID, R> withIdMapping(Converter<T, ID> mapping);
<ID> LookupRegistrar<T, ID, R> withIdMapping(Converter<T, ID> mapping);
}
/**
@@ -65,7 +63,7 @@ public interface EntityLookupRegistrar {
* @param identifierMapping must not be {@literal null}.
* @param lookup must not be {@literal null}.
*/
<T, ID extends Serializable, R extends Repository<T, ?>> EntityLookupRegistrar forRepository(Class<R> type,
<T, ID, R extends Repository<T, ?>> EntityLookupRegistrar forRepository(Class<R> type,
Converter<T, ID> identifierMapping, Lookup<R, ID> lookup);
/**
@@ -76,10 +74,10 @@ public interface EntityLookupRegistrar {
* @param identifierMapping must not be {@literal null}.
* @param lookup must not be {@literal null}.
*/
<T, ID extends Serializable, R extends Repository<T, ?>> EntityLookupRegistrar forValueRepository(Class<R> type,
<T, ID, R extends Repository<T, ?>> EntityLookupRegistrar forValueRepository(Class<R> type,
Converter<T, ID> identifierMapping, Lookup<R, ID> lookup);
interface LookupRegistrar<T, ID extends Serializable, R extends Repository<T, ?>> {
interface LookupRegistrar<T, ID, R extends Repository<T, ?>> {
/**
* Registers the given {@link Lookup} to obtain entity instances.

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.data.rest.core.support;
import java.io.Serializable;
import java.util.Optional;
import org.springframework.plugin.core.Plugin;
@@ -42,7 +41,7 @@ public interface EntityLookup<T> extends Plugin<Class<?>> {
* @param entity will never be {@literal null}.
* @return must not be {@literal null}.
*/
Serializable getResourceIdentifier(T entity);
Object getResourceIdentifier(T entity);
/**
* Returns the entity instance to be used if an entity with the given identifier value is requested. Implementations
@@ -55,5 +54,5 @@ public interface EntityLookup<T> extends Plugin<Class<?>> {
* @param id will never be {@literal null}.
* @return can be {@literal null}.
*/
Optional<Object> lookupEntity(Serializable id);
Optional<Object> lookupEntity(Object id);
}

View File

@@ -85,12 +85,13 @@ public class UnwrappingRepositoryInvokerFactory implements RepositoryInvokerFact
* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeFindOne(java.io.Serializable)
*/
@Override
@SuppressWarnings("unchecked")
public <T> Optional<T> invokeFindOne(Serializable id) {
public <T> Optional<T> invokeFindById(Object id) {
return (Optional<T>) lookup//
.map(it -> it.lookupEntity(id).orElse(Optional.empty()))//
.orElseGet(() -> delegate.invokeFindOne(id));
.orElseGet(() -> delegate.invokeFindById(id));
}
/*
@@ -139,13 +140,13 @@ public class UnwrappingRepositoryInvokerFactory implements RepositoryInvokerFact
return delegate.hasSaveMethod();
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeDelete(java.io.Serializable)
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeDeleteById(java.lang.Object)
*/
@Override
public void invokeDelete(Serializable id) {
delegate.invokeDelete(id);
public void invokeDeleteById(Object id) {
delegate.invokeDeleteById(id);
}
/*

View File

@@ -105,7 +105,7 @@ public class UriToEntityConverterUnitTests {
Entity reference = new Entity();
RepositoryInvoker invoker = mock(RepositoryInvoker.class);
doReturn(Optional.of(reference)).when(invoker).invokeFindOne("1");
doReturn(Optional.of(reference)).when(invoker).invokeFindById("1");
doReturn(invoker).when(invokerFactory).getInvokerFor(ENTITY_TYPE.getType());
assertThat(converter.convert(URI.create("/foo/bar/1"), URI_TYPE, ENTITY_TYPE)).isEqualTo((Object) reference);

View File

@@ -32,10 +32,10 @@ public interface OrderRepository extends CrudRepository<Order, UUID> {
@Override
<S extends Order> S save(S entity);
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#findOne(java.io.Serializable)
* @see org.springframework.data.repository.CrudRepository#findById(java.lang.Object)
*/
@Override
Optional<Order> findOne(UUID id);
Optional<Order> findById(UUID id);
}

View File

@@ -152,7 +152,7 @@ public class CrudMethodsSupportedHttpMethodsUnitTests {
@Override
@RestResource(exported = false)
Optional<Object> findOne(Long id);
Optional<Object> findById(Long id);
}
interface NoFindOne extends Repository<Object, Long> {

View File

@@ -86,7 +86,7 @@ public class UnwrappingRepositoryInvokerFactoryUnitTests {
when(delegate.getInvokerFor(Profile.class)).thenReturn(invoker);
factory = new UnwrappingRepositoryInvokerFactory(delegate, Arrays.asList(lookup));
factory.getInvokerFor(Profile.class).invokeFindOne(1L);
factory.getInvokerFor(Profile.class).invokeFindById(1L);
verify(lookup, times(1)).lookupEntity(eq(1L));
}