DATACASS-91 - ready to test multiple base package entity scanning

This commit is contained in:
Matthew Adams
2014-02-10 18:02:47 -06:00
parent 11f6156a70
commit f451050a15
23 changed files with 509 additions and 160 deletions

View File

@@ -22,7 +22,7 @@ package org.springframework.cassandra.config.xml;
*/
public interface DefaultBeanNames {
public static final String CLUSTER = "cassandra-cluster";
public static final String SESSION = "cassandra-session";
public static final String TEMPLATE = "cql-template";
public static final String CLUSTER = "cassandraCluster";
public static final String SESSION = "cassandraSession";
public static final String TEMPLATE = "cqlTemplate";
}

View File

@@ -10,69 +10,66 @@
location="classpath:/org/springframework/cassandra/test/integration/config/xml/ppncxct.properties" />
<bean id="authProvider" class="com.datastax.driver.core.sasl.DseAuthProvider" />
<bean id="loadBalancingPolicy" class="com.datastax.driver.core.policies.DCAwareRoundRobinPolicy">
<bean id="loadBalancingPolicy"
class="com.datastax.driver.core.policies.DCAwareRoundRobinPolicy">
<constructor-arg name="localDc" value="${lb.policy.dcAware.localDc}" />
<constructor-arg name="usedHostsPerRemoteDc" value="${lb.policy.dcAware.remoteHosts}" />
<constructor-arg name="usedHostsPerRemoteDc"
value="${lb.policy.dcAware.remoteHosts}" />
</bean>
<bean id="reconnectionPolicy" class="com.datastax.driver.core.policies.ConstantReconnectionPolicy">
<constructor-arg name="constantDelayMs" value="${cluster.reconnection.delayMillis}"/>
<bean id="reconnectionPolicy"
class="com.datastax.driver.core.policies.ConstantReconnectionPolicy">
<constructor-arg name="constantDelayMs"
value="${cluster.reconnection.delayMillis}" />
</bean>
<bean id="retryPolicy" class="com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy" />
<bean id="hostStateListener" class="org.springframework.cassandra.test.integration.config.xml.TestHostStateListener"/>
<bean id="latencyTracker" class="org.springframework.cassandra.test.integration.config.xml.TestLatencyTracker"/>
<bean id="retryPolicy"
class="com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy" />
<cassandra:cluster id="cassandra-cluster"
contact-points="${cluster.contactPoints}" port="${cluster.port}"
compression="${cluster.compression}" auth-info-provider-ref="authProvider"
load-balancing-policy-ref="loadBalancingPolicy" username="${auth.username}" password="${auth.password}"
<bean id="hostStateListener"
class="org.springframework.cassandra.test.integration.config.xml.TestHostStateListener" />
<bean id="latencyTracker"
class="org.springframework.cassandra.test.integration.config.xml.TestLatencyTracker" />
<cassandra:cluster contact-points="${cluster.contactPoints}"
port="${cluster.port}" compression="${cluster.compression}"
auth-info-provider-ref="authProvider" load-balancing-policy-ref="loadBalancingPolicy"
username="${auth.username}" password="${auth.password}"
deferred-initialization="${cluster.deferredInit}" metrics-enabled="${cluster.metricsEnabled}"
jmx-reporting-enabled="${cluster.jmxReportingEnabled}"
reconnection-policy-ref="reconnectionPolicy"
retry-policy-ref="retryPolicy"
host-state-listener-ref="hostStateListener"
latency-tracker-ref="latencyTracker">
<cassandra:local-pooling-options
reconnection-policy-ref="reconnectionPolicy" retry-policy-ref="retryPolicy"
host-state-listener-ref="hostStateListener" latency-tracker-ref="latencyTracker">
<cassandra:local-pooling-options
min-simultaneous-requests="${local.min.requests}"
max-simultaneous-requests="${local.max.requests}"
core-connections="${local.core.connections}"
max-connections="${local.max.connections}"
/>
<cassandra:remote-pooling-options
max-simultaneous-requests="${local.max.requests}" core-connections="${local.core.connections}"
max-connections="${local.max.connections}" />
<cassandra:remote-pooling-options
min-simultaneous-requests="${remote.min.requests}"
max-simultaneous-requests="${remote.max.requests}"
core-connections="${remote.core.connections}"
max-connections="${remote.max.connections}"
/>
<cassandra:socket-options
connect-timeout-millis="${socket.connectTimeoutMillis}"
keep-alive="${socket.keepAlive}"
read-timeout-millis="${socket.readTimeoutMillis}"
reuse-address="${socket.reuseAddress}"
so-linger="${socket.soLinger}"
tcp-no-delay="${socket.tcpNoDelay}"
receive-buffer-size="${socket.receiveBufferSize}"
send-buffer-size="${socket.sendBufferSize}"
/>
<cassandra:keyspace name="${keyspace.name}" action="${keyspace.action}"/>
<cassandra:keyspace name="Foo123" action="CREATE_DROP" durable-writes="true">
max-simultaneous-requests="${remote.max.requests}" core-connections="${remote.core.connections}"
max-connections="${remote.max.connections}" />
<cassandra:socket-options
connect-timeout-millis="${socket.connectTimeoutMillis}" keep-alive="${socket.keepAlive}"
read-timeout-millis="${socket.readTimeoutMillis}" reuse-address="${socket.reuseAddress}"
so-linger="${socket.soLinger}" tcp-no-delay="${socket.tcpNoDelay}"
receive-buffer-size="${socket.receiveBufferSize}" send-buffer-size="${socket.sendBufferSize}" />
<cassandra:keyspace name="${keyspace.name}" action="${keyspace.action}" />
<cassandra:keyspace name="Foo123" action="CREATE_DROP"
durable-writes="true">
<cassandra:replication class="NETWORK_TOPOLOGY_STRATEGY">
<cassandra:data-center replication-factor="${dc1.rf}" name="${dc1.name}"/>
<cassandra:data-center replication-factor="${dc1.rf}" name="${dc2.name}"/>
<cassandra:data-center replication-factor="${dc1.rf}"
name="${dc1.name}" />
<cassandra:data-center replication-factor="${dc1.rf}"
name="${dc2.name}" />
</cassandra:replication>
</cassandra:keyspace>
</cassandra:cluster>
<cassandra:session id="cassandra-session"
keyspace-name="system">
</cassandra:session>
<cassandra:session keyspace-name="system" />
<bean id="cassandraTemplate" class="org.springframework.cassandra.core.CqlTemplate">
<constructor-arg ref="cassandra-session" />
<constructor-arg ref="cassandraSession" />
</bean>
</beans>

