spring-cassandra now supporting xml config
This commit is contained in:
@@ -18,6 +18,7 @@ package org.springframework.cassandra.config.xml;
|
||||
/**
|
||||
* @author Alex Shvid
|
||||
* @author David Webb
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
public final class BeanNames {
|
||||
|
||||
@@ -27,5 +28,5 @@ public final class BeanNames {
|
||||
public static final String CASSANDRA_CLUSTER = "cassandra-cluster";
|
||||
public static final String CASSANDRA_KEYSPACE = "cassandra-keyspace";
|
||||
public static final String CASSANDRA_SESSION = "cassandra-session";
|
||||
|
||||
public static final String CASSANDRA_TEMPLATE = "cassandra-template";
|
||||
}
|
||||
|
||||
@@ -74,15 +74,14 @@ public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser {
|
||||
builder.addPropertyValue("compressionType", CompressionType.valueOf(compression));
|
||||
}
|
||||
|
||||
postProcess(builder, element);
|
||||
parseChildElements(builder, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
|
||||
List<Element> subElements = DomUtils.getChildElements(element);
|
||||
protected void parseChildElements(BeanDefinitionBuilder builder, Element element) {
|
||||
List<Element> elements = DomUtils.getChildElements(element);
|
||||
|
||||
// parse nested elements
|
||||
for (Element subElement : subElements) {
|
||||
for (Element subElement : elements) {
|
||||
String name = subElement.getLocalName();
|
||||
|
||||
if ("local-pooling-options".equals(name)) {
|
||||
@@ -99,11 +98,10 @@ public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser {
|
||||
private BeanDefinition parsePoolingOptions(Element element) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(PoolingOptionsConfig.class);
|
||||
|
||||
// TODO
|
||||
// ParsingUtils.setPropertyValue(builder, element, "min-simultaneous-requests", "minSimultaneousRequests");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "max-simultaneous-requests", "maxSimultaneousRequests");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "core-connections", "coreConnections");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "max-connections", "maxConnections");
|
||||
ParsingUtils.setPropertyValue(builder, element, "min-simultaneous-requests", "minSimultaneousRequests");
|
||||
ParsingUtils.setPropertyValue(builder, element, "max-simultaneous-requests", "maxSimultaneousRequests");
|
||||
ParsingUtils.setPropertyValue(builder, element, "core-connections", "coreConnections");
|
||||
ParsingUtils.setPropertyValue(builder, element, "max-connections", "maxConnections");
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
@@ -111,14 +109,13 @@ public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser {
|
||||
private BeanDefinition parseSocketOptions(Element element) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SocketOptionsConfig.class);
|
||||
|
||||
// TODO
|
||||
// ParsingUtils.setPropertyValue(builder, element, "connect-timeout-mls", "connectTimeoutMls");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "keep-alive", "keepAlive");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "reuse-address", "reuseAddress");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "so-linger", "soLinger");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "tcp-no-delay", "tcpNoDelay");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "receive-buffer-size", "receiveBufferSize");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "send-buffer-size", "sendBufferSize");
|
||||
ParsingUtils.setPropertyValue(builder, element, "connect-timeout-mls", "connectTimeoutMls");
|
||||
ParsingUtils.setPropertyValue(builder, element, "keep-alive", "keepAlive");
|
||||
ParsingUtils.setPropertyValue(builder, element, "reuse-address", "reuseAddress");
|
||||
ParsingUtils.setPropertyValue(builder, element, "so-linger", "soLinger");
|
||||
ParsingUtils.setPropertyValue(builder, element, "tcp-no-delay", "tcpNoDelay");
|
||||
ParsingUtils.setPropertyValue(builder, element, "receive-buffer-size", "receiveBufferSize");
|
||||
ParsingUtils.setPropertyValue(builder, element, "send-buffer-size", "sendBufferSize");
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
@@ -31,9 +31,10 @@ import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for <keyspace;gt; definitions.
|
||||
* Parser for <keyspace> definitions.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
|
||||
public class CassandraKeyspaceParser extends AbstractSimpleBeanDefinitionParser {
|
||||
@@ -95,11 +96,10 @@ public class CassandraKeyspaceParser extends AbstractSimpleBeanDefinitionParser
|
||||
private BeanDefinition parseKeyspaceAttributes(Element element) {
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(KeyspaceAttributes.class);
|
||||
|
||||
// TODO
|
||||
// ParsingUtils.setPropertyValue(defBuilder, element, "auto", "auto");
|
||||
// ParsingUtils.setPropertyValue(defBuilder, element, "replication-strategy", "replicationStrategy");
|
||||
// ParsingUtils.setPropertyValue(defBuilder, element, "replication-factor", "replicationFactor");
|
||||
// ParsingUtils.setPropertyValue(defBuilder, element, "durable-writes", "durableWrites");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "auto", "auto");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "replication-strategy", "replicationStrategy");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "replication-factor", "replicationFactor");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "durable-writes", "durableWrites");
|
||||
|
||||
List<Element> subElements = DomUtils.getChildElements(element);
|
||||
ManagedList<Object> tables = new ManagedList<Object>(subElements.size());
|
||||
@@ -122,9 +122,8 @@ public class CassandraKeyspaceParser extends AbstractSimpleBeanDefinitionParser
|
||||
private BeanDefinition parseTable(Element element) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(TableAttributes.class);
|
||||
|
||||
// TODO
|
||||
// ParsingUtils.setPropertyValue(builder, element, "entity", "entity");
|
||||
// ParsingUtils.setPropertyValue(builder, element, "name", "name");
|
||||
ParsingUtils.setPropertyValue(builder, element, "entity", "entity");
|
||||
ParsingUtils.setPropertyValue(builder, element, "name", "name");
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@ package org.springframework.cassandra.config.xml;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
/**
|
||||
* Namespace handler for <cassandra;gt;.
|
||||
* Namespace handler for <cassandra> elements.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
|
||||
public class CassandraNamespaceHandler extends NamespaceHandlerSupport {
|
||||
@@ -28,9 +29,8 @@ public class CassandraNamespaceHandler extends NamespaceHandlerSupport {
|
||||
public void init() {
|
||||
|
||||
registerBeanDefinitionParser("cluster", new CassandraClusterParser());
|
||||
registerBeanDefinitionParser("keyspace", new CassandraKeyspaceParser());
|
||||
// registerBeanDefinitionParser("keyspace", new CassandraKeyspaceParser());
|
||||
registerBeanDefinitionParser("session", new CassandraSessionParser());
|
||||
|
||||
registerBeanDefinitionParser("template", new CassandraTemplateParser());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,54 +15,41 @@
|
||||
*/
|
||||
package org.springframework.cassandra.config.xml;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cassandra.config.KeyspaceAttributes;
|
||||
import org.springframework.cassandra.support.CassandraExceptionTranslator;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.KeyspaceMetadata;
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
/**
|
||||
* Convenient factory for configuring a Cassandra Session. Session is a thread safe singleton and created per a
|
||||
* keyspace. So, it is enough to have one session per application.
|
||||
* Factory for configuring a Cassandra {@link Session}, which is a thread-safe singleton. As such, it is sufficient to
|
||||
* have one {@link Session} per application and keyspace.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
|
||||
public class CassandraSessionFactoryBean implements FactoryBean<Session>, InitializingBean, DisposableBean,
|
||||
BeanClassLoaderAware, PersistenceExceptionTranslator {
|
||||
PersistenceExceptionTranslator {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CassandraSessionFactoryBean.class);
|
||||
|
||||
public static final String DEFAULT_REPLICATION_STRATEGY = "SimpleStrategy";
|
||||
public static final int DEFAULT_REPLICATION_FACTOR = 1;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private Cluster cluster;
|
||||
private Session session;
|
||||
private String keyspace;
|
||||
|
||||
private KeyspaceAttributes keyspaceAttributes;
|
||||
private String keyspaceName;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
public Session getObject() {
|
||||
return session;
|
||||
}
|
||||
@@ -101,7 +88,7 @@ public class CassandraSessionFactoryBean implements FactoryBean<Session>, Initia
|
||||
throw new IllegalArgumentException("at least one cluster is required");
|
||||
}
|
||||
|
||||
this.session = StringUtils.hasText(this.keyspace) ? cluster.connect(keyspace) : cluster.connect();
|
||||
this.session = StringUtils.hasText(this.keyspaceName) ? cluster.connect(keyspaceName) : cluster.connect();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -109,49 +96,14 @@ public class CassandraSessionFactoryBean implements FactoryBean<Session>, Initia
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
|
||||
this.session.shutdown();
|
||||
}
|
||||
|
||||
public void setKeyspace(String keyspace) {
|
||||
this.keyspace = keyspace;
|
||||
public void setKeyspaceName(String keyspaceName) {
|
||||
this.keyspaceName = keyspaceName;
|
||||
}
|
||||
|
||||
public void setCluster(Cluster cluster) {
|
||||
this.cluster = cluster;
|
||||
}
|
||||
|
||||
public void setKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes) {
|
||||
this.keyspaceAttributes = keyspaceAttributes;
|
||||
}
|
||||
|
||||
private static String compareKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes,
|
||||
KeyspaceMetadata keyspaceMetadata) {
|
||||
if (keyspaceAttributes.isDurableWrites() != keyspaceMetadata.isDurableWrites()) {
|
||||
return "durableWrites";
|
||||
}
|
||||
Map<String, String> replication = keyspaceMetadata.getReplication();
|
||||
String replicationFactorStr = replication.get("replication_factor");
|
||||
if (replicationFactorStr == null) {
|
||||
return "replication_factor";
|
||||
}
|
||||
try {
|
||||
int replicationFactor = Integer.parseInt(replicationFactorStr);
|
||||
if (keyspaceAttributes.getReplicationFactor() != replicationFactor) {
|
||||
return "replication_factor";
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return "replication_factor";
|
||||
}
|
||||
|
||||
String attributesStrategy = keyspaceAttributes.getReplicationStrategy();
|
||||
if (attributesStrategy.indexOf('.') == -1) {
|
||||
attributesStrategy = "org.apache.cassandra.locator." + attributesStrategy;
|
||||
}
|
||||
String replicationStrategy = replication.get("class");
|
||||
if (!attributesStrategy.equals(replicationStrategy)) {
|
||||
return "replication_class";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,21 +20,21 @@ 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.cassandra.core.SessionFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for <session;gt; definitions.
|
||||
* Parser for <session> definitions.
|
||||
*
|
||||
* @author David Webb
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
|
||||
public class CassandraSessionParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return SessionFactoryBean.class;
|
||||
return CassandraSessionFactoryBean.class;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -52,18 +52,16 @@ public class CassandraSessionParser extends AbstractSimpleBeanDefinitionParser {
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
|
||||
String keyspaceRef = element.getAttribute("cassandra-keyspace-ref");
|
||||
if (!StringUtils.hasText(keyspaceRef)) {
|
||||
keyspaceRef = BeanNames.CASSANDRA_KEYSPACE;
|
||||
String keyspaceName = element.getAttribute("keyspace-name");
|
||||
if (!StringUtils.hasText(keyspaceName)) {
|
||||
keyspaceName = null;
|
||||
}
|
||||
builder.addPropertyReference("keyspace", keyspaceRef);
|
||||
builder.addPropertyValue("keyspaceName", keyspaceName);
|
||||
|
||||
postProcess(builder, element);
|
||||
String clusterRef = element.getAttribute("cluster-ref");
|
||||
if (!StringUtils.hasText(clusterRef)) {
|
||||
clusterRef = BeanNames.CASSANDRA_CLUSTER;
|
||||
}
|
||||
builder.addPropertyReference("cluster", clusterRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2011-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cassandra.config.xml;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cassandra.core.CassandraTemplate;
|
||||
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
/**
|
||||
* Factory for configuring a {@link CassandraTemplate}.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
|
||||
public class CassandraTemplateFactoryBean implements FactoryBean<CassandraTemplate>, InitializingBean {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CassandraTemplateFactoryBean.class);
|
||||
|
||||
private CassandraTemplate template;
|
||||
private Session session;
|
||||
|
||||
public CassandraTemplate getObject() {
|
||||
return template;
|
||||
}
|
||||
|
||||
public Class<? extends CassandraTemplate> getObjectType() {
|
||||
return CassandraTemplate.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
if (session == null) {
|
||||
throw new IllegalStateException("session is required");
|
||||
}
|
||||
|
||||
this.template = new CassandraTemplate(session);
|
||||
}
|
||||
|
||||
public void setSession(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2011-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cassandra.config.xml;
|
||||
|
||||
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.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for <template> definitions.
|
||||
*
|
||||
* @author David Webb
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
|
||||
public class CassandraTemplateParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return CassandraTemplateFactoryBean.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 : BeanNames.CASSANDRA_TEMPLATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
|
||||
String sessionRef = element.getAttribute("session-ref");
|
||||
if (!StringUtils.hasText(sessionRef)) {
|
||||
sessionRef = BeanNames.CASSANDRA_SESSION;
|
||||
}
|
||||
builder.addPropertyReference("session", sessionRef);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.springframework.cassandra.config.xml;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class ParsingUtils {
|
||||
|
||||
/**
|
||||
* Configures a property value for the given property name reading the attribute of the given name from the given
|
||||
* {@link Element} if the attribute is configured.
|
||||
*
|
||||
* @param builder must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @param attrName must not be {@literal null} or empty.
|
||||
* @param propertyName must not be {@literal null} or empty.
|
||||
*/
|
||||
public static void setPropertyValue(BeanDefinitionBuilder builder, Element element, String attrName,
|
||||
String propertyName) {
|
||||
|
||||
Assert.notNull(builder, "BeanDefinitionBuilder must not be null!");
|
||||
Assert.notNull(element, "Element must not be null!");
|
||||
Assert.hasText(attrName, "Attribute name must not be null!");
|
||||
Assert.hasText(propertyName, "Property name must not be null!");
|
||||
|
||||
String attr = element.getAttribute(attrName);
|
||||
|
||||
if (StringUtils.hasText(attr)) {
|
||||
builder.addPropertyValue(propertyName, attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cassandra.core;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cassandra.core.Keyspace;
|
||||
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
/**
|
||||
* @author David Webb
|
||||
*
|
||||
*/
|
||||
public class SessionFactoryBean implements FactoryBean<Session>, InitializingBean {
|
||||
|
||||
private Keyspace keyspace;
|
||||
|
||||
public SessionFactoryBean() {
|
||||
}
|
||||
|
||||
public SessionFactoryBean(Keyspace keyspace) {
|
||||
setKeyspace(keyspace);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (keyspace == null) {
|
||||
throw new IllegalStateException("Keyspace required.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the keyspace.
|
||||
*/
|
||||
public Keyspace getKeyspace() {
|
||||
return keyspace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param keyspace The keyspace to set.
|
||||
*/
|
||||
public void setKeyspace(Keyspace keyspace) {
|
||||
this.keyspace = keyspace;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
*/
|
||||
@Override
|
||||
public Session getObject() {
|
||||
return keyspace.getSession();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Session.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,14 +12,14 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the configuration elements for Spring Cassandra support.
|
||||
]]></xsd:documentation>
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="session" type="sessionType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="org.springframework.cassandra.core.SessionFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Session instance used for accessing Cassandra Keyspace'.
|
||||
source="org.springframework.cassandra.config.xml.SessionFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Session.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
@@ -29,11 +29,25 @@ Defines a Cassandra Session instance used for accessing Cassandra Keyspace'.
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="template" type="templateType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="org.springframework.cassandra.config.xml.TemplateFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Templat.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.cassandra.CassandraTemplate" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="cluster" type="clusterType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="org.springframework.data.cassandra.core.CassandraClusterFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Cluster instance used for accessing Cassandra'.
|
||||
source="org.springframework.cassandra.config.xml.CassandraClusterFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Cluster.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
@@ -43,6 +57,20 @@ Defines a Cassandra Cluster instance used for accessing Cassandra'.
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="keyspace" type="keyspaceType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="org.springframework.data.cassandra.core.CassandraKeyspaceFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Session instance used for accessing Cassandra Keyspace'.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="com.datastax.driver.core.Session" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="clusterType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="local-pooling-options" type="poolingOptionsType"
|
||||
@@ -62,24 +90,26 @@ Defines a Cassandra Cluster instance used for accessing Cassandra'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="contactPoints" type="xsd:string">
|
||||
<xsd:attribute name="contactPoints" type="xsd:string"
|
||||
use="optional" default="localhost">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The comma separated hosts to Cassandra servers. Default is localhost
|
||||
The comma separated list of Cassandra servers. Default is localhost.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="port" type="xsd:string" use="optional">
|
||||
<xsd:attribute name="port" type="xsd:string" use="optional"
|
||||
default="9042">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The port to connect to Cassandra server as native CQL client. Default is 9042
|
||||
The native CQL port to connect to. Default is 9042.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="compression" default="NONE" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The protocol options compression. Default is 'none'.
|
||||
The protocol compression option. Default is 'none'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
@@ -174,20 +204,6 @@ RetryPolicy implementation.
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="keyspace" type="keyspaceType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="org.springframework.data.cassandra.core.CassandraKeyspaceFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Session instance used for accessing Cassandra Keyspace'.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="com.datastax.driver.core.Session" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="keyspaceType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="keyspace-attributes" type="keyspaceAttributesType"
|
||||
@@ -195,35 +211,17 @@ Defines a Cassandra Session instance used for accessing Cassandra Keyspace'.
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the Keyspace definition (by default
|
||||
"cassandra-keyspace")
|
||||
</xsd:documentation>
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The keyspace name of the Cassandra database.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="cassandra-cluster-ref" type="clusterRef"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Cassandra Cluster instance. Will default to 'cassandra-cluster'.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="cassandra-converter-ref" type="converterRef"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a CassandraConverter instance. Default is null.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
The name of the Cassandra keyspace.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
@@ -239,12 +237,11 @@ The reference to a CassandraConverter instance. Default is null.
|
||||
<xsd:union memberTypes="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="converterRef">
|
||||
<xsd:simpleType name="sessionRef" final="union">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to
|
||||
type="org.springframework.data.cassandra.convert.CassandraConverter" />
|
||||
<tool:assignable-to type="com.datastax.driver.core.Session" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
@@ -335,55 +332,12 @@ Sets the SO_SNDBUF socket option.
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="keyspaceAttributesType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="table" type="tableType" maxOccurs="unbounded"
|
||||
minOccurs="0"></xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="auto" default="validate">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The keyspace manipulation operation on startup. Default value is 'validate'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="validate">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Validate the keyspace, makes no changes.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="update">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Update the keyspace.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="create">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Creates the keyspace, destroying previous data.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="create-drop">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Creates and then drop the keyspace at the end of the session.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="replication-stategy" type="xsd:string"
|
||||
<xsd:attribute name="replication-strategy" type="xsd:string"
|
||||
use="optional" default="SimpleStrategy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Replication strategy of the Cassandra keyspace. Default value is 'SimpleStrategy'.
|
||||
]]></xsd:documentation>
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="replication-factor" type="xsd:string"
|
||||
@@ -391,32 +345,15 @@ Replication strategy of the Cassandra keyspace. Default value is 'SimpleStrategy
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Replication factor used by the Cassandra keyspace. Default value is '1'.
|
||||
]]></xsd:documentation>
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="durable-writes" type="xsd:string"
|
||||
use="optional" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Support durable writes in the Cassandra keyspace. Default value is 'true'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="tableType">
|
||||
<xsd:attribute name="entity" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Entity class name.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="name" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Table name override.
|
||||
]]></xsd:documentation>
|
||||
Whether to support durable writes in the Cassandra keyspace. Default value is 'true'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
@@ -425,29 +362,44 @@ Table name override.
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the Session definition; "cassandra-session" by default.
|
||||
]]></xsd:documentation>
|
||||
The name of the Session definition; default is 'cassandra-session'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="cassandra-keyspace-ref" type="keyspaceRef"
|
||||
<xsd:attribute name="cluster-ref" type="clusterRef"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Cassandra Cluster; default is 'cassandra-cluster'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="keyspace-name" type="xsd:string"
|
||||
use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Cassandra Keyspace instance. Will default to 'cassandra-keyspace'.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
The name of a Cassandra Keyspace. No default; for the system keyspace, use the empty string.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="templateType">
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the template; default is 'cassandra-template'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="session-ref" type="sessionRef"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Cassandra Session; default is 'cassandra-session'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:simpleType name="keyspaceRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="com.datastax.driver.core.Session" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:schema>
|
||||
@@ -7,8 +7,6 @@ import org.apache.cassandra.exceptions.ConfigurationException;
|
||||
import org.apache.thrift.transport.TTransportException;
|
||||
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.KeyspaceMetadata;
|
||||
@@ -20,12 +18,20 @@ public abstract class AbstractEmbeddedCassandraIntegrationTest {
|
||||
protected final static String CASSANDRA_HOST = "localhost";
|
||||
protected final static int CASSANDRA_NATIVE_PORT = 9042;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws ConfigurationException, TTransportException, IOException,
|
||||
public static void startCassandra() throws ConfigurationException, TTransportException, IOException,
|
||||
InterruptedException {
|
||||
EmbeddedCassandraServerHelper.startEmbeddedCassandra(CASSANDRA_CONFIG);
|
||||
}
|
||||
|
||||
public AbstractEmbeddedCassandraIntegrationTest() {
|
||||
try {
|
||||
startCassandra();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to clear the cluster before the next test.
|
||||
*/
|
||||
@@ -47,6 +53,10 @@ public abstract class AbstractEmbeddedCassandraIntegrationTest {
|
||||
*/
|
||||
protected Session session;
|
||||
|
||||
protected String keyspace() {
|
||||
return keyspace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we're currently connected to the cluster.
|
||||
*/
|
||||
@@ -58,23 +68,22 @@ public abstract class AbstractEmbeddedCassandraIntegrationTest {
|
||||
return Cluster.builder().addContactPoint(CASSANDRA_HOST).withPort(CASSANDRA_NATIVE_PORT).build();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
public void connect() {
|
||||
if (connect && !connected()) {
|
||||
cluster = cluster();
|
||||
|
||||
if (keyspace == null) {
|
||||
if (keyspace() == null) {
|
||||
session = cluster.connect();
|
||||
} else {
|
||||
|
||||
KeyspaceMetadata kmd = cluster.getMetadata().getKeyspace(keyspace);
|
||||
KeyspaceMetadata kmd = cluster.getMetadata().getKeyspace(keyspace());
|
||||
if (kmd == null) { // then create keyspace
|
||||
session = cluster.connect();
|
||||
session.execute("CREATE KEYSPACE " + keyspace
|
||||
session.execute("CREATE KEYSPACE " + keyspace()
|
||||
+ " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};");
|
||||
session.execute("USE " + keyspace + ";");
|
||||
session.execute("USE " + keyspace() + ";");
|
||||
} else {// else keyspace already exists
|
||||
session = cluster.connect(keyspace);
|
||||
session = cluster.connect(keyspace());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.springframework.cassandra.test.integration.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cassandra.exceptions.ConfigurationException;
|
||||
import org.apache.thrift.transport.TTransportException;
|
||||
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public abstract class AbstractIntegrationTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void startCassandra() throws ConfigurationException, TTransportException, IOException {
|
||||
EmbeddedCassandraServerHelper.startEmbeddedCassandra("spring-cassandra.yaml");
|
||||
}
|
||||
|
||||
@Inject
|
||||
public Session session;
|
||||
|
||||
@Before
|
||||
public void assertSession() {
|
||||
IntegrationTestUtils.assertSession(session);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,6 @@ public class IntegrationTestUtils {
|
||||
}
|
||||
|
||||
public static void assertKeyspaceExists(String keyspace, Session session) {
|
||||
assertNotNull(session.getCluster().getMetadata().getKeyspace(KeyspaceCreatingConfig.KEYSPACE));
|
||||
assertNotNull(session.getCluster().getMetadata().getKeyspace(keyspace));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.cassandra.test.integration.config.IntegrationTestUtils;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public abstract class AbstractIntegrationTest extends AbstractEmbeddedCassandraIntegrationTest {
|
||||
|
||||
@Inject
|
||||
public Session session;
|
||||
|
||||
@Before
|
||||
public void assertSession() {
|
||||
IntegrationTestUtils.assertSession(session);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.cassandra.test.integration.config;
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import org.springframework.cassandra.config.java.AbstractCassandraConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.cassandra.test.integration.config;
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import org.springframework.cassandra.config.KeyspaceAttributes;
|
||||
import org.springframework.cassandra.config.PoolingOptionsConfig;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.cassandra.test.integration.config;
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.cassandra.test.integration.config;
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.cassandra.test.integration.config;
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.springframework.cassandra.test.integration.config;
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cassandra.test.integration.config.IntegrationTestUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
@ContextConfiguration(classes = KeyspaceCreatingConfig.class)
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.springframework.cassandra.test.integration.config.xml;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.cassandra.core.CassandraOperations;
|
||||
import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.cassandra.test.integration.config.IntegrationTestUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class MinimalXmlConfigTest extends AbstractEmbeddedCassandraIntegrationTest {
|
||||
|
||||
protected String keyspace() {
|
||||
return "minimalxmlconfigtest";
|
||||
}
|
||||
|
||||
@Inject
|
||||
Session s;
|
||||
|
||||
@Inject
|
||||
CassandraOperations ops;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
IntegrationTestUtils.assertSession(s);
|
||||
IntegrationTestUtils.assertKeyspaceExists(keyspace(), s);
|
||||
|
||||
assertNotNull(ops);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.springframework.cassandra.test.integration.config.xml;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.cassandra.test.integration.config.IntegrationTestUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class XmlConfigTest extends AbstractEmbeddedCassandraIntegrationTest {
|
||||
|
||||
protected String keyspace() {
|
||||
return "xmlconfigtest";
|
||||
}
|
||||
|
||||
@Inject
|
||||
Session s;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
IntegrationTestUtils.assertSession(s);
|
||||
IntegrationTestUtils.assertKeyspaceExists(keyspace(), s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?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/cassandra"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/cassandra http://www.springframework.org/schema/cassandra/spring-cassandra-1.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">
|
||||
|
||||
<cassandra:cluster port="9042" />
|
||||
|
||||
<cassandra:session keyspace-name="minimalxmlconfigtest" />
|
||||
|
||||
<cassandra:template />
|
||||
</beans>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?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/cassandra"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/cassandra http://www.springframework.org/schema/cassandra/spring-cassandra-1.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">
|
||||
|
||||
<context:property-placeholder
|
||||
location="classpath:/org/springframework/cassandra/test/integration/config/xml/xmlconfigtest.properties" />
|
||||
|
||||
<cassandra:cluster id="cassandra-cluster"
|
||||
contactPoints="${cassandra.contactPoints}" port="${cassandra.port}">
|
||||
<cassandra:local-pooling-options
|
||||
min-simultaneous-requests="25" max-simultaneous-requests="100"
|
||||
core-connections="2" max-connections="8" />
|
||||
<cassandra:remote-pooling-options
|
||||
min-simultaneous-requests="25" max-simultaneous-requests="100"
|
||||
core-connections="1" max-connections="2" />
|
||||
<cassandra:socket-options
|
||||
connect-timeout-mls="5000" keep-alive="true" 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="${cassandra.keyspace}" />
|
||||
|
||||
<bean id="cassandraTemplate" class="org.springframework.cassandra.core.CassandraTemplate">
|
||||
<constructor-arg ref="cassandra-session" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -1,7 +1,3 @@
|
||||
cassandra.contactPoints=localhost
|
||||
cassandra.port=9042
|
||||
cassandra.keyspace=TestKS123
|
||||
|
||||
|
||||
|
||||
|
||||
cassandra.keyspace=xmlconfigtest
|
||||
@@ -1,55 +0,0 @@
|
||||
<?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"
|
||||
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
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<context:property-placeholder
|
||||
location="classpath:/org/springframework/data/cassandra/test/integration/config/cassandra.properties" />
|
||||
|
||||
<cassandra:cluster id="cassandra-cluster"
|
||||
contactPoints="${cassandra.contactPoints}" port="${cassandra.port}"
|
||||
compression="SNAPPY">
|
||||
<cassandra:local-pooling-options
|
||||
min-simultaneous-requests="25" max-simultaneous-requests="100"
|
||||
core-connections="2" max-connections="8" />
|
||||
<cassandra:remote-pooling-options
|
||||
min-simultaneous-requests="25" max-simultaneous-requests="100"
|
||||
core-connections="1" max-connections="2" />
|
||||
<cassandra:socket-options
|
||||
connect-timeout-mls="5000" keep-alive="true" reuse-address="true"
|
||||
so-linger="60" tcp-no-delay="true" receive-buffer-size="65536"
|
||||
send-buffer-size="65536" />
|
||||
</cassandra:cluster>
|
||||
|
||||
<bean id="cassandra-mapping"
|
||||
class=" org.springframework.data.cassandra.mapping.CassandraMappingContext" />
|
||||
|
||||
<bean id="cassandra-converter"
|
||||
class=" org.springframework.data.cassandra.convert.MappingCassandraConverter">
|
||||
<constructor-arg ref="cassandra-mapping" />
|
||||
</bean>
|
||||
|
||||
<cassandra:keyspace id="cassandra-keyspace" name="${cassandra.keyspace}"
|
||||
cassandra-cluster-ref="cassandra-cluster" cassandra-converter-ref="cassandra-converter">
|
||||
<cassandra:keyspace-attributes auto="update"
|
||||
replication-stategy="SimpleStrategy" replication-factor="1"
|
||||
durable-writes="true">
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.integration.table.Comment" />
|
||||
<cassandra:table
|
||||
entity="org.springframework.data.cassandra.test.integration.table.Notification" />
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.integration.table.Post" />
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.integration.table.Timeline" />
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.integration.table.User" />
|
||||
</cassandra:keyspace-attributes>
|
||||
</cassandra:keyspace>
|
||||
|
||||
<cassandra:session id="cassandra-session" cassandra-keyspace-ref="cassandra-keyspace"/>
|
||||
|
||||
<bean id="cassandraTemplate" class="org.springframework.cassandra.core.CassandraTemplate">
|
||||
<constructor-arg ref="cassandra-session" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
/**
|
||||
* Simple enumeration for the various compression types.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public enum CompressionType {
|
||||
NONE, SNAPPY;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
/**
|
||||
* Pooling options POJO. Can be remote or local.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class PoolingOptionsConfig {
|
||||
|
||||
private Integer minSimultaneousRequests;
|
||||
private Integer maxSimultaneousRequests;
|
||||
private Integer coreConnections;
|
||||
private Integer maxConnections;
|
||||
|
||||
public Integer getMinSimultaneousRequests() {
|
||||
return minSimultaneousRequests;
|
||||
}
|
||||
|
||||
public void setMinSimultaneousRequests(Integer minSimultaneousRequests) {
|
||||
this.minSimultaneousRequests = minSimultaneousRequests;
|
||||
}
|
||||
|
||||
public Integer getMaxSimultaneousRequests() {
|
||||
return maxSimultaneousRequests;
|
||||
}
|
||||
|
||||
public void setMaxSimultaneousRequests(Integer maxSimultaneousRequests) {
|
||||
this.maxSimultaneousRequests = maxSimultaneousRequests;
|
||||
}
|
||||
|
||||
public Integer getCoreConnections() {
|
||||
return coreConnections;
|
||||
}
|
||||
|
||||
public void setCoreConnections(Integer coreConnections) {
|
||||
this.coreConnections = coreConnections;
|
||||
}
|
||||
|
||||
public Integer getMaxConnections() {
|
||||
return maxConnections;
|
||||
}
|
||||
|
||||
public void setMaxConnections(Integer maxConnections) {
|
||||
this.maxConnections = maxConnections;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
/**
|
||||
* Socket options POJO. Uses to configure Netty.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class SocketOptionsConfig {
|
||||
|
||||
private Integer connectTimeoutMls;
|
||||
private Boolean keepAlive;
|
||||
private Boolean reuseAddress;
|
||||
private Integer soLinger;
|
||||
private Boolean tcpNoDelay;
|
||||
private Integer receiveBufferSize;
|
||||
private Integer sendBufferSize;
|
||||
|
||||
public Integer getConnectTimeoutMls() {
|
||||
return connectTimeoutMls;
|
||||
}
|
||||
|
||||
public void setConnectTimeoutMls(Integer connectTimeoutMls) {
|
||||
this.connectTimeoutMls = connectTimeoutMls;
|
||||
}
|
||||
|
||||
public Boolean getKeepAlive() {
|
||||
return keepAlive;
|
||||
}
|
||||
|
||||
public void setKeepAlive(Boolean keepAlive) {
|
||||
this.keepAlive = keepAlive;
|
||||
}
|
||||
|
||||
public Boolean getReuseAddress() {
|
||||
return reuseAddress;
|
||||
}
|
||||
|
||||
public void setReuseAddress(Boolean reuseAddress) {
|
||||
this.reuseAddress = reuseAddress;
|
||||
}
|
||||
|
||||
public Integer getSoLinger() {
|
||||
return soLinger;
|
||||
}
|
||||
|
||||
public void setSoLinger(Integer soLinger) {
|
||||
this.soLinger = soLinger;
|
||||
}
|
||||
|
||||
public Boolean getTcpNoDelay() {
|
||||
return tcpNoDelay;
|
||||
}
|
||||
|
||||
public void setTcpNoDelay(Boolean tcpNoDelay) {
|
||||
this.tcpNoDelay = tcpNoDelay;
|
||||
}
|
||||
|
||||
public Integer getReceiveBufferSize() {
|
||||
return receiveBufferSize;
|
||||
}
|
||||
|
||||
public void setReceiveBufferSize(Integer receiveBufferSize) {
|
||||
this.receiveBufferSize = receiveBufferSize;
|
||||
}
|
||||
|
||||
public Integer getSendBufferSize() {
|
||||
return sendBufferSize;
|
||||
}
|
||||
|
||||
public void setSendBufferSize(Integer sendBufferSize) {
|
||||
this.sendBufferSize = sendBufferSize;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,341 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cassandra.support.CassandraExceptionTranslator;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.cassandra.config.KeyspaceAttributes;
|
||||
import org.springframework.data.cassandra.config.TableAttributes;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.util.CqlUtils;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.KeyspaceMetadata;
|
||||
import com.datastax.driver.core.Session;
|
||||
import com.datastax.driver.core.TableMetadata;
|
||||
import com.datastax.driver.core.exceptions.NoHostAvailableException;
|
||||
|
||||
/**
|
||||
* Convenient factory for configuring a Cassandra Session. Session is a thread safe singleton and created per a
|
||||
* keyspace. So, it is enough to have one session per application.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
public class CassandraKeyspaceFactoryBean implements FactoryBean<SpringDataKeyspace>, InitializingBean, DisposableBean,
|
||||
BeanClassLoaderAware, PersistenceExceptionTranslator {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CassandraKeyspaceFactoryBean.class);
|
||||
|
||||
public static final String DEFAULT_REPLICATION_STRATEGY = "SimpleStrategy";
|
||||
public static final int DEFAULT_REPLICATION_FACTOR = 1;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private Cluster cluster;
|
||||
private Session session;
|
||||
private String keyspace;
|
||||
|
||||
private CassandraConverter converter;
|
||||
private MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
|
||||
|
||||
private SpringDataKeyspace keyspaceBean;
|
||||
|
||||
private KeyspaceAttributes keyspaceAttributes;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
public SpringDataKeyspace getObject() {
|
||||
return keyspaceBean;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
public Class<? extends Session> getObjectType() {
|
||||
return Session.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
if (this.converter == null) {
|
||||
this.converter = getDefaultCassandraConverter();
|
||||
}
|
||||
this.mappingContext = this.converter.getMappingContext();
|
||||
|
||||
if (cluster == null) {
|
||||
throw new IllegalArgumentException("at least one cluster is required");
|
||||
}
|
||||
|
||||
Session session = null;
|
||||
session = cluster.connect();
|
||||
|
||||
if (StringUtils.hasText(keyspace)) {
|
||||
|
||||
KeyspaceMetadata keyspaceMetadata = cluster.getMetadata().getKeyspace(keyspace.toLowerCase());
|
||||
boolean keyspaceExists = keyspaceMetadata != null;
|
||||
boolean keyspaceCreated = false;
|
||||
|
||||
if (keyspaceExists) {
|
||||
log.info("keyspace exists " + keyspaceMetadata.asCQLQuery());
|
||||
}
|
||||
|
||||
if (keyspaceAttributes == null) {
|
||||
keyspaceAttributes = new KeyspaceAttributes();
|
||||
}
|
||||
|
||||
// drop the old keyspace if needed
|
||||
if (keyspaceExists && (keyspaceAttributes.isCreate() || keyspaceAttributes.isCreateDrop())) {
|
||||
log.info("Drop keyspace " + keyspace + " on afterPropertiesSet");
|
||||
session.execute("DROP KEYSPACE " + keyspace + ";");
|
||||
keyspaceExists = false;
|
||||
}
|
||||
|
||||
// create the new keyspace if needed
|
||||
if (!keyspaceExists
|
||||
&& (keyspaceAttributes.isCreate() || keyspaceAttributes.isCreateDrop() || keyspaceAttributes.isUpdate())) {
|
||||
|
||||
String query = String
|
||||
.format(
|
||||
"CREATE KEYSPACE %1$s WITH replication = { 'class' : '%2$s', 'replication_factor' : %3$d } AND DURABLE_WRITES = %4$b",
|
||||
keyspace, keyspaceAttributes.getReplicationStrategy(), keyspaceAttributes.getReplicationFactor(),
|
||||
keyspaceAttributes.isDurableWrites());
|
||||
|
||||
log.info("Create keyspace " + keyspace + " on afterPropertiesSet " + query);
|
||||
|
||||
session.execute(query);
|
||||
keyspaceCreated = true;
|
||||
}
|
||||
|
||||
// update keyspace if needed
|
||||
if (keyspaceAttributes.isUpdate() && !keyspaceCreated) {
|
||||
|
||||
if (compareKeyspaceAttributes(keyspaceAttributes, keyspaceMetadata) != null) {
|
||||
|
||||
String query = String
|
||||
.format(
|
||||
"ALTER KEYSPACE %1$s WITH replication = { 'class' : '%2$s', 'replication_factor' : %3$d } AND DURABLE_WRITES = %4$b",
|
||||
keyspace, keyspaceAttributes.getReplicationStrategy(), keyspaceAttributes.getReplicationFactor(),
|
||||
keyspaceAttributes.isDurableWrites());
|
||||
|
||||
log.info("Update keyspace " + keyspace + " on afterPropertiesSet " + query);
|
||||
session.execute(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// validate keyspace if needed
|
||||
if (keyspaceAttributes.isValidate()) {
|
||||
|
||||
if (!keyspaceExists) {
|
||||
throw new InvalidDataAccessApiUsageException("keyspace '" + keyspace + "' not found in the Cassandra");
|
||||
}
|
||||
|
||||
String errorField = compareKeyspaceAttributes(keyspaceAttributes, keyspaceMetadata);
|
||||
if (errorField != null) {
|
||||
throw new InvalidDataAccessApiUsageException(errorField + " attribute is not much in the keyspace '"
|
||||
+ keyspace + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
session.execute("USE " + keyspace);
|
||||
|
||||
if (!CollectionUtils.isEmpty(keyspaceAttributes.getTables())) {
|
||||
|
||||
for (TableAttributes tableAttributes : keyspaceAttributes.getTables()) {
|
||||
|
||||
String entityClassName = tableAttributes.getEntity();
|
||||
Class<?> entityClass = ClassUtils.forName(entityClassName, this.beanClassLoader);
|
||||
CassandraPersistentEntity<?> entity = determineEntity(entityClass);
|
||||
String useTableName = tableAttributes.getName() != null ? tableAttributes.getName() : entity.getTable();
|
||||
|
||||
if (keyspaceCreated) {
|
||||
createNewTable(session, useTableName, entity);
|
||||
} else if (keyspaceAttributes.isUpdate()) {
|
||||
TableMetadata table = keyspaceMetadata.getTable(useTableName.toLowerCase());
|
||||
if (table == null) {
|
||||
createNewTable(session, useTableName, entity);
|
||||
} else {
|
||||
// alter table columns
|
||||
for (String cql : CqlUtils.alterTable(useTableName, entity, table)) {
|
||||
log.info("Execute on keyspace " + keyspace + " CQL " + cql);
|
||||
session.execute(cql);
|
||||
}
|
||||
}
|
||||
} else if (keyspaceAttributes.isValidate()) {
|
||||
TableMetadata table = keyspaceMetadata.getTable(useTableName.toLowerCase());
|
||||
if (table == null) {
|
||||
throw new InvalidDataAccessApiUsageException("not found table " + useTableName + " for entity "
|
||||
+ entityClassName);
|
||||
}
|
||||
// validate columns
|
||||
List<String> alter = CqlUtils.alterTable(useTableName, entity, table);
|
||||
if (!alter.isEmpty()) {
|
||||
throw new InvalidDataAccessApiUsageException("invalid table " + useTableName + " for entity "
|
||||
+ entityClassName + ". modify it by " + alter);
|
||||
}
|
||||
}
|
||||
|
||||
// System.out.println("tableAttributes, entityClass=" + entityClass + ", table = " + entity.getTable());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// initialize property
|
||||
this.session = session;
|
||||
|
||||
this.keyspaceBean = new SpringDataKeyspace(keyspace, session, converter);
|
||||
}
|
||||
|
||||
private void createNewTable(Session session, String useTableName, CassandraPersistentEntity<?> entity)
|
||||
throws NoHostAvailableException {
|
||||
String cql = CqlUtils.createTable(useTableName, entity, converter);
|
||||
log.info("Execute on keyspace " + keyspace + " CQL " + cql);
|
||||
session.execute(cql);
|
||||
for (String indexCQL : CqlUtils.createIndexes(useTableName, entity)) {
|
||||
log.info("Execute on keyspace " + keyspace + " CQL " + indexCQL);
|
||||
session.execute(indexCQL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
|
||||
if (StringUtils.hasText(keyspace) && keyspaceAttributes != null && keyspaceAttributes.isCreateDrop()) {
|
||||
log.info("Drop keyspace " + keyspace + " on destroy");
|
||||
session.execute("USE system");
|
||||
session.execute("DROP KEYSPACE " + keyspace);
|
||||
}
|
||||
this.session.shutdown();
|
||||
}
|
||||
|
||||
public void setKeyspace(String keyspace) {
|
||||
this.keyspace = keyspace;
|
||||
}
|
||||
|
||||
public void setCluster(Cluster cluster) {
|
||||
this.cluster = cluster;
|
||||
}
|
||||
|
||||
public void setKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes) {
|
||||
this.keyspaceAttributes = keyspaceAttributes;
|
||||
}
|
||||
|
||||
public void setConverter(CassandraConverter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
private static String compareKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes,
|
||||
KeyspaceMetadata keyspaceMetadata) {
|
||||
if (keyspaceAttributes.isDurableWrites() != keyspaceMetadata.isDurableWrites()) {
|
||||
return "durableWrites";
|
||||
}
|
||||
Map<String, String> replication = keyspaceMetadata.getReplication();
|
||||
String replicationFactorStr = replication.get("replication_factor");
|
||||
if (replicationFactorStr == null) {
|
||||
return "replication_factor";
|
||||
}
|
||||
try {
|
||||
int replicationFactor = Integer.parseInt(replicationFactorStr);
|
||||
if (keyspaceAttributes.getReplicationFactor() != replicationFactor) {
|
||||
return "replication_factor";
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return "replication_factor";
|
||||
}
|
||||
|
||||
String attributesStrategy = keyspaceAttributes.getReplicationStrategy();
|
||||
if (attributesStrategy.indexOf('.') == -1) {
|
||||
attributesStrategy = "org.apache.cassandra.locator." + attributesStrategy;
|
||||
}
|
||||
String replicationStrategy = replication.get("class");
|
||||
if (!attributesStrategy.equals(replicationStrategy)) {
|
||||
return "replication_class";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
CassandraPersistentEntity<?> determineEntity(Class<?> entityClass) {
|
||||
|
||||
if (entityClass == null) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"No class parameter provided, entity table name can't be determined!");
|
||||
}
|
||||
|
||||
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
if (entity == null) {
|
||||
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
|
||||
+ entityClass.getName());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
private static final CassandraConverter getDefaultCassandraConverter() {
|
||||
MappingCassandraConverter converter = new MappingCassandraConverter(new CassandraMappingContext());
|
||||
converter.afterPropertiesSet();
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user