DATACMNS-867 - RepositoryInvoker now returns an Optional for invokeFindOne(…).

Adapted ReflectionRepositoryInvoker to transparently unwrap other potentially used wrapper types to then convert the result into an Optional.
This commit is contained in:
Oliver Gierke
2017-03-21 11:50:50 +01:00
parent dec820d6c2
commit fee153f724
7 changed files with 47 additions and 13 deletions

View File

@@ -17,6 +17,7 @@ package org.springframework.data.querydsl;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
@@ -125,7 +126,7 @@ public class QuerydslRepositoryInvokerAdapter implements RepositoryInvoker {
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeFindOne(java.io.Serializable)
*/
@Override
public <T> T invokeFindOne(Serializable id) {
public <T> Optional<T> invokeFindOne(Serializable id) {
return delegate.invokeFindOne(id);
}

View File

@@ -89,8 +89,8 @@ class CrudRepositoryInvoker extends ReflectionRepositoryInvoker {
*/
@Override
@SuppressWarnings("unchecked")
public <T> T invokeFindOne(Serializable id) {
return customFindOneMethod ? super.invokeFindOne(id) : (T) repository.findOne(convertId(id));
public <T> Optional<T> invokeFindOne(Serializable id) {
return customFindOneMethod ? super.invokeFindOne(id) : (Optional<T>) repository.findOne(convertId(id));
}
/*

View File

@@ -152,11 +152,9 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
Class<?> domainType = targetType.getType();
RepositoryInvoker invoker = repositoryInvokerFactory.getInvokerFor(domainType);
RepositoryInformation information = repositories.getRequiredRepositoryInformation(domainType);
return repositories.getRepositoryInformationFor(domainType)//
.map(it -> invoker.invokeFindOne(conversionService.convert(source, it.getIdType())))//
.orElseThrow(() -> new IllegalStateException(
String.format("Couldn't find RepositoryInformation for %s!", domainType)));
return invoker.invokeFindOne(conversionService.convert(source, information.getIdType())).orElse(null);
}
/*

View File

@@ -30,6 +30,7 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.repository.core.CrudMethods;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Param;
import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.MultiValueMap;
@@ -135,12 +136,23 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker {
* @see org.springframework.data.rest.core.invoke.RepositoryInvoker#invokeFindOne(java.io.Serializable)
*/
@Override
public <T> T invokeFindOne(Serializable id) {
@SuppressWarnings("unchecked")
public <T> Optional<T> invokeFindOne(Serializable id) {
Method method = methods.getFindOneMethod()//
.orElseThrow(() -> new IllegalStateException("Repository doesn't have a find-one-method declared!"));
return invoke(method, convertId(id));
Object invoke = invoke(method, convertId(id));
if (Optional.class.isInstance(invoke)) {
return (Optional<T>) invoke;
}
if (invoke == null) {
return Optional.empty();
}
return conversionService.convert(QueryExecutionConverters.unwrap(invoke), Optional.class);
}
/*
@@ -169,7 +181,7 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker {
if (idTypes.contains(parameterType)) {
invoke(method, convertId(id));
} else {
invoke(method, this.<Object>invokeFindOne(id));
invoke(method, this.<Object> invokeFindOne(id).orElse(null));
}
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.repository.support;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
@@ -49,7 +50,7 @@ public interface RepositoryInvoker extends RepositoryInvocationInformation {
* @return the entity with the given id.
* @throws IllegalStateException if the repository does not expose a find-one-method.
*/
<T> T invokeFindOne(Serializable id);
<T> Optional<T> invokeFindOne(Serializable id);
/**
* Invokes the find-all method of the underlying repository using the method taking a {@link Pageable} as parameter if

View File

@@ -18,6 +18,8 @@ package org.springframework.data.repository.support;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.util.Optional;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -59,9 +61,9 @@ public class DefaultRepositoryInvokerFactoryIntegrationTests {
Product product = new Product();
when(productRepository.findOne(4711L)).thenReturn(product);
Object invokeFindOne = factory.getInvokerFor(Product.class).invokeFindOne(4711L);
Optional<Object> invokeFindOne = factory.getInvokerFor(Product.class).invokeFindOne(4711L);
assertThat(invokeFindOne).isEqualTo(product);
assertThat(invokeFindOne).isEqualTo(Optional.of(product));
}
@Test // DATACMNS-374, DATACMNS-589

View File

@@ -16,6 +16,7 @@
package org.springframework.data.repository.support;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.repository.support.RepositoryInvocationTestUtils.*;
@@ -25,6 +26,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
@@ -239,6 +241,19 @@ public class ReflectionRepositoryInvokerUnitTests {
}
}
@Test // DATACMNS-867
public void convertsWrapperTypeToJdkOptional() {
GuavaRepository mock = mock(GuavaRepository.class);
when(mock.findOne(any())).thenReturn(com.google.common.base.Optional.of(new Domain()));
RepositoryInvoker invoker = getInvokerFor(mock);
Optional<Object> invokeFindOne = invoker.invokeFindOne(1L);
assertThat(invokeFindOne).isPresent();
}
private static RepositoryInvoker getInvokerFor(Object repository) {
RepositoryMetadata metadata = new DefaultRepositoryMetadata(repository.getClass().getInterfaces()[0]);
@@ -298,4 +313,9 @@ public class ReflectionRepositoryInvokerUnitTests {
Domain findByClass(@Param("value") int value);
}
interface GuavaRepository extends Repository<Domain, Long> {
com.google.common.base.Optional<Domain> findOne(Long id);
}
}