View File

@@ -9,8 +9,8 @@
<context:property-placeholder
location="classpath:org.springframework.cassandra.test.integration.support.SpringCassandraBuildProperties.properties" />
<cassandra:cluster id="cassandra-cluster"
contact-points="localhost" port="${build.cassandra.native_transport_port}">
<cassandra:cluster contact-points="localhost"
port="${build.cassandra.native_transport_port}">
<cassandra:local-pooling-options
min-simultaneous-requests="25" max-simultaneous-requests="100"
core-connections="2" max-connections="8" />
@@ -18,16 +18,15 @@
min-simultaneous-requests="25" max-simultaneous-requests="100"
core-connections="1" max-connections="2" />
<cassandra:socket-options
connect-timeout-millis="5000" keep-alive="true" read-timeout-millis="60000" reuse-address="true"
so-linger="60" tcp-no-delay="true" receive-buffer-size="65536"
send-buffer-size="65536" />
connect-timeout-millis="5000" keep-alive="true" read-timeout-millis="60000"
reuse-address="true" so-linger="60" tcp-no-delay="true"
receive-buffer-size="65536" send-buffer-size="65536" />
</cassandra:cluster>
<cassandra:session id="cassandra-session"
keyspace-name="xmlconfigtest" />
<cassandra:session keyspace-name="xmlconfigtest" />
<bean id="cassandraTemplate" class="org.springframework.cassandra.core.CqlTemplate">
<constructor-arg ref="cassandra-session" />
<constructor-arg ref="cassandraSession" />
</bean>
</beans>

View File

@@ -0,0 +1,46 @@
package org.springframework.data.cassandra.config;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext;
public class CassandraDataCassandraMappingContextFactoryBean implements FactoryBean<CassandraMappingContext>,
InitializingBean {
protected Set<String> basePackages = new HashSet<String>();
@Override
public void afterPropertiesSet() throws Exception {
}
@Override
public CassandraMappingContext getObject() throws Exception {
DefaultCassandraMappingContext cmc = new DefaultCassandraMappingContext();
cmc.setInitialEntitySet(new CassandraEntityClassScanner(basePackages).scanForEntityClasses());
return cmc;
}
@Override
public Class<?> getObjectType() {
return CassandraMappingContext.class;
}
@Override
public boolean isSingleton() {
return true;
}
public Set<String> getBasePackages() {
return basePackages;
}
public void setBasePackages(Set<String> basePackages) {
this.basePackages = basePackages;
}
}

View File

@@ -0,0 +1,49 @@
package org.springframework.data.cassandra.config;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.util.Assert;
public class CassandraDataMappingConverterFactoryBean implements FactoryBean<CassandraConverter>, InitializingBean {
protected CassandraMappingContext mappingContext;
protected Set<String> basePackages = new HashSet<String>();
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(mappingContext);
Assert.notNull(basePackages);
}
@Override
public CassandraConverter getObject() throws Exception {
return new MappingCassandraConverter(mappingContext);
}
@Override
public Class<?> getObjectType() {
return CassandraConverter.class;
}
@Override
public boolean isSingleton() {
return true;
}
public CassandraMappingContext getMappingContext() {
return mappingContext;
}
public void setMappingContext(CassandraMappingContext mappingContext) {
Assert.notNull(mappingContext);
this.mappingContext = mappingContext;
}
}

View File

@@ -0,0 +1,110 @@
package org.springframework.data.cassandra.config;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.cassandra.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Scans packages for Cassandra entities.
*
* @author Matthew T. Adams
*/
public class CassandraEntityClassScanner {
protected Set<String> entityBasePackages = new HashSet<String>();
protected Set<Class<?>> entityBasePackageClasses = new HashSet<Class<?>>();
protected ClassLoader beanClassLoader;
public CassandraEntityClassScanner() {
}
public CassandraEntityClassScanner(Collection<String> entityBasePackages) {
this(entityBasePackages, null);
}
public CassandraEntityClassScanner(Collection<String> entityBasePackages,
Collection<Class<?>> entityBasePackageClasses) {
setEntityBasePackages(entityBasePackages);
setEntityBasePackageClasses(entityBasePackageClasses);
}
public Set<String> getEntityBasePackages() {
return Collections.unmodifiableSet(entityBasePackages);
}
public void setEntityBasePackages(Collection<String> entityBasePackages) {
this.entityBasePackages = entityBasePackages == null ? new HashSet<String>() : new HashSet<String>(
entityBasePackages);
}
public Set<Class<?>> getEntityBasePackageClasses() {
return Collections.unmodifiableSet(entityBasePackageClasses);
}
public void setEntityBasePackageClasses(Collection<Class<?>> entityBasePackageClasses) {
this.entityBasePackageClasses = entityBasePackageClasses == null ? new HashSet<Class<?>>() : new HashSet<Class<?>>(
entityBasePackageClasses);
}
public void setBeanClassLoader(ClassLoader beanClassLoader) {
this.beanClassLoader = beanClassLoader;
}
/**
* Scans the mapping base package for entity classes annotated with {@link Table} or {@link Persistent}.
*
* @see #getEntityBasePackages()
* @return <code>Set&lt;Class&lt;?&gt;&gt;</code> representing the annotated entity classes found.
* @throws ClassNotFoundException
*/
public Set<Class<?>> scanForEntityClasses() throws ClassNotFoundException {
Set<Class<?>> classes = new HashSet<Class<?>>();
for (String basePackage : getEntityBasePackages()) {
classes.addAll(scanBasePackageForEntities(basePackage));
}
for (Class<?> basePackageClass : getEntityBasePackageClasses()) {
classes.addAll(scanBasePackageForEntities(basePackageClass.getPackage().getName()));
}
return classes;
}
protected Set<Class<?>> scanBasePackageForEntities(String basePackage) throws ClassNotFoundException {
HashSet<Class<?>> classes = new HashSet<Class<?>>();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
for (Class<? extends Annotation> annoClass : getEntityAnnotations()) {
componentProvider.addIncludeFilter(new AnnotationTypeFilter(annoClass));
}
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
classes.add(ClassUtils.forName(candidate.getBeanClassName(), beanClassLoader));
}
}
return classes;
}
@SuppressWarnings("unchecked")
public Class<? extends Annotation>[] getEntityAnnotations() {
return new Class[] { Table.class, Persistent.class, PrimaryKeyClass.class };
}
}

