diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/BeanDefinitionUtils.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/BeanDefinitionUtils.java index 75282fb5a..7552d7447 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/BeanDefinitionUtils.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/BeanDefinitionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors + * Copyright 2013-2016 the original author or authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,15 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.util.StringUtils; +/** + * Utilities to lookup {@link BeanDefinition bean definitions} for a {@link ListableBeanFactory} and to conditionally + * register {@link BeanDefinition bean definitions}. + * + * @author Matthew Adams + * @author Mark Paluch + * @deprecated Will be removed with the next major release. + */ +@Deprecated public class BeanDefinitionUtils { /** diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraMappingBeanFactoryPostProcessor.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraMappingBeanFactoryPostProcessor.java index b45895035..be7c97128 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraMappingBeanFactoryPostProcessor.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraMappingBeanFactoryPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors + * Copyright 2013-2016 the original author or authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,34 +15,38 @@ */ package org.springframework.data.cassandra.config; -import static org.springframework.data.cassandra.config.BeanDefinitionUtils.getBeanDefinitionsOfType; +import static org.springframework.data.cassandra.config.BeanDefinitionUtils.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import org.springframework.beans.BeansException; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.data.cassandra.convert.CassandraConverter; import org.springframework.data.cassandra.convert.MappingCassandraConverter; import org.springframework.data.cassandra.core.CassandraOperations; import org.springframework.data.cassandra.core.CassandraTemplate; -import org.springframework.data.cassandra.mapping.CassandraMappingContext; import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext; +import org.springframework.data.cassandra.mapping.CassandraMappingContext; import org.springframework.util.StringUtils; import com.datastax.driver.core.Session; /** - * {@link BeanDefinitionRegistryPostProcessor} that does its best to register any missing Spring Data Cassandra beans - * that can be defaulted. Specifically, it attempts to create default bean definitions for the following required - * interface types via their default implementation types: + * {@link BeanFactoryPostProcessor} that does its best to register any missing Spring Data Cassandra beans that can be + * defaulted. Specifically, it attempts to create default bean definitions for the following required interface types + * via their default implementation types: * *

* If there are multiple definitions for any type that another type depends on, an {@link IllegalStateException} is @@ -57,59 +61,53 @@ import com.datastax.driver.core.Session; * It requires that a single {@link Session} or {@link CassandraSessionFactoryBean} definition be present. As described * above, multiple {@link Session} definitions, multiple {@link CassandraSessionFactoryBean} definitions, or both a * {@link Session} and {@link CassandraSessionFactoryBean} will cause an {@link IllegalStateException} to be thrown. - * + * * @author Matthew T. Adams + * @author Mark Paluch + * @deprecated Will be removed with the next major release. Spring Data Cassandra is not the best place to apply + * configuration defaults. */ -public class CassandraMappingBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor { - - /** - * Does nothing. - */ - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {} +@Deprecated +public class CassandraMappingBeanFactoryPostProcessor implements BeanFactoryPostProcessor { /** * Ensures that {@link BeanDefinition}s for a {@link CassandraMappingContext} and a {@link CassandraConverter} exist. */ @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException { - if (!(registry instanceof ListableBeanFactory)) { + if (!(factory instanceof BeanDefinitionRegistry)) { return; } - ListableBeanFactory factory = (ListableBeanFactory) registry; - registerMissingDefaultableBeanDefinitions(registry, factory); + registerMissingDefaultableBeanDefinitions((BeanDefinitionRegistry) factory, factory); } - protected void registerMissingDefaultableBeanDefinitions(BeanDefinitionRegistry registry, ListableBeanFactory factory) { + private void registerMissingDefaultableBeanDefinitions(BeanDefinitionRegistry registry, ListableBeanFactory factory) { // see if any template definitions exist, which requires a converter, which requires a mapping context BeanDefinitionHolder[] templateBeans = getBeanDefinitionsOfType(registry, factory, CassandraOperations.class, true, - false); + true); if (templateBeans.length >= 1) { return; } // need a session & converter for the default template - // see if an actual Session definition exists String sessionBeanName = findSessionBeanName(registry, factory); // see if any converter bean definitions exist, which requires a mapping context - BeanDefinitionHolder[] converterBeans = getBeanDefinitionsOfType(registry, factory, - MappingCassandraConverter.class, true, false); + BeanDefinitionHolder[] converterBeans = getBeanDefinitionsOfType(registry, factory, MappingCassandraConverter.class, + true, false); + + if (converterBeans.length > 1) { + throw createAmbiguousBeansException(converterBeans.length, CassandraConverter.class, CassandraTemplate.class); + } if (converterBeans.length == 1) { - registerDefaultTemplate(registry, sessionBeanName, converterBeans[0].getBeanName()); return; - } else if (converterBeans.length > 1) { - // then throw, because we need to create a default converter, but we wouldn't know which mapping context to use - throw new IllegalStateException(String.format( - "found %d beans of type [%s] - can't disambiguate for creation of [%s]", converterBeans.length, - CassandraConverter.class.getName(), CassandraTemplate.class.getName())); } // see if any mapping context bean definitions exist @@ -118,84 +116,85 @@ public class CassandraMappingBeanFactoryPostProcessor implements BeanDefinitionR if (contextBeans.length > 1) { // then throw, because we need to create a default converter, but we wouldn't know which mapping context to use - throw new IllegalStateException(String.format( - "found %d beans of type [%s] - can't disambiguate for creation of [%s]", contextBeans.length, - CassandraMappingContext.class.getName(), MappingCassandraConverter.class.getName())); + throw createAmbiguousBeansException(contextBeans.length, MappingCassandraConverter.class, + CassandraMappingContext.class); } // create the mapping context if necessary - BeanDefinitionHolder contextBean = contextBeans.length == 1 ? contextBeans[0] : null; - if (contextBean == null) { - contextBean = regsiterDefaultContext(registry); - } + BeanDefinitionHolder contextBean = contextBeans.length == 1 ? contextBeans[0] : registerDefaultContext(registry); // create the default converter & template bean definitions BeanDefinitionHolder converter = registerDefaultConverter(registry, contextBean.getBeanName()); registerDefaultTemplate(registry, sessionBeanName, converter.getBeanName()); } - public String findSessionBeanName(BeanDefinitionRegistry registry, ListableBeanFactory factory) { + private String findSessionBeanName(BeanDefinitionRegistry registry, ListableBeanFactory factory) { // first, search for any session and session factory beans - BeanDefinitionHolder[] sessionBeans = getBeanDefinitionsOfType(registry, factory, Session.class, true, false); - BeanDefinitionHolder[] sessionFactoryBeans = getBeanDefinitionsOfType(registry, factory, - CassandraSessionFactoryBean.class, true, false); + BeanDefinitionHolder[] sessionBeans = getBeanDefinitionsOfType(registry, factory, Session.class, true, true); - int sessionCount = sessionBeans.length; - int sessionFactoryCount = sessionFactoryBeans.length; - int totalCount = sessionCount + sessionFactoryCount; - - if (totalCount == 0 || totalCount > 1) { // can't create default template -- none or multiple - throw createSessionException(totalCount, Session.class, CassandraSessionFactoryBean.class); - } - - if (sessionCount == 1) { + if (sessionBeans.length == 1) { // can't create default template -- none or multiple return sessionBeans[0].getBeanName(); } - // else it must be the one session factory bean - return sessionFactoryBeans[0].getBeanName(); + + throw createAmbiguousBeansException(sessionBeans.length, CassandraTemplate.class, Session.class, + CassandraSessionFactoryBean.class); } - protected IllegalStateException createSessionException(int beanDefinitionCount, Class... types) { + private IllegalStateException createAmbiguousBeansException(int beanDefinitionCount, Class defaultBeanType, + Class... types) { - return new IllegalStateException(String.format("found %d beans of type%s [%s] - %s for creation of default [%s]", - beanDefinitionCount, beanDefinitionCount == 1 ? "" : "s", StringUtils.arrayToCommaDelimitedString(types), - beanDefinitionCount == 0 ? "need exactly one" : "can't disambiguate", CassandraTemplate.class.getName())); + return new IllegalStateException( + String.format("found %d beans of type%s [%s] - %s for creation of default [%s]", beanDefinitionCount, + beanDefinitionCount == 1 ? "" : "s", StringUtils.collectionToCommaDelimitedString(getNames(types)), + beanDefinitionCount == 0 ? "need exactly one" : "can't disambiguate", defaultBeanType.getName())); } - protected BeanDefinitionHolder regsiterDefaultContext(BeanDefinitionRegistry registry) { + private BeanDefinitionHolder registerDefaultContext(BeanDefinitionRegistry registry) { - BeanDefinitionHolder contextBean = new BeanDefinitionHolder(BeanDefinitionBuilder.genericBeanDefinition( - BasicCassandraMappingContext.class).getBeanDefinition(), DefaultBeanNames.CONTEXT); + BeanDefinitionHolder contextBean = new BeanDefinitionHolder( + BeanDefinitionBuilder.genericBeanDefinition(BasicCassandraMappingContext.class).getBeanDefinition(), + DefaultBeanNames.CONTEXT); registry.registerBeanDefinition(contextBean.getBeanName(), contextBean.getBeanDefinition()); return contextBean; } - public BeanDefinitionHolder registerDefaultConverter(BeanDefinitionRegistry registry, String contextBeanName) { + private BeanDefinitionHolder registerDefaultConverter(BeanDefinitionRegistry registry, String contextBeanName) { - BeanDefinitionBuilder converterBeanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition( - MappingCassandraConverter.class).addConstructorArgReference(contextBeanName); - BeanDefinitionHolder beanDefinition = new BeanDefinitionHolder(converterBeanDefinitionBuilder.getBeanDefinition(), - DefaultBeanNames.CONVERTER); + BeanDefinition beanDefinition = BeanDefinitionBuilder // + .genericBeanDefinition(MappingCassandraConverter.class) // + .addConstructorArgReference(contextBeanName).getBeanDefinition(); - registry.registerBeanDefinition(beanDefinition.getBeanName(), beanDefinition.getBeanDefinition()); + BeanDefinitionHolder converter = new BeanDefinitionHolder(beanDefinition, DefaultBeanNames.CONVERTER); + registry.registerBeanDefinition(converter.getBeanName(), converter.getBeanDefinition()); - return beanDefinition; + return converter; } - public BeanDefinitionHolder registerDefaultTemplate(BeanDefinitionRegistry registry, String sessionBeanName, + private BeanDefinitionHolder registerDefaultTemplate(BeanDefinitionRegistry registry, String sessionBeanName, String converterBeanName) { - BeanDefinitionBuilder templateBeanDefinitionBuilder = BeanDefinitionBuilder - .genericBeanDefinition(CassandraTemplate.class).addConstructorArgReference(sessionBeanName) - .addConstructorArgReference(converterBeanName); - BeanDefinition beanDefinition = templateBeanDefinitionBuilder.getBeanDefinition(); + BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(CassandraTemplate.class) // + .addConstructorArgReference(sessionBeanName) // + .addConstructorArgReference(converterBeanName) // + .getBeanDefinition(); BeanDefinitionHolder template = new BeanDefinitionHolder(beanDefinition, DefaultBeanNames.TEMPLATE); registry.registerBeanDefinition(template.getBeanName(), template.getBeanDefinition()); return template; } + + private Collection getNames(Class[] types) { + + List names = new ArrayList(); + + for (Class type : types) { + names.add(type.getName()); + } + + return names; + } } diff --git a/spring-data-cassandra/src/main/resources/org/springframework/data/cassandra/config/spring-cassandra-1.5.xsd b/spring-data-cassandra/src/main/resources/org/springframework/data/cassandra/config/spring-cassandra-1.5.xsd index 3e21bb326..ce42c76ca 100644 --- a/spring-data-cassandra/src/main/resources/org/springframework/data/cassandra/config/spring-cassandra-1.5.xsd +++ b/spring-data-cassandra/src/main/resources/org/springframework/data/cassandra/config/spring-cassandra-1.5.xsd @@ -775,6 +775,13 @@ Defines a CassandraMappingContext for holding rich entity mapping information. + + + + + { + + @Override + public Class getObjectType() { + return Session.class; + } + + @Override + protected Session createInstance() { + return mock(Session.class); + } + } +} diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/cluster-and-mock-session.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/cluster-and-mock-session.xml new file mode 100644 index 000000000..7f83a5d90 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/cluster-and-mock-session.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/mock-session-converter.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/mock-session-converter.xml new file mode 100644 index 000000000..b1691c37a --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/mock-session-converter.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/mock-session-mapping-converter.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/mock-session-mapping-converter.xml new file mode 100644 index 000000000..1b8c0d71a --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/mock-session-mapping-converter.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-converters.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-converters.xml new file mode 100644 index 000000000..a37e530f4 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-converters.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-mapping-contexts.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-mapping-contexts.xml new file mode 100644 index 000000000..6af65be04 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-mapping-contexts.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-session-factories.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-session-factories.xml new file mode 100644 index 000000000..e6b960786 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-session-factories.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-sessions.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-sessions.xml new file mode 100644 index 000000000..a5c2eebb0 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/multiple-sessions.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/two-keyspaces-namespace.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/two-keyspaces-namespace.xml new file mode 100644 index 000000000..cf0ad849f --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/config/two-keyspaces-namespace.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + +