diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java index 596b39ed1..f8047adbc 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.data.cassandra.repository.config; import java.lang.annotation.Annotation; @@ -22,8 +23,8 @@ import java.util.stream.Collectors; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.cassandra.config.xml.ParsingUtils; -import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.io.ResourceLoader; +import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.cassandra.config.DefaultBeanNames; import org.springframework.data.cassandra.mapping.Table; import org.springframework.data.cassandra.repository.CassandraRepository; @@ -35,6 +36,7 @@ import org.springframework.data.repository.config.RepositoryConfigurationExtensi import org.springframework.data.repository.config.RepositoryConfigurationSource; import org.springframework.data.repository.config.XmlRepositoryConfigurationSource; import org.springframework.data.repository.util.ReactiveWrappers; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.w3c.dom.Element; @@ -49,25 +51,33 @@ public class CassandraRepositoryConfigurationExtension extends RepositoryConfigu private static final String CASSANDRA_TEMPLATE_REF = "cassandra-template-ref"; - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getModuleName() + /** + * @inheritDoc */ @Override public String getModuleName() { return "Reactive Cassandra"; } + /** + * @inheritDoc + */ @Override protected String getModulePrefix() { return "cassandra"; } + /** + * @inheritDoc + */ @Override public String getRepositoryFactoryClassName() { return CassandraRepositoryFactoryBean.class.getName(); } + /** + * @inheritDoc + */ @Override public void postProcess(BeanDefinitionBuilder builder, XmlRepositoryConfigurationSource config) { @@ -77,53 +87,78 @@ public class CassandraRepositoryConfigurationExtension extends RepositoryConfigu DefaultBeanNames.TEMPLATE); } + /** + * @inheritDoc + */ @Override public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource config) { - AnnotationAttributes attributes = config.getAttributes(); - - String cassandraTemplateRef = attributes.getString("cassandraTemplateRef"); + String cassandraTemplateRef = config.getAttributes().getString("cassandraTemplateRef"); if (StringUtils.hasText(cassandraTemplateRef)) { builder.addPropertyReference("cassandraTemplate", cassandraTemplateRef); } } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getIdentifyingAnnotations() + /** + * @inheritDoc */ @Override protected Collection> getIdentifyingAnnotations() { - return Collections.> singleton(Table.class); + return Collections.singleton(Table.class); } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getIdentifyingTypes() + /** + * @inheritDoc */ @Override protected Collection> getIdentifyingTypes() { - return Collections.> singleton(CassandraRepository.class); + return Collections.singleton(CassandraRepository.class); } + /** + * @inheritDoc + */ @Override public Collection> getRepositoryConfigurations( T configSource, ResourceLoader loader, boolean strictMatchesOnly) { - Collection> repositoryConfigurations = super.getRepositoryConfigurations(configSource, - loader, strictMatchesOnly); + Collection> repositoryConfigurations = + super.getRepositoryConfigurations(configSource, loader, strictMatchesOnly); - if (ReactiveWrappers.isAvailable()) { + return (ReactiveWrappers.isAvailable() ? filter(repositoryConfigurations, loader) : repositoryConfigurations); + } - return repositoryConfigurations.stream().filter(configuration -> { + /* (non-Javadoc) */ + private Collection> filter( + Collection> repositoryConfigurations, ResourceLoader loader) { - Class repositoryInterface = super.loadRepositoryInterface(configuration, loader); + return repositoryConfigurations.stream().filter( + configuration -> isNonReactiveRepository(configuration, loader)).collect(Collectors.toList()); + } - return !RepositoryType.isReactiveRepository(repositoryInterface); - }).collect(Collectors.toList()); + /* (non-Javadoc) */ + private boolean isNonReactiveRepository(RepositoryConfiguration repositoryConfiguration, ResourceLoader loader) { + return !RepositoryType.isReactiveRepository(loadRepositoryInterface(repositoryConfiguration, loader)); + } + + /** + * TODO replace with {@link org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#loadRepositoryInterface(RepositoryConfiguration, ResourceLoader)} + * Loads the Repository interface specified in the given {@link RepositoryConfiguration} using + * the given {@link ResourceLoader}. + * + * @param configuration must not be {@literal null}. + * @param loader must not be {@literal null}. + * @return the Repository interface. + * @throws InvalidDataAccessApiUsageException if the Repository interface could not loaded. + */ + private Class loadRepositoryInterface(RepositoryConfiguration configuration, ResourceLoader loader) { + try { + return ClassUtils.forName(configuration.getRepositoryInterface(), loader.getClassLoader()); + } + catch (ClassNotFoundException | LinkageError e) { + throw new InvalidDataAccessApiUsageException(String.format( + "Could not find Repository type [%s]", configuration.getRepositoryInterface()), e); } - - return repositoryConfigurations; } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/ReactiveCassandraRepositoryConfigurationExtension.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/ReactiveCassandraRepositoryConfigurationExtension.java index b3dd4e48e..2110978d3 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/ReactiveCassandraRepositoryConfigurationExtension.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/ReactiveCassandraRepositoryConfigurationExtension.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.data.cassandra.repository.config; import java.lang.annotation.Annotation; @@ -21,8 +22,8 @@ import java.util.Collections; import java.util.stream.Collectors; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.io.ResourceLoader; +import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.cassandra.mapping.Table; import org.springframework.data.cassandra.repository.ReactiveCassandraRepository; import org.springframework.data.cassandra.repository.support.ReactiveCassandraRepositoryFactoryBean; @@ -32,6 +33,7 @@ import org.springframework.data.repository.config.RepositoryConfigurationExtensi import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport; import org.springframework.data.repository.config.RepositoryConfigurationSource; import org.springframework.data.repository.config.XmlRepositoryConfigurationSource; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** @@ -42,87 +44,97 @@ import org.springframework.util.StringUtils; */ public class ReactiveCassandraRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport { - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getModuleName() + /** + * @inheritDoc */ @Override public String getModuleName() { return "Reactive Cassandra"; } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getModulePrefix() + /** + * @inheritDoc */ @Override protected String getModulePrefix() { return "cassandra"; } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getRepositoryFactoryClassName() + /** + * @inheritDoc */ @Override public String getRepositoryFactoryClassName() { return ReactiveCassandraRepositoryFactoryBean.class.getName(); } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.XmlRepositoryConfigurationSource) + /** + * @inheritDoc */ @Override public void postProcess(BeanDefinitionBuilder builder, XmlRepositoryConfigurationSource config) {} - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource) + /** + * @inheritDoc */ @Override public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource config) { - AnnotationAttributes attributes = config.getAttributes(); - - String reactiveCassandraTemplateRef = attributes.getString("reactiveCassandraTemplateRef"); + String reactiveCassandraTemplateRef = config.getAttributes().getString("reactiveCassandraTemplateRef"); if (StringUtils.hasText(reactiveCassandraTemplateRef)) { builder.addPropertyReference("reactiveCassandraOperations", reactiveCassandraTemplateRef); } } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getIdentifyingAnnotations() + /** + * @inheritDoc */ @Override protected Collection> getIdentifyingAnnotations() { - return Collections.>singleton(Table.class); + return Collections.singleton(Table.class); } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getIdentifyingTypes() + /** + * @inheritDoc */ @Override protected Collection> getIdentifyingTypes() { - return Collections.>singleton(ReactiveCassandraRepository.class); + return Collections.singleton(ReactiveCassandraRepository.class); } - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getRepositoryConfigurations(T, org.springframework.core.io.ResourceLoader, boolean) + /** + * @inheritDoc */ @Override public Collection> getRepositoryConfigurations( T configSource, ResourceLoader loader, boolean strictMatchesOnly) { - Collection> repositoryConfigurations = super.getRepositoryConfigurations(configSource, - loader, strictMatchesOnly); + Collection> repositoryConfigurations = + super.getRepositoryConfigurations(configSource, loader, strictMatchesOnly); return repositoryConfigurations.stream() - .filter(configuration -> RepositoryType.isReactiveRepository(loadRepositoryInterface(configuration, loader))) - .collect(Collectors.toList()); + .filter(configuration -> RepositoryType.isReactiveRepository(loadRepositoryInterface(configuration, loader))) + .collect(Collectors.toList()); + } + + /** + * TODO replace with {@link org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#loadRepositoryInterface(RepositoryConfiguration, ResourceLoader)} + * Loads the Repository interface specified in the given {@link RepositoryConfiguration} using + * the given {@link ResourceLoader}. + * + * @param configuration must not be {@literal null}. + * @param loader must not be {@literal null}. + * @return the Repository interface. + * @throws InvalidDataAccessApiUsageException if the Repository interface could not loaded. + */ + private Class loadRepositoryInterface(RepositoryConfiguration configuration, ResourceLoader loader) { + try { + return ClassUtils.forName(configuration.getRepositoryInterface(), loader.getClassLoader()); + } + catch (ClassNotFoundException | LinkageError e) { + throw new InvalidDataAccessApiUsageException(String.format( + "Could not find Repository type [%s]", configuration.getRepositoryInterface()), e); + } } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/RepositoryType.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/RepositoryType.java index 530c8844c..b8949178a 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/RepositoryType.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/RepositoryType.java @@ -44,7 +44,7 @@ class RepositoryType { */ public static boolean isReactiveRepository(Class repositoryInterface) { - if (!ReactiveWrappers.isAvailable()) { + if (repositoryInterface == null || !ReactiveWrappers.isAvailable()) { return false; } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/ReactiveCassandraRepositoryFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/ReactiveCassandraRepositoryFactory.java index a67acafc7..d6a0b2d73 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/ReactiveCassandraRepositoryFactory.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/ReactiveCassandraRepositoryFactory.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.data.cassandra.repository.support; import java.io.Serializable; @@ -20,8 +21,6 @@ import java.lang.reflect.Method; import java.util.Arrays; import org.reactivestreams.Publisher; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.cassandra.core.ReactiveCassandraOperations; import org.springframework.data.cassandra.mapping.CassandraMappingContext; @@ -58,7 +57,6 @@ public class ReactiveCassandraRepositoryFactory extends RepositoryFactorySupport private final ReactiveCassandraOperations operations; private final CassandraMappingContext mappingContext; - private final ConversionService conversionService; /** * Creates a new {@link ReactiveCassandraRepositoryFactory} with the given {@link ReactiveCassandraOperations}. @@ -71,12 +69,6 @@ public class ReactiveCassandraRepositoryFactory extends RepositoryFactorySupport this.operations = cassandraOperations; this.mappingContext = cassandraOperations.getConverter().getMappingContext(); - - DefaultConversionService conversionService = new DefaultConversionService(); - ReactiveWrapperConverters.registerConvertersIn(conversionService); - - this.conversionService = conversionService; - setConversionService(conversionService); } /* @@ -95,8 +87,8 @@ public class ReactiveCassandraRepositoryFactory extends RepositoryFactorySupport @Override protected Object getTargetRepository(RepositoryInformation information) { - CassandraEntityInformation entityInformation = getEntityInformation(information.getDomainType(), - information); + CassandraEntityInformation entityInformation = + getEntityInformation(information.getDomainType()); return getTargetRepositoryViaReflection(information, entityInformation, operations); } @@ -107,7 +99,7 @@ public class ReactiveCassandraRepositoryFactory extends RepositoryFactorySupport */ @Override protected QueryLookupStrategy getQueryLookupStrategy(Key key, EvaluationContextProvider evaluationContextProvider) { - return new CassandraQueryLookupStrategy(operations, evaluationContextProvider, mappingContext, conversionService); + return new CassandraQueryLookupStrategy(operations, evaluationContextProvider, mappingContext); } /* @@ -161,23 +153,16 @@ public class ReactiveCassandraRepositoryFactory extends RepositoryFactorySupport * (non-Javadoc) * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class) */ - public CassandraEntityInformation getEntityInformation(Class domainClass) { - return getEntityInformation(domainClass, null); - } - @SuppressWarnings("unchecked") - private CassandraEntityInformation getEntityInformation(Class domainClass, - RepositoryInformation information) { - + public CassandraEntityInformation getEntityInformation(Class domainClass) { CassandraPersistentEntity entity = mappingContext.getPersistentEntity(domainClass); if (entity == null) { throw new MappingException( - String.format("Could not lookup mapping metadata for domain class %s!", domainClass.getName())); + String.format("Could not lookup mapping metadata for domain class %s!", domainClass.getName())); } - return new MappingCassandraEntityInformation((CassandraPersistentEntity) entity, - operations.getConverter()); + return new MappingCassandraEntityInformation<>((CassandraPersistentEntity) entity, operations.getConverter()); } /** @@ -191,16 +176,13 @@ public class ReactiveCassandraRepositoryFactory extends RepositoryFactorySupport private final EvaluationContextProvider evaluationContextProvider; private final ReactiveCassandraOperations operations; private final CassandraMappingContext mappingContext; - private final ConversionService conversionService; CassandraQueryLookupStrategy(ReactiveCassandraOperations operations, - EvaluationContextProvider evaluationContextProvider, CassandraMappingContext mappingContext, - ConversionService conversionService) { + EvaluationContextProvider evaluationContextProvider, CassandraMappingContext mappingContext) { this.evaluationContextProvider = evaluationContextProvider; this.operations = operations; this.mappingContext = mappingContext; - this.conversionService = conversionService; } /*