View File

@@ -4,6 +4,7 @@ import org.springframework.cassandra.config.xml.DefaultBeanNames;
public interface DefaultDataBeanNames extends DefaultBeanNames {
public static final String DATA_TEMPLATE = "cassandra-template";
public static final String CONVERTER = "cassandra-converter";
public static final String DATA_TEMPLATE = "cassandraTemplate";
public static final String CONVERTER = "cassandraConverter";
public static final String MAPPING_CONTEXT = "cassandra-mapping";
}

View File

@@ -15,18 +15,15 @@
*/
package org.springframework.data.cassandra.config.java;
import java.util.HashSet;
import java.util.Arrays;
import java.util.Set;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.cassandra.config.java.AbstractClusterConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.cassandra.config.CassandraDataSessionFactoryBean;
import org.springframework.data.cassandra.config.CassandraEntityClassScanner;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
@@ -35,11 +32,8 @@ import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext;
import org.springframework.data.cassandra.mapping.Mapping;
import org.springframework.data.cassandra.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Base class for Spring Data Cassandra configuration using JavaConfig.
@@ -64,11 +58,11 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
}
/**
* The base package to scan for entities annotated with {@link Table} annotations. By default, returns the package
* name of {@literal this} (<code>this.getClass().getPackage().getName()</code>).
* The base packages to scan for entities annotated with {@link Table} annotations. By default, returns the package
* name of {@literal this} (<code>this.getClass().getPackage().getName()</code>). This method must never return null.
*/
public String getEntityBasePackage() {
return getClass().getPackage().getName();
public String[] getMappingBasePackages() {
return new String[] { getClass().getPackage().getName() };
}
@Bean
@@ -118,46 +112,27 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
*/
@Bean
public CassandraConverter converter() throws ClassNotFoundException {
MappingCassandraConverter converter = new MappingCassandraConverter(cassandraMappingContext());
converter.setBeanClassLoader(beanClassLoader);
return converter;
return new MappingCassandraConverter(cassandraMappingContext());
}
/**
* Scans the mapping base package for entity classes annotated with {@link Table} or {@link Persistent}.
* Scans the mapping base package for entity classes.
*
* @see #getEntityBasePackage()
* @see #getMappingBasePackages()
* @see #getEntityScanner()
* @return <code>Set&lt;Class&lt;?&gt;&gt;</code> representing the annotated entity classes found.
* @throws ClassNotFoundException
*/
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
String basePackage = getEntityBasePackage();
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
CassandraEntityClassScanner entityScanner = getEntityScanner();
entityScanner.setEntityBasePackages(Arrays.asList(getMappingBasePackages()));
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Table.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(PrimaryKeyClass.class));
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
Class<?> clazz = ClassUtils.forName(candidate.getBeanClassName(), beanClassLoader);
initialEntitySet.add(clazz);
}
}
processMappingOverrides(initialEntitySet);
return initialEntitySet;
return entityScanner.scanForEntityClasses();
}
protected void processMappingOverrides(Set<Class<?>> entityTypes) {
// TODO: search for external entity mapping info (xml/properties/yaml/etc) here & update this.mapping
// similar to JPA's or JDO's external metadata search algorithms
public CassandraEntityClassScanner getEntityScanner() {
return new CassandraEntityClassScanner();
}
@Override

View File

@@ -0,0 +1,52 @@
package org.springframework.data.cassandra.config.xml;
import java.util.Set;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.cassandra.config.CassandraDataCassandraMappingContextFactoryBean;
import org.springframework.data.cassandra.config.DefaultDataBeanNames;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Spring Data Cassandra XML namespace parser for the &lt;mapping-context&gt; element.
*
* @author Matthew T. Adams
*/
public class CassandraDataCassandraMappingContextParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return CassandraDataCassandraMappingContextFactoryBean.class;
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : DefaultDataBeanNames.MAPPING_CONTEXT;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
parseBasePackagesAttribute(element, parserContext, builder);
}
protected void parseBasePackagesAttribute(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String basePackages = element.getAttribute("base-packages");
if (!StringUtils.hasText(basePackages)) {
return;
}
Set<String> basePackageSet = StringUtils.commaDelimitedListToSet(basePackages);
builder.addPropertyValue("basePackages", basePackageSet);
}
}

View File

@@ -0,0 +1,62 @@
package org.springframework.data.cassandra.config.xml;
import java.util.Set;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.cassandra.config.CassandraDataMappingConverterFactoryBean;
import org.springframework.data.cassandra.config.DefaultDataBeanNames;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Spring Data Cassandra XML namespace parser for the &lt;mapping-converter&gt; element.
*
* @author Matthew T. Adams
*/
public class CassandraDataMappingCassandraConverterParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return CassandraDataMappingConverterFactoryBean.class;
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : DefaultDataBeanNames.CONVERTER;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
parseMappingContextAttribute(element, parserContext, builder);
parseBasePackagesAttribute(element, parserContext, builder);
}
protected void parseMappingContextAttribute(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder) {
String mappingContextRef = element.getAttribute("mapping-context-ref");
if (!StringUtils.hasText(mappingContextRef)) {
mappingContextRef = DefaultDataBeanNames.MAPPING_CONTEXT;
}
builder.addPropertyReference("mappingContext", mappingContextRef);
}
protected void parseBasePackagesAttribute(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String basePackages = element.getAttribute("base-packages");
if (!StringUtils.hasText(basePackages)) {
return;
}
Set<String> basePackageSet = StringUtils.commaDelimitedListToSet(basePackages);
}
}

View File

@@ -36,5 +36,7 @@ public class CassandraDataNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("cluster", new CassandraDataClusterParser());
registerBeanDefinitionParser("session", new CassandraDataSessionParser());
registerBeanDefinitionParser("template", new CassandraDataTemplateParser());
registerBeanDefinitionParser("mapping-converter", new CassandraDataMappingCassandraConverterParser());
registerBeanDefinitionParser("mapping-context", new CassandraDataCassandraMappingContextParser());
}
}

View File

@@ -45,6 +45,15 @@ public class CassandraDataSessionParser extends CassandraSessionParser {
}
}
@Override
protected void setDefaultProperties(BeanDefinitionBuilder builder) {
super.setDefaultProperties(builder);
addRequiredPropertyReference(builder, "converter", DefaultDataBeanNames.CONVERTER);
addRequiredPropertyReference(builder, "schemaAction", SchemaAction.NONE.name());
}
@Override
protected void parseUnhandledElement(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {

View File

@@ -52,6 +52,8 @@ public class DefaultCassandraMappingContext extends
CassandraMappingContext, ApplicationContextAware {
protected ApplicationContext context;
// useful caches
protected Map<String, Set<CassandraPersistentEntity<?>>> entitySetsByTableName = new HashMap<String, Set<CassandraPersistentEntity<?>>>();
protected Set<CassandraPersistentEntity<?>> nonPrimaryKeyEntities = new HashSet<CassandraPersistentEntity<?>>();
protected Set<CassandraPersistentEntity<?>> primaryKeyEntities = new HashSet<CassandraPersistentEntity<?>>();
@@ -63,6 +65,20 @@ public class DefaultCassandraMappingContext extends
setSimpleTypeHolder(new CassandraSimpleTypeHolder());
}
@Override
public void initialize() {
super.initialize();
processMappingOverrides();
}
protected void processMappingOverrides() {
// TODO: search for external entity mapping info (xml/properties/yaml/etc) here & update this.mapping
// similar to JPA's or JDO's external metadata search algorithms
}
@Override
public Collection<CassandraPersistentEntity<?>> getPersistentEntities() {
return getPersistentEntities(false);

View File

@@ -18,6 +18,7 @@ package org.springframework.data.cassandra.repository.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.cassandra.config.xml.ParsingUtils;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.data.cassandra.config.DefaultDataBeanNames;
import org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
@@ -52,7 +53,7 @@ public class CassandraRepositoryConfigurationExtension extends RepositoryConfigu
Element element = config.getElement();
ParsingUtils.addOptionalPropertyReference(builder, "cassandraTemplate", element, CASSANDRA_TEMPLATE_REF,
"cassandra-template");
DefaultDataBeanNames.TEMPLATE);
}
@Override

View File

@@ -482,7 +482,7 @@ The name of a Cassandra Keyspace. No default; for the system keyspace, use the
use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The reference to a CassandraConverter; default is "cassandra-converter".
The reference to a CassandraConverter; default is "cassandraConverter".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -500,7 +500,7 @@ The schema action to perform; default is NONE.
<xsd:attribute name="id" type="xsd:ID" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the template; default is "cassandra-template".
The name of the template; default is "cassandraTemplate".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -515,7 +515,7 @@ The reference to a Cassandra session; default is "cassandra-session".
use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The reference to a CassandraConverter; default is "cassandra-converter".
The reference to a CassandraConverter; default is "cassandraConverter".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -676,11 +676,10 @@ Table name override.
</xsd:simpleType>
<xsd:attributeGroup name="cassandra-repository-attributes">
<xsd:attribute name="cassandra-template-ref" type="cassandraTemplateRef"
default="cassandra-template">
<xsd:attribute name="cassandra-template-ref" type="cassandraTemplateRef">
<xsd:annotation>
<xsd:documentation><![CDATA[
The reference to a cassandraTemplate. Will default to 'cassandra-template'.
The reference to a cassandraTemplate. Will default to 'cassandraTemplate'.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -696,4 +695,61 @@ The reference to a cassandraTemplate. Will default to 'cassandra-template'.
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="mapping-context">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines a CassandraMappingContext for holding rich entity mapping information.
]]></xsd:documentation>
<xsd:appinfo>
<tool:exports
type="org.springframework.data.cassandra.mapping.CassandraMappingContext" />
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="base-packages" type="xsd:string"
use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The comma-delimited base packages in which to scan for entities and their mapping information.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="mapping-converter">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines a CassandraConverter for getting rich mapping functionality.
]]></xsd:documentation>
<xsd:appinfo>
<tool:exports
type="org.springframework.data.cassandra.convert.CassandraConverter" />
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="mapping-context-ref" type="mappingContextRef"
use="optional">
<xsd:annotation>
<xsd:documentation
source="org.springframework.data.mapping.model.MappingContext"><![CDATA[
The reference to a MappingContext. Will default to 'mapping-context'.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="mappingContextRef">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to
type="org.springframework.data.cassandra.mapping.CassandraMappingContext" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:schema>

View File

@@ -69,8 +69,8 @@ public class CommentRepositoryJavaConfigIntegrationTests extends AbstractSpringD
}
@Override
public String getEntityBasePackage() {
return Comment.class.getPackage().getName();
public String[] getMappingBasePackages() {
return new String[] { Comment.class.getPackage().getName() };
}
}

View File

@@ -68,8 +68,8 @@ public class UserRepositoryJavaConfigIntegrationTests extends AbstractSpringData
}
@Override
public String getEntityBasePackage() {
return User.class.getPackage().getName();
public String[] getMappingBasePackages() {
return new String[] { User.class.getPackage().getName() };
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.data.cassandra.test.integration.template;
import static org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification.createKeyspace;
import static org.springframework.cassandra.core.keyspace.DropTableSpecification.dropTable;
import java.io.IOException;
import java.util.ArrayList;
@@ -24,30 +23,22 @@ import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.core.ConsistencyLevel;
import org.springframework.cassandra.core.QueryOptions;
import org.springframework.cassandra.core.RetryPolicy;
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.test.integration.simpletons.Book;
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.cassandra.test.integration.support.TestConfig;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
@@ -75,8 +66,8 @@ public class CassandraDataOperationsTest extends AbstractSpringDataEmbeddedCassa
}
@Override
public String getEntityBasePackage() {
return Book.class.getPackage().getName();
public String[] getMappingBasePackages() {
return new String[] { Book.class.getPackage().getName() };
}
}

View File

@@ -2,24 +2,23 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/data/cassandra http://www.springframework.org/schema/data/cassandra/spring-cassandra-1.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<import resource="classpath:/spring-data-cassandra-basic.xml" />
<cassandra:cluster id="cassandra-cluster"
port="${cassandra.native_transport_port}">
<cassandra:cluster port="${cassandra.native_transport_port}">
<cassandra:keyspace name="CommentRepositoryXmlConfigIntegrationTests"
action="CREATE" durable-writes="true">
</cassandra:keyspace>
</cassandra:cluster>
<cassandra:session id="cassandra-session"
cluster-ref="cassandra-cluster" keyspace-name="CommentRepositoryXmlConfigIntegrationTests"
cassandra-converter-ref="cassandra-converter" schema-action="CREATE">
<cassandra:session keyspace-name="CommentRepositoryXmlConfigIntegrationTests"
schema-action="CREATE">
<cassandra:mapping>
<cassandra:entity
class="org.springframework.data.cassandra.test.integration.composites.Comment">

View File

@@ -11,9 +11,8 @@
<context:property-placeholder
location="classpath:/org/springframework/data/cassandra/test/integration/config/cassandra.properties" />
<cass:cluster id="cassandra-cluster"
contact-points="${cassandra.contactPoints}" port="${cassandra.native_transport_port}"
compression="SNAPPY">
<cass:cluster contact-points="${cassandra.contactPoints}"
port="${cassandra.native_transport_port}" compression="SNAPPY">
<cass:local-pooling-options
min-simultaneous-requests="25" max-simultaneous-requests="100"
core-connections="2" max-connections="8" />
@@ -27,21 +26,13 @@
durable-writes="true" />
</cass:cluster>
<!-- TODO: not require that this bean be defined -->
<bean id="cassandra-mapping"
class="org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext"/>
<!-- TODO: not require that these beans be defined -->
<cass:mapping-context/>
<cass:mapping-converter />
<!-- TODO: not require that this bean be defined -->
<bean id="cassandra-converter"
class="org.springframework.data.cassandra.convert.MappingCassandraConverter">
<constructor-arg ref="cassandra-mapping" />
</bean>
<cass:session keyspace-name="${cassandra.keyspace}"
schema-action="NONE" />
<cass:session id="cassandra-session" keyspace-name="${cassandra.keyspace}"
schema-action="NONE" cluster-ref="cassandra-cluster"
cassandra-converter-ref="cassandra-converter">
</cass:session>
<cass:template session-ref="cassandra-session" />
<cass:template />
</beans>

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/data/cassandra http://www.springframework.org/schema/data/cassandra/spring-cassandra-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
@@ -11,17 +12,14 @@
<import resource="classpath:/spring-data-cassandra-basic.xml" />
<cassandra:cluster id="cassandra-cluster"
port="${cassandra.native_transport_port}">
<cassandra:cluster port="${cassandra.native_transport_port}">
<cassandra:keyspace name="UserRepositoryXmlConfigIntegrationTests"
action="CREATE" durable-writes="true">
</cassandra:keyspace>
</cassandra:cluster>
<cassandra:session id="cassandra-session"
cluster-ref="cassandra-cluster" keyspace-name="UserRepositoryXmlConfigIntegrationTests"
cassandra-converter-ref="cassandra-converter" schema-action="CREATE">
<cassandra:session keyspace-name="UserRepositoryXmlConfigIntegrationTests"
schema-action="CREATE">
<cassandra:mapping>
<cassandra:entity
class="org.springframework.data.cassandra.test.integration.repository.User">

View File

@@ -10,15 +10,10 @@
<context:property-placeholder
location="classpath:/spring-data-cassandra-build.properties" />
<bean id="cassandra-mapping"
class="org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext" />
<cassandra:mapping-context />
<bean id="cassandra-converter"
class="org.springframework.data.cassandra.convert.MappingCassandraConverter">
<constructor-arg ref="cassandra-mapping" />
</bean>
<cassandra:mapping-converter />
<cassandra:template id="cassandra-template"
cassandra-converter-ref="cassandra-converter" session-ref="cassandra-session" />
<cassandra:template />
</beans>