all tests passing now with the exception of UserRepositoryIntegrationTests

This commit is contained in:
Matthew Adams
2014-01-29 21:19:33 -06:00
parent 845bf75854
commit 1ee1e96f2b
35 changed files with 1060 additions and 429 deletions

View File

@@ -28,6 +28,7 @@ import org.springframework.cassandra.core.CqlTemplate;
import org.springframework.cassandra.support.CassandraExceptionTranslator;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.datastax.driver.core.Cluster;
@@ -76,9 +77,7 @@ public class CassandraSessionFactoryBean implements FactoryBean<Session>, Initia
@Override
public void afterPropertiesSet() throws Exception {
if (cluster == null) {
throw new IllegalArgumentException("at least one cluster is required");
}
Assert.notNull(cluster);
session = StringUtils.hasText(keyspaceName) ? cluster.connect(keyspaceName) : cluster.connect();
executeScripts(startupScripts);

View File

@@ -50,7 +50,7 @@ public class KeyspaceActionSpecificationFactoryBean implements FactoryBean<Set<K
private String name;
private List<String> networkTopologyDataCenters = new LinkedList<String>();
private List<String> networkTopologyReplicationFactors = new LinkedList<String>();
private String replicationStrategy;
private ReplicationStrategy replicationStrategy;
private long replicationFactor;
private boolean durableWrites = false;
private boolean ifNotExists = false;
@@ -97,18 +97,15 @@ public class KeyspaceActionSpecificationFactoryBean implements FactoryBean<Set<K
create.name(name).ifNotExists(ifNotExists).with(KeyspaceOption.DURABLE_WRITES, durableWrites);
Map<Option, Object> replicationStrategyMap = new HashMap<Option, Object>();
replicationStrategyMap.put(new DefaultOption("class", String.class, true, false, true), ReplicationStrategy
.valueOf(replicationStrategy).getValue());
replicationStrategyMap.put(new DefaultOption("class", String.class, true, false, true),
replicationStrategy.getValue());
/*
* Just set replication factor for SimpleStrategy
*/
if (replicationStrategy.equals(ReplicationStrategy.SIMPLE_STRATEGY.name())) {
if (replicationStrategy == ReplicationStrategy.SIMPLE_STRATEGY) {
replicationStrategyMap.put(new DefaultOption("replication_factor", Long.class, true, false, false),
replicationFactor);
}
if (replicationStrategy.equals(ReplicationStrategy.NETWORK_TOPOLOGY_STRATEGY.name())) {
if (replicationStrategy == ReplicationStrategy.NETWORK_TOPOLOGY_STRATEGY) {
int i = 0;
for (String datacenter : networkTopologyDataCenters) {
replicationStrategyMap.put(new DefaultOption(datacenter, Long.class, true, false, false),
@@ -207,14 +204,14 @@ public class KeyspaceActionSpecificationFactoryBean implements FactoryBean<Set<K
/**
* @return Returns the replicationStrategy.
*/
public String getReplicationStrategy() {
public ReplicationStrategy getReplicationStrategy() {
return replicationStrategy;
}
/**
* @param replicationStrategy The replicationStrategy to set.
*/
public void setReplicationStrategy(String replicationStrategy) {
public void setReplicationStrategy(ReplicationStrategy replicationStrategy) {
this.replicationStrategy = replicationStrategy;
}

View File

@@ -20,6 +20,7 @@ import java.util.Map;
import org.springframework.cassandra.core.keyspace.DefaultOption;
import org.springframework.cassandra.core.keyspace.KeyspaceOption;
import org.springframework.cassandra.core.keyspace.KeyspaceOption.ReplicationStrategy;
import org.springframework.cassandra.core.keyspace.Option;
import org.springframework.cassandra.core.util.MapBuilder;
@@ -31,10 +32,7 @@ import org.springframework.cassandra.core.util.MapBuilder;
*/
public class KeyspaceAttributes {
public static final String SIMPLE_REPLICATION_STRATEGY = "SimpleStrategy";
public static final String NETWORK_TOPOLOGY_REPLICATION_STRATEGY = "NetworkTopologyStrategy";
public static final String DEFAULT_REPLICATION_STRATEGY = SIMPLE_REPLICATION_STRATEGY;
public static final ReplicationStrategy DEFAULT_REPLICATION_STRATEGY = ReplicationStrategy.SIMPLE_STRATEGY;
public static final long DEFAULT_REPLICATION_FACTOR = 1;
public static final boolean DEFAULT_DURABLE_WRITES = true;
@@ -51,8 +49,10 @@ public class KeyspaceAttributes {
* replication strategy class "SimpleStrategy" and with a replication factor equal to that given.
*/
public static Map<Option, Object> newSimpleReplication(long replicationFactor) {
return MapBuilder.map(Option.class, Object.class)
.entry(new DefaultOption("class", String.class, true, false, true), SIMPLE_REPLICATION_STRATEGY)
return MapBuilder
.map(Option.class, Object.class)
.entry(new DefaultOption("class", String.class, true, false, true),
ReplicationStrategy.SIMPLE_STRATEGY.getValue())
.entry(new DefaultOption("replication_factor", Long.class, true, false, false), replicationFactor).build();
}
@@ -64,7 +64,8 @@ public class KeyspaceAttributes {
public static Map<Option, Object> newNetworkReplication(DataCenterReplication... dataCenterReplications) {
MapBuilder<Option, Object> builder = MapBuilder.map(Option.class, Object.class).entry(
new DefaultOption("class", String.class, true, false, true), NETWORK_TOPOLOGY_REPLICATION_STRATEGY);
new DefaultOption("class", String.class, true, false, true),
ReplicationStrategy.NETWORK_TOPOLOGY_STRATEGY.getValue());
for (DataCenterReplication dcr : dataCenterReplications) {
builder.entry(new DefaultOption(dcr.dataCenter, Long.class, true, false, false), dcr.replicationFactor);
@@ -86,16 +87,16 @@ public class KeyspaceAttributes {
}
}
private String replicationStrategy = DEFAULT_REPLICATION_STRATEGY;
private ReplicationStrategy replicationStrategy = DEFAULT_REPLICATION_STRATEGY;
private long replicationFactor = DEFAULT_REPLICATION_FACTOR;
private boolean durableWrites = DEFAULT_DURABLE_WRITES;
private Map<String, Long> replicasPerNodeByDataCenter = new HashMap<String, Long>();
public String getReplicationStrategy() {
public ReplicationStrategy getReplicationStrategy() {
return replicationStrategy;
}
public void setReplicationStrategy(String replicationStrategy) {
public void setReplicationStrategy(ReplicationStrategy replicationStrategy) {
this.replicationStrategy = replicationStrategy;
}

View File

@@ -15,7 +15,10 @@
*/
package org.springframework.cassandra.config.xml;
import static org.springframework.data.config.ParsingUtils.getSourceBeanDefinition;
import static org.springframework.cassandra.config.xml.ParsingUtils.addOptionalPropertyReference;
import static org.springframework.cassandra.config.xml.ParsingUtils.addOptionalPropertyValue;
import static org.springframework.cassandra.config.xml.ParsingUtils.addRequiredPropertyValue;
import static org.springframework.cassandra.config.xml.ParsingUtils.getSourceBeanDefinition;
import java.util.ArrayList;
import java.util.List;
@@ -35,8 +38,6 @@ import org.springframework.cassandra.config.MultiLevelSetFlattenerFactoryBean;
import org.springframework.cassandra.config.PoolingOptionsFactoryBean;
import org.springframework.cassandra.config.SocketOptionsFactoryBean;
import org.springframework.cassandra.core.keyspace.KeyspaceActionSpecification;
import org.springframework.cassandra.core.keyspace.KeyspaceOption.ReplicationStrategy;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
@@ -58,7 +59,7 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : BeanNames.CASSANDRA_CLUSTER;
return StringUtils.hasText(id) ? id : DefaultBeanNames.CLUSTER;
}
@Override
@@ -91,91 +92,29 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
*/
protected void doParse(Element element, ParserContext context, BeanDefinitionBuilder builder) {
String contactPoints = element.getAttribute("contactPoints");
if (StringUtils.hasText(contactPoints)) {
builder.addPropertyValue("contactPoints", contactPoints);
}
addOptionalPropertyValue(builder, "contactPoints", element, "contact-points", null);
addOptionalPropertyValue(builder, "port", element, "port", null);
addOptionalPropertyValue(builder, "compressionType", element, "compression", null);
addOptionalPropertyValue(builder, "username", element, "username", null);
addOptionalPropertyValue(builder, "password", element, "password", null);
addOptionalPropertyValue(builder, "deferredInitialization", element, "deferred-initialization", null);
addOptionalPropertyValue(builder, "metricsEnabled", element, "metrics-enabled", null);
addOptionalPropertyValue(builder, "jmxReportingEnabled", element, "jmx-reporting-enabled", null);
addOptionalPropertyValue(builder, "sslEnabled", element, "ssl-enabled", null);
String port = element.getAttribute("port");
if (StringUtils.hasText(port)) {
builder.addPropertyValue("port", port);
}
String compression = element.getAttribute("compression");
if (StringUtils.hasText(compression)) {
builder.addPropertyValue("compressionType", compression);
}
String username = element.getAttribute("username");
if (StringUtils.hasText(username)) {
builder.addPropertyValue("username", username);
}
String password = element.getAttribute("password");
if (StringUtils.hasText(password)) {
builder.addPropertyValue("password", password);
}
String deferredInitialization = element.getAttribute("deferredInitialization");
if (StringUtils.hasText(deferredInitialization)) {
builder.addPropertyValue("deferredInitialization", deferredInitialization);
}
String metricsEnabled = element.getAttribute("metricsEnabled");
if (StringUtils.hasText(metricsEnabled)) {
builder.addPropertyValue("metricsEnabled", metricsEnabled);
}
String jmxReportingEnabled = element.getAttribute("jmxReportingEnabled");
if (StringUtils.hasText(jmxReportingEnabled)) {
builder.addPropertyValue("jmxReportingEnabled", jmxReportingEnabled);
}
String sslEnabled = element.getAttribute("sslEnabled");
if (StringUtils.hasText(sslEnabled)) {
builder.addPropertyValue("sslEnabled", sslEnabled);
}
String authProvider = element.getAttribute("auth-info-provider-ref");
if (StringUtils.hasText(authProvider)) {
builder.addPropertyReference("authProvider", authProvider);
}
String loadBalancingPolicy = element.getAttribute("load-balancing-policy-ref");
if (StringUtils.hasText(loadBalancingPolicy)) {
builder.addPropertyReference("loadBalancingPolicy", loadBalancingPolicy);
}
String reconnectionPolicy = element.getAttribute("reconnection-policy-ref");
if (StringUtils.hasText(reconnectionPolicy)) {
builder.addPropertyReference("reconnectionPolicy", reconnectionPolicy);
}
String retryPolicy = element.getAttribute("retry-policy-ref");
if (StringUtils.hasText(retryPolicy)) {
builder.addPropertyReference("retryPolicy", retryPolicy);
}
String sslOptions = element.getAttribute("ssl-options-ref");
if (StringUtils.hasText(sslOptions)) {
builder.addPropertyReference("sslOptions", sslOptions);
}
String hostStateListener = element.getAttribute("host-state-listener-ref");
if (StringUtils.hasText(hostStateListener)) {
builder.addPropertyReference("hostStateListener", hostStateListener);
}
String latencyTracker = element.getAttribute("latency-tracker-ref");
if (StringUtils.hasText(latencyTracker)) {
builder.addPropertyReference("latencyTracker", latencyTracker);
}
addOptionalPropertyReference(builder, "authProvider", element, "auth-info-provider-ref", null);
addOptionalPropertyReference(builder, "loadBalancingPolicy", element, "load-balancing-policy-ref", null);
addOptionalPropertyReference(builder, "reconnectionPolicy", element, "reconnection-policy-ref", null);
addOptionalPropertyReference(builder, "retryPolicy", element, "retry-policy-ref", null);
addOptionalPropertyReference(builder, "sslOptions", element, "ssl-options-ref", null);
addOptionalPropertyReference(builder, "hostStateListener", element, "host-state-listener-ref", null);
addOptionalPropertyReference(builder, "latencyTracker", element, "latency-tracker-ref", null);
parseChildElements(element, context, builder);
}
/**
* Parse the Child Elemement of {@link BeanNames.CASSANDRA_CLUSTER}
* Parse the Child Element of {@link DefaultBeanNames.CLUSTER}
*
* @param element The Element being parsed
* @param context The Parser Context
@@ -223,7 +162,7 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
}
/*
* If the PoolingOptionsBuilder was initilized during parsing, process it now.
* If the PoolingOptionsBuilder was initialized during parsing, process it now.
*/
if (poolingOptionsBuilder != null) {
builder.addPropertyValue("poolingOptions", getSourceBeanDefinition(poolingOptionsBuilder, context, element));
@@ -236,7 +175,7 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
}
/**
* Create the Single Factory Bean that will flatten all List<List<KeyspaceActionSpecificationFactoryBean>>
* Create the Single Factory Bean that will flatten all Set<Set<KeyspaceActionSpecificationFactoryBean>>
*
* @param element The Element being parsed
* @param context The Parser Context
@@ -262,20 +201,13 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
ManagedList<String> networkTopologyDataCenters = new ManagedList<String>();
ManagedList<String> networkTopologyReplicationFactors = new ManagedList<String>();
String strategyClass = null;
String replicationFactor = null;
if (element != null) {
strategyClass = element.getAttribute("class");
if (!StringUtils.hasText(strategyClass)) {
strategyClass = KeyspaceAttributes.DEFAULT_REPLICATION_STRATEGY;
}
replicationFactor = element.getAttribute("replication-factor");
if (!StringUtils.hasText(replicationFactor)) {
replicationFactor = KeyspaceAttributes.DEFAULT_REPLICATION_FACTOR + "";
}
addOptionalPropertyValue(builder, "replicationStrategy", element, "class",
KeyspaceAttributes.DEFAULT_REPLICATION_STRATEGY.name());
addOptionalPropertyValue(builder, "replicationFactor", element, "replication-factor", ""
+ KeyspaceAttributes.DEFAULT_REPLICATION_FACTOR);
/*
* DataCenters only apply to NetworkTolopogyStrategy
@@ -285,16 +217,10 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
networkTopologyDataCenters.add(dataCenter.getAttribute("name"));
networkTopologyReplicationFactors.add(dataCenter.getAttribute("replication-factor"));
}
} else {
strategyClass = ReplicationStrategy.SIMPLE_STRATEGY.name();
replicationFactor = KeyspaceAttributes.DEFAULT_REPLICATION_FACTOR + "";
}
builder.addPropertyValue("replicationStrategy", strategyClass);
builder.addPropertyValue("replicationFactor", replicationFactor);
builder.addPropertyValue("networkTopologyDataCenters", networkTopologyDataCenters);
builder.addPropertyValue("networkTopologyReplicationFactors", networkTopologyReplicationFactors);
}
/**
@@ -323,16 +249,16 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
}
if (hostDistance.equals(HostDistance.LOCAL)) {
ParsingUtils.setPropertyValue(builder, element, "min-simultaneous-requests", "localMinSimultaneousRequests");
ParsingUtils.setPropertyValue(builder, element, "max-simultaneous-requests", "localMaxSimultaneousRequests");
ParsingUtils.setPropertyValue(builder, element, "core-connections", "localCoreConnections");
ParsingUtils.setPropertyValue(builder, element, "max-connections", "localMaxConnections");
addOptionalPropertyValue(builder, "localMinSimultaneousRequests", element, "min-simultaneous-requests", null);
addOptionalPropertyValue(builder, "localMaxSimultaneousRequests", element, "max-simultaneous-requests", null);
addOptionalPropertyValue(builder, "localCoreConnections", element, "core-connections", null);
addOptionalPropertyValue(builder, "localMaxConnections", element, "max-connections", null);
}
if (hostDistance.equals(HostDistance.REMOTE)) {
ParsingUtils.setPropertyValue(builder, element, "min-simultaneous-requests", "remoteMinSimultaneousRequests");
ParsingUtils.setPropertyValue(builder, element, "max-simultaneous-requests", "remoteMaxSimultaneousRequests");
ParsingUtils.setPropertyValue(builder, element, "core-connections", "remoteCoreConnections");
ParsingUtils.setPropertyValue(builder, element, "max-connections", "remoteMaxConnections");
addOptionalPropertyValue(builder, "remoteMinSimultaneousRequests", element, "min-simultaneous-requests", null);
addOptionalPropertyValue(builder, "remoteMaxSimultaneousRequests", element, "max-simultaneous-requests", null);
addOptionalPropertyValue(builder, "remoteCoreConnections", element, "core-connections", null);
addOptionalPropertyValue(builder, "remoteMaxConnections", element, "max-connections", null);
}
return builder;
@@ -349,14 +275,14 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SocketOptionsFactoryBean.class);
ParsingUtils.setPropertyValue(builder, element, "connect-timeout-mls", "connectTimeoutMillis");
ParsingUtils.setPropertyValue(builder, element, "keep-alive", "keepAlive");
ParsingUtils.setPropertyValue(builder, element, "read-timeout-mls", "readTimeoutMillis");
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");
addOptionalPropertyValue(builder, "connectTimeoutMillis", element, "connect-timeout-mls", null);
addOptionalPropertyValue(builder, "keepAlive", element, "keep-alive", null);
addOptionalPropertyValue(builder, "readTimeoutMillis", element, "read-timeout-mls", null);
addOptionalPropertyValue(builder, "reuseAddress", element, "reuse-address", null);
addOptionalPropertyValue(builder, "soLinger", element, "so-linger", null);
addOptionalPropertyValue(builder, "tcpNoDelay", element, "tcp-no-delay", null);
addOptionalPropertyValue(builder, "receiveBufferSize", element, "receive-buffer-size", null);
addOptionalPropertyValue(builder, "sendBufferSize", element, "send-buffer-size", null);
return getSourceBeanDefinition(builder, context, element);
}
@@ -370,21 +296,22 @@ public class CassandraClusterParser extends AbstractBeanDefinitionParser {
*/
private BeanDefinition getKeyspaceSpecificationBeanDefinition(Element element, ParserContext context) {
String action = element.getAttribute("action");
Assert.notNull(action, "Keyspace Action must not be null!");
BeanDefinitionBuilder keyspaceBuilder = BeanDefinitionBuilder
.genericBeanDefinition(KeyspaceActionSpecificationFactoryBean.class);
ParsingUtils.setPropertyValue(keyspaceBuilder, element, "name", "name");
ParsingUtils.setPropertyValue(keyspaceBuilder, element, "action", "action");
ParsingUtils.setPropertyValue(keyspaceBuilder, element, "durableWrites", "durableWrites");
// add required replication defaults
addRequiredPropertyValue(keyspaceBuilder, "replicationStrategy",
KeyspaceAttributes.DEFAULT_REPLICATION_STRATEGY.name());
addRequiredPropertyValue(keyspaceBuilder, "replicationFactor", "" + KeyspaceAttributes.DEFAULT_REPLICATION_FACTOR);
// now start parsing
addRequiredPropertyValue(keyspaceBuilder, "name", element, "name");
addRequiredPropertyValue(keyspaceBuilder, "action", element, "action");
addOptionalPropertyValue(keyspaceBuilder, "durableWrites", element, "durable-writes", "false");
Element replicationElement = DomUtils.getChildElementByTagName(element, "replication");
parseReplication(replicationElement, keyspaceBuilder);
return getSourceBeanDefinition(keyspaceBuilder, context, element);
}
}

View File

@@ -18,12 +18,11 @@ package org.springframework.cassandra.config.xml;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* Namespace handler for &lt;cassandra&gt; elements.
* Namespace handler for spring-cassandra.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public class CassandraNamespaceHandler extends NamespaceHandlerSupport {
@Override

View File

@@ -15,8 +15,9 @@
*/
package org.springframework.cassandra.config.xml;
import java.util.ArrayList;
import java.util.List;
import static org.springframework.cassandra.config.xml.ParsingUtils.addOptionalPropertyReference;
import static org.springframework.cassandra.config.xml.ParsingUtils.addRequiredPropertyReference;
import static org.springframework.cassandra.config.xml.ParsingUtils.addRequiredPropertyValue;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
@@ -26,8 +27,9 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
/**
* Parser for &lt;session&gt; definitions.
@@ -35,7 +37,6 @@ import org.w3c.dom.NodeList;
* @author David Webb
* @author Matthew T. Adams
*/
public class CassandraSessionParser extends AbstractSimpleBeanDefinitionParser {
@Override
@@ -48,53 +49,76 @@ public class CassandraSessionParser extends AbstractSimpleBeanDefinitionParser {
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : BeanNames.CASSANDRA_SESSION;
return StringUtils.hasText(id) ? id : DefaultBeanNames.SESSION;
}
/**
* Parse the given element. This method is intended to be overridden by subclasses so that any elements not known to
* this class can be properly parsed. The default implementation throws {@link IllegalStateException}.
*/
protected void parseUnhandledElement(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
throw new IllegalStateException(String.format("encountered unhandled element [%s]", element.getLocalName()));
}
/**
* Parse the given session element attribute. This method is intended to be overridden by subclasses so that any
* attributes not known to this class can be properly parsed. The default implementation throws
* {@link IllegalStateException}.
*/
protected void parseUnhandledSessionElementAttribute(Attr attribute, ParserContext parserContext,
BeanDefinitionBuilder builder) {
throw new IllegalStateException(String.format("encountered unhandled session element attribute [%s]",
attribute.getName()));
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
parseKeyspaceName(element, builder);
parseClusterRef(element, builder);
parseScripts(element, builder, "startup-cql", "startupScripts");
parseScripts(element, builder, "shutdown-cql", "shutdownScripts");
setDefaultProperties(builder);
parseSessionAttributes(element, parserContext, builder);
parseSessionChildElements(element, parserContext, builder);
}
protected void parseScripts(Element element, BeanDefinitionBuilder builder, String elementName, String propertyName) {
List<String> scripts = parseScripts(element, elementName);
builder.addPropertyValue(propertyName, scripts);
protected void setDefaultProperties(BeanDefinitionBuilder builder) {
addRequiredPropertyReference(builder, "cluster", DefaultBeanNames.CLUSTER);
}
protected void parseClusterRef(Element element, BeanDefinitionBuilder builder) {
protected void parseSessionAttributes(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String clusterRef = element.getAttribute("cluster-ref");
if (!StringUtils.hasText(clusterRef)) {
clusterRef = BeanNames.CASSANDRA_CLUSTER;
}
builder.addPropertyReference("cluster", clusterRef);
}
protected void parseKeyspaceName(Element element, BeanDefinitionBuilder builder) {
String keyspaceName = element.getAttribute("keyspace-name");
if (!StringUtils.hasText(keyspaceName)) {
keyspaceName = null;
}
builder.addPropertyValue("keyspaceName", keyspaceName);
}
protected List<String> parseScripts(Element element, String elementName) {
NodeList nodes = element.getElementsByTagName(elementName);
int length = nodes.getLength();
List<String> scripts = new ArrayList<String>(length);
NamedNodeMap attributes = element.getAttributes();
int length = attributes.getLength();
for (int i = 0; i < length; i++) {
Element script = (Element) nodes.item(i);
scripts.add(DomUtils.getTextValue(script));
}
return scripts;
Attr attribute = (Attr) attributes.item(i);
if ("id".equals(attribute.getName())) {
continue;
}
String name = attribute.getName();
if ("keyspace-name".equals(name)) {
addRequiredPropertyValue(builder, "keyspaceName", attribute);
} else if ("cluster-ref".equals(name)) {
addOptionalPropertyReference(builder, "cluster", attribute, DefaultBeanNames.CLUSTER);
} else {
parseUnhandledSessionElementAttribute(attribute, parserContext, builder);
}
}
}
protected void parseSessionChildElements(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
for (Element child : DomUtils.getChildElements(element)) {
if ("startup-cql".equals(child.getLocalName())) {
builder.addPropertyValue("startupScripts", DomUtils.getTextValue(child));
} else if ("shutdown-cql".equals(child.getLocalName())) {
builder.addPropertyValue("shutdownScripts", DomUtils.getTextValue(child));
} else {
parseUnhandledElement(child, parserContext, builder);
}
}
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.cassandra.config.xml;
import static org.springframework.cassandra.config.xml.ParsingUtils.*;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -30,7 +32,6 @@ import org.w3c.dom.Element;
* @author David Webb
* @author Matthew T. Adams
*/
public class CassandraTemplateParser extends AbstractSimpleBeanDefinitionParser {
@Override
@@ -43,16 +44,11 @@ public class CassandraTemplateParser extends AbstractSimpleBeanDefinitionParser
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : BeanNames.CASSANDRA_TEMPLATE;
return StringUtils.hasText(id) ? id : DefaultBeanNames.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);
addOptionalPropertyReference(builder, "session", element, "session-ref", DefaultBeanNames.SESSION);
}
}

View File

@@ -20,13 +20,9 @@ package org.springframework.cassandra.config.xml;
* @author David Webb
* @author Matthew T. Adams
*/
public final class BeanNames {
public interface DefaultBeanNames {
private 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";
public static final String CLUSTER = "cassandra-cluster";
public static final String SESSION = "cassandra-session";
public static final String TEMPLATE = "cql-template";
}

View File

@@ -1,33 +1,295 @@
package org.springframework.cassandra.config.xml;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Attr;
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.
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void setPropertyValue(BeanDefinitionBuilder builder, Element element, String attrName,
String propertyName) {
public static void addOptionalPropertyValue(BeanDefinitionBuilder builder, String propertyName, Element element,
String attrName, String defaultValue) {
addProperty(builder, propertyName, element.getAttribute(attrName), defaultValue, false, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addOptionalPropertyReference(BeanDefinitionBuilder builder, String propertyName, Element element,
String attrName, String defaultValue) {
addProperty(builder, propertyName, element.getAttribute(attrName), defaultValue, false, true);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addRequiredPropertyValue(BeanDefinitionBuilder builder, String propertyName, Element element,
String attrName) {
addProperty(builder, propertyName, element.getAttribute(attrName), null, true, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addRequiredPropertyReference(BeanDefinitionBuilder builder, String propertyName, Element element,
String attrName) {
addProperty(builder, propertyName, element.getAttribute(attrName), null, true, true);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addPropertyValue(BeanDefinitionBuilder builder, String propertyName, Element element,
String attrName, String defaultValue, boolean required) {
addProperty(builder, propertyName, element.getAttribute(attrName), defaultValue, required, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, Element element,
String attrName, String defaultValue, boolean required) {
addProperty(builder, propertyName, element.getAttribute(attrName), defaultValue, required, true);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addProperty(BeanDefinitionBuilder builder, String propertyName, Element element, String attrName,
String defaultValue, boolean required, boolean reference) {
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!");
addProperty(builder, propertyName, element.getAttribute(attrName), defaultValue, required, reference);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addOptionalPropertyValue(BeanDefinitionBuilder builder, String propertyName, Attr attr,
String defaultValue) {
addProperty(builder, propertyName, attr, defaultValue, false, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addOptionalPropertyReference(BeanDefinitionBuilder builder, String propertyName, Attr attr,
String defaultValue) {
addProperty(builder, propertyName, attr, defaultValue, false, true);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addRequiredPropertyValue(BeanDefinitionBuilder builder, String propertyName, Attr attr) {
addProperty(builder, propertyName, attr, null, true, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addRequiredPropertyReference(BeanDefinitionBuilder builder, String propertyName, Attr attr) {
addProperty(builder, propertyName, attr, null, true, true);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addPropertyValue(BeanDefinitionBuilder builder, String propertyName, Attr attr,
String defaultValue, boolean required) {
addProperty(builder, propertyName, attr, defaultValue, required, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, Attr attr,
String defaultValue, boolean required) {
addProperty(builder, propertyName, attr, defaultValue, required, true);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addProperty(BeanDefinitionBuilder builder, String propertyName, Attr attr, String defaultValue,
boolean required, boolean reference) {
Assert.notNull(attr, "Attr must not be null!");
addProperty(builder, propertyName, attr.getValue(), defaultValue, required, reference);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addRequiredPropertyValue(BeanDefinitionBuilder builder, String propertyName, String value) {
addProperty(builder, propertyName, value, null, true, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addRequiredPropertyReference(BeanDefinitionBuilder builder, String propertyName, String value) {
addProperty(builder, propertyName, value, null, true, true);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addOptionalPropertyValue(BeanDefinitionBuilder builder, String propertyName, String value,
String defaultValue) {
addProperty(builder, propertyName, value, defaultValue, false, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addOptionalPropertyReference(BeanDefinitionBuilder builder, String propertyName, String value,
String defaultValue) {
addProperty(builder, propertyName, value, defaultValue, false, true);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addPropertyValue(BeanDefinitionBuilder builder, String propertyName, String value,
String defaultValue, boolean required) {
addProperty(builder, propertyName, value, defaultValue, required, false);
}
/**
* Convenience method that ultimately delegates to
* {@link #addProperty(BeanDefinitionBuilder, String, Element, String, String, boolean, boolean)}.
*/
public static void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, String value,
String defaultValue, boolean required) {
addProperty(builder, propertyName, value, defaultValue, required, true);
}
/**
* Adds the named property as a value or reference to the given {@link BeanDefinitionBuilder}, with an optional
* default value.
* <p/>
* Note: If <code>required</code> is <code>false</code>, <code>value</code> is null or empty, and
* <code>defaultValue</code> is null or empty, then no property is added and this method silently returns.
*
* @param builder The {@link BeanDefinitionBuilder}; must not be null.
* @param propertyName The name of the property being added; must not be null or empty.
* @param value The value of the property being added; may be null.
* @param defaultValue The default value of the property being set.
* @param required If <code>true</code>, then the <code>value</code> parameter must not be null or empty. If
* <code>false</code>, the <code>value</code> parameter may be null, in which case the
* <code>defaultValue</code> is used. If <code>required</code> is <code>false</code>, <code>value</code> is
* null or empty, and <code>defaultValue</code> is null or empty, then no property is added and this method
* silently returns.
* @param reference If <code>true</code>, this method will add the property as a reference, else as a value.
*
* @see BeanDefinitionBuilder#addPropertyReference(String, String)
* @see BeanDefinitionBuilder#addPropertyValue(String, Object)
*/
public static void addProperty(BeanDefinitionBuilder builder, String propertyName, String value, String defaultValue,
boolean required, boolean reference) {
Assert.notNull(builder, "BeanDefinitionBuilder must not be null!");
Assert.hasText(propertyName, "Property name must not be null!");
String attr = element.getAttribute(attrName);
if (!StringUtils.hasText(value)) {
if (required) {
throw new IllegalStateException(String.format("value required for property %s [%s] on class [%s]",
reference ? "reference" : "", propertyName, builder.getBeanDefinition().getClass().getName()));
}
// else optional; use default
if (defaultValue != null) {
value = defaultValue;
} else { // no default value given; quietly ignore & return
return;
}
}
if (StringUtils.hasText(attr)) {
builder.addPropertyValue(propertyName, attr);
if (reference) {
builder.addPropertyReference(propertyName, value);
} else {
builder.addPropertyValue(propertyName, value);
}
}
/**
* Returns the {@link BeanDefinition} built by the given {@link BeanDefinitionBuilder} enriched with source
* information derived from the given {@link Element}.
*
* @param builder must not be {@literal null}.
* @param context must not be {@literal null}.
* @param element must not be {@literal null}.
* @return
*/
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, ParserContext context,
Element element) {
Assert.notNull(element, "Element must not be null!");
Assert.notNull(context, "ParserContext must not be null!");
return getSourceBeanDefinition(builder, context.extractSource(element));
}
/**
* Returns the {@link AbstractBeanDefinition} built by the given builder with the given extracted source applied.
*
* @param builder must not be {@literal null}.
* @param source
* @return
*/
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, Object source) {
Assert.notNull(builder, "Builder must not be null!");
AbstractBeanDefinition definition = builder.getRawBeanDefinition();
definition.setSource(source);
return definition;
}
}

View File

@@ -18,6 +18,7 @@ package org.springframework.cassandra.support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.datastax.driver.core.Session;
@@ -53,6 +54,7 @@ public class CassandraAccessor implements InitializingBean {
/**
* Ensure that the Cassandra Session has been set
*/
@Override
public void afterPropertiesSet() {
if (getSession() == null) {
throw new IllegalArgumentException("Property 'session' is required");
@@ -70,7 +72,7 @@ public class CassandraAccessor implements InitializingBean {
* @param session The session to set.
*/
public void setSession(Session session) {
Assert.notNull(session);
this.session = session;
}
}

View File

@@ -18,7 +18,7 @@ Defines the configuration elements for Spring Cassandra support.
<xsd:element name="session" type="sessionType">
<xsd:annotation>
<xsd:documentation
source="org.springframework.cassandra.config.xml.SessionFactoryBean"><![CDATA[
source="org.springframework.cassandra.config.xml.CassandraSessionFactoryBean"><![CDATA[
Defines a Cassandra session.
]]></xsd:documentation>
<xsd:appinfo>
@@ -32,12 +32,12 @@ Defines a Cassandra session.
<xsd:element name="template" type="templateType">
<xsd:annotation>
<xsd:documentation
source="org.springframework.cassandra.config.xml.TemplateFactoryBean"><![CDATA[
Defines a CassandraTemplate.
source="org.springframework.cassandra.config.xml.CassandraTemplateFactoryBean"><![CDATA[
Defines a CqlTemplate.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="org.springframework.cassandra.CassandraTemplate" />
<tool:exports type="org.springframework.cassandra.CqlTemplate" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
@@ -59,16 +59,22 @@ Defines a Cassandra cluster.
<xsd:complexType name="clusterType">
<xsd:sequence>
<xsd:element name="local-pooling-options"
type="poolingOptionsType" maxOccurs="1" minOccurs="0">
<xsd:element name="local-pooling-options" type="poolingOptionsType"
maxOccurs="1" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
Local pooling options.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="remote-pooling-options" type="poolingOptionsType"
minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
Remote pooling options.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="remote-pooling-options" type="poolingOptionsType" minOccurs="0" maxOccurs="1"></xsd:element>
<xsd:element name="socket-options" type="socketOptionsType"
maxOccurs="1" minOccurs="0">
<xsd:annotation>
@@ -111,7 +117,7 @@ The name of the Cassandra Cluster definition; default is "cassandra-cluster".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="contactPoints" type="xsd:string"
<xsd:attribute name="contact-points" type="xsd:string"
use="optional" default="localhost">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -135,7 +141,6 @@ The protocol compression option. Default is "NONE".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="username" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -151,35 +156,39 @@ When Authentication is enabled, the password to use when connecting to the Clust
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="metricsEnabled" type="xsd:string" default="true">
<xsd:attribute name="metrics-enabled" type="xsd:string"
default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determine whether or not to collect metrics. Defaults to true.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="jmxReportingEnabled" type="xsd:string" default="true">
<xsd:attribute name="jmx-reporting-enabled" type="xsd:string"
default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determine whether or not to enable JMX Reporting. Defaults to true.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="deferredInitialization" type="xsd:string" default="false">
<xsd:attribute name="deferred-initialization" type="xsd:string"
default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determine if we defer initalizing the cluster until a connection is requested. Defaults to false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="sslEnabled" type="xsd:string" default="false">
<xsd:attribute name="ssl-enabled" type="xsd:string"
default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determine if SSL is used for Cassandra communication. Defaults to false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auth-info-provider-ref" use="optional">
<xsd:attribute name="auth-info-provider-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
AuthInfoProvider implementation.
@@ -196,7 +205,7 @@ AuthInfoProvider implementation.
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="load-balancing-policy-ref" use="optional">
<xsd:attribute name="load-balancing-policy-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
LoadBalancingPolicy implementation.
@@ -260,8 +269,7 @@ Custom SSL Options. sslEnabled must be true for sslOptions to be used.
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to
type="com.datastax.driver.core.SSLOptions" />
<tool:assignable-to type="com.datastax.driver.core.SSLOptions" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
@@ -278,8 +286,7 @@ Custom Host State Listener for the Cassandra Cluster.
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to
type="com.datastax.driver.core.Host.StateListener" />
<tool:assignable-to type="com.datastax.driver.core.Host.StateListener" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
@@ -296,8 +303,7 @@ Custom Latency Tracker for the Cassandra Cluster.
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to
type="com.datastax.driver.core.LatencyTracker" />
<tool:assignable-to type="com.datastax.driver.core.LatencyTracker" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
@@ -467,7 +473,7 @@ The name of a Cassandra Keyspace. No default; for the system keyspace, use the
<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 "cql-template".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -537,7 +543,7 @@ Provides the ability to specify replication factors by data center.
</xsd:element>
</xsd:sequence>
<xsd:attribute name="class" type="xsd:string" use="optional"
default="SimpleStrategy">
default="SIMPLE_STRATEGY">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the replication class; default is "SIMPLE_STRATEGY".

View File

@@ -27,11 +27,11 @@
<bean id="latencyTracker" class="org.springframework.cassandra.test.integration.config.xml.TestLatencyTracker"/>
<cassandra:cluster id="cassandra-cluster"
contactPoints="${cluster.contactPoints}" port="${cluster.port}"
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}"
deferredInitialization="${cluster.deferredInit}" metricsEnabled="${cluster.metricsEnabled}"
jmxReportingEnabled="${cluster.jmxReportingEnabled}"
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"

View File

@@ -10,7 +10,7 @@
location="classpath:org.springframework.cassandra.test.integration.support.BuildProperties.properties" />
<cassandra:cluster id="cassandra-cluster"
contactPoints="localhost" port="${build.cassandra.native_transport_port}">
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" />

View File

@@ -0,0 +1,12 @@
package org.springframework.data.cassandra.config;
import org.springframework.cassandra.config.CassandraClusterFactoryBean;
/**
* Spring Data Cassandra extension of CassandraClusterFactoryBean. This class exists only in the name of symmetry, based
* on the other CassandraData*FactoryBean classes.
*
* @author Matthew T. Adams
*/
public class CassandraDataClusterFactoryBean extends CassandraClusterFactoryBean {
}

View File

@@ -8,7 +8,10 @@ import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.datastax.driver.core.KeyspaceMetadata;
import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.TableMetadata;
public class CassandraDataSessionFactoryBean extends CassandraSessionFactoryBean {
@@ -17,17 +20,56 @@ public class CassandraDataSessionFactoryBean extends CassandraSessionFactoryBean
protected CassandraAdminTemplate admin;
protected CassandraConverter converter;
protected CassandraMappingContext mappingContext;
protected Mapping mapping;
protected ClassLoader entityClassLoader = getClass().getClassLoader();
@Override
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
Assert.notNull(converter);
if (mapping == null) {
mapping = new Mapping();
}
admin = new CassandraAdminTemplate(session);
admin.setCassandraConverter(converter);
processMappingOverrides();
performSchemaAction();
}
protected void processMappingOverrides() throws ClassNotFoundException {
if (mapping == null) {
return;
}
for (EntityMapping entityMapping : mapping.getEntityMappings()) {
if (entityMapping == null) {
continue;
}
String entityClassName = entityMapping.getEntityClassName();
Class<?> entityClass = Class.forName(entityClassName, false, entityClassLoader);
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
if (entity == null) {
throw new IllegalStateException(String.format("unknown persistent entity class name [%s]", entityClassName));
}
String tableName = entityMapping.getTableName();
if (!StringUtils.hasText(tableName)) {
continue;
}
entity.setTableName(tableName);
}
}
protected void performSchemaAction() {
boolean dropTables = false;
@@ -51,7 +93,18 @@ public class CassandraDataSessionFactoryBean extends CassandraSessionFactoryBean
protected void createTables(boolean dropTables, boolean dropUnused) {
for (TableMetadata table : session.getCluster().getMetadata().getKeyspace(keyspaceName).getTables()) {
Metadata md = session.getCluster().getMetadata();
KeyspaceMetadata kmd = md.getKeyspace(keyspaceName);
if (kmd == null) { // try lower-cased keyspace name
kmd = md.getKeyspace(keyspaceName.toLowerCase());
}
if (kmd == null) {
throw new IllegalStateException(String.format("keyspace [%s] does not exist", keyspaceName));
}
for (TableMetadata table : kmd.getTables()) {
if (dropTables) {
if (dropUnused || mappingContext.usesTable(table)) {
admin.dropTable(table.getName());
@@ -62,7 +115,7 @@ public class CassandraDataSessionFactoryBean extends CassandraSessionFactoryBean
Collection<? extends CassandraPersistentEntity<?>> entities = converter.getMappingContext().getPersistentEntities();
for (CassandraPersistentEntity<?> entity : entities) {
admin.createTable(false, entity.getTableName(), entity.getType(), null /* TODO */);
admin.createTable(false, entity.getTableName(), entity.getType(), null); // TODO: allow spec of table options
}
}
@@ -84,4 +137,22 @@ public class CassandraDataSessionFactoryBean extends CassandraSessionFactoryBean
this.converter = converter;
this.mappingContext = converter.getCassandraMappingContext();
}
public Mapping getMapping() {
return mapping;
}
public void setMapping(Mapping mapping) {
Assert.notNull(mapping);
this.mapping = mapping;
}
public ClassLoader getEntityClassLoader() {
return entityClassLoader;
}
public void setEntityClassLoader(ClassLoader entityClassLoader) {
Assert.notNull(entityClassLoader);
this.entityClassLoader = entityClassLoader;
}
}

View File

@@ -0,0 +1,47 @@
package org.springframework.data.cassandra.config;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.util.Assert;
import com.datastax.driver.core.Session;
public class CassandraDataTemplateFactoryBean implements FactoryBean<CassandraOperations>, InitializingBean {
protected Session session;
protected CassandraConverter converter;
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(session);
Assert.notNull(converter);
}
@Override
public CassandraOperations getObject() throws Exception {
return new CassandraTemplate(session, converter);
}
@Override
public Class<?> getObjectType() {
return CassandraOperations.class;
}
@Override
public boolean isSingleton() {
return true;
}
public void setSession(Session session) {
Assert.notNull(session);
this.session = session;
}
public void setConverter(CassandraConverter converter) {
Assert.notNull(converter);
this.converter = converter;
}
}

View File

@@ -0,0 +1,9 @@
package org.springframework.data.cassandra.config;
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";
}

View File

@@ -0,0 +1,55 @@
package org.springframework.data.cassandra.config;
/**
* Mapping information for an individual entity class.
*
* @author Matthew T. Adams
*/
public class EntityMapping {
protected String entityClassName;
protected String tableName;
public EntityMapping(String entityClassName, String tableName) {
setEntityClassName(entityClassName);
setTableName(tableName);
}
public String getEntityClassName() {
return entityClassName;
}
public void setEntityClassName(String entityClassName) {
this.entityClassName = entityClassName;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
@Override
public boolean equals(Object that) {
if (that == null) {
return false;
}
if (this == that) {
return true;
}
if (!(that instanceof EntityMapping)) {
return false;
}
EntityMapping thatMapping = (EntityMapping) that;
return this.entityClassName.equals(thatMapping.entityClassName) && this.tableName.equals(thatMapping.tableName);
}
@Override
public int hashCode() {
return entityClassName.hashCode() ^ tableName.hashCode();
}
}

View File

@@ -15,17 +15,25 @@
*/
package org.springframework.data.cassandra.config;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class KeyspaceAttributes extends org.springframework.cassandra.config.KeyspaceAttributes {
public class Mapping {
private Collection<TableAttributes> tables;
private Set<EntityMapping> entityMappings = new HashSet<EntityMapping>();
public Collection<TableAttributes> getTables() {
return tables;
public Set<EntityMapping> getEntityMappings() {
return Collections.unmodifiableSet(entityMappings);
}
public void setTables(Collection<TableAttributes> tables) {
this.tables = tables;
public void setEntityMappings(Set<EntityMapping> mappings) {
if (mappings == null) {
entityMappings.clear();
return;
}
this.entityMappings = new HashSet<EntityMapping>(mappings);
}
}

View File

@@ -1,49 +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;
/**
* Table attributes are used for manipulation around table at the startup (create/update/validate).
*
* @author Alex Shvid
*/
public class TableAttributes {
private String entity;
private String name;
public String getEntity() {
return entity;
}
public void setEntity(String entity) {
this.entity = entity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "TableAttributes [entity=" + entity + "]";
}
}

View File

@@ -0,0 +1,11 @@
package org.springframework.data.cassandra.config.xml;
import org.springframework.cassandra.config.xml.CassandraClusterParser;
/**
* Spring Data Cassandra XML namespace parser for the &lt;cluster&gt; element.
*
* @author Matthew T. Adams
*/
public class CassandraDataClusterParser extends CassandraClusterParser {
}

View File

@@ -15,16 +15,21 @@
*/
package org.springframework.data.cassandra.config.xml;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* Namespace handler for &lt;cassandra&gt;.
* Namespace handler for spring-data-cassandra.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public class CassandraNamespaceHandler extends org.springframework.cassandra.config.xml.CassandraNamespaceHandler {
public class CassandraDataNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
super.init();
registerBeanDefinitionParser("cluster", new CassandraDataClusterParser());
registerBeanDefinitionParser("session", new CassandraDataSessionParser());
registerBeanDefinitionParser("template", new CassandraDataTemplateParser());
}
}

View File

@@ -0,0 +1,100 @@
package org.springframework.data.cassandra.config.xml;
import static org.springframework.cassandra.config.xml.ParsingUtils.*;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cassandra.config.xml.CassandraSessionParser;
import org.springframework.data.cassandra.config.DefaultDataBeanNames;
import org.springframework.data.cassandra.config.CassandraDataSessionFactoryBean;
import org.springframework.data.cassandra.config.EntityMapping;
import org.springframework.data.cassandra.config.Mapping;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
/**
* Spring Data Cassandra XML namespace parser for the &lt;session&gt; element.
*
* @author Matthew T. Adams
*/
public class CassandraDataSessionParser extends CassandraSessionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return CassandraDataSessionFactoryBean.class;
}
@Override
protected void parseUnhandledSessionElementAttribute(Attr attribute, ParserContext parserContext,
BeanDefinitionBuilder builder) {
String name = attribute.getName();
if ("cassandra-converter-ref".equals(name)) {
addOptionalPropertyReference(builder, "converter", attribute, DefaultDataBeanNames.CONVERTER);
} else if ("schema-action".equals(name)) {
addOptionalPropertyValue(builder, "schemaAction", attribute, SchemaAction.NONE.name());
} else {
super.parseUnhandledSessionElementAttribute(attribute, parserContext, builder);
}
}
@Override
protected void parseUnhandledElement(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
if ("mapping".equals(element.getLocalName())) {
parseMapping(element, parserContext, builder);
} else {
super.parseUnhandledElement(element, parserContext, builder);
}
}
protected void parseMapping(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
// TODO: parse <mapping> attributes here, if there ever are any
Set<EntityMapping> mappings = new HashSet<EntityMapping>();
for (Element child : DomUtils.getChildElementsByTagName(element, "entity")) {
EntityMapping entityMapping = parseEntity(child);
if (entityMapping != null) {
mappings.add(entityMapping);
}
}
Mapping mapping = new Mapping();
mapping.setEntityMappings(mappings);
builder.addPropertyValue("mapping", mapping);
}
protected EntityMapping parseEntity(Element entity) {
String className = entity.getAttribute("class");
if (!StringUtils.hasText(className)) {
throw new IllegalStateException("class attribute must not be empty");
}
Element table = DomUtils.getChildElementByTagName(entity, "table");
if (table == null) {
return null;
}
String tableName = table.getAttribute("name");
if (!StringUtils.hasText(tableName)) {
tableName = null;
}
// TODO: parse future entity mappings here, like table options
return new EntityMapping(className, tableName);
}
}

View File

@@ -0,0 +1,47 @@
package org.springframework.data.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.ParserContext;
import org.springframework.cassandra.config.xml.CassandraTemplateParser;
import org.springframework.data.cassandra.config.DefaultDataBeanNames;
import org.springframework.data.cassandra.config.CassandraDataTemplateFactoryBean;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Spring Data Cassandra XML namespace parser for the &lt;template&gt; element.
*
* @author Matthew T. Adams
*/
public class CassandraDataTemplateParser extends CassandraTemplateParser {
@Override
protected Class<?> getBeanClass(Element element) {
return CassandraDataTemplateFactoryBean.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.DATA_TEMPLATE;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
parseConverterAttribute(element, parserContext, builder);
}
protected void parseConverterAttribute(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String converterRef = element.getAttribute("cassandra-converter-ref");
if (!StringUtils.hasText(converterRef)) {
converterRef = DefaultDataBeanNames.CONVERTER;
}
builder.addPropertyReference("converter", converterRef);
}
}

View File

@@ -30,7 +30,6 @@ public class CassandraAdminTemplate extends CassandraAccessor implements Cassand
private static final Logger log = LoggerFactory.getLogger(CassandraAdminTemplate.class);
private Session session;
private CassandraConverter converter;
private CassandraMappingContext mappingContext;
@@ -197,7 +196,7 @@ public class CassandraAdminTemplate extends CassandraAccessor implements Cassand
Assert.notNull(callback);
try {
return callback.doInSession(session);
return callback.doInSession(getSession());
} catch (RuntimeException x) {
throw tryToConvert(x);
}

View File

@@ -46,11 +46,12 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
/**
* The Cassandra Data Template is a convenience API for all Cassandra Operations using POJOs. This is the "Spring Data"
* flavor of the template. For low level Cassandra Operations use the {@link CqlTemplate}
* The Cassandra Data Template is a convenience API for all Cassandra Operations using POJOs. For low level Cassandra
* Operations use the {@link CqlTemplate}
*
* @author Alex Shvid
* @author David Webb
* @author Matthew T. Adams
*/
public class CassandraTemplate extends CqlTemplate implements CassandraOperations {
@@ -107,7 +108,11 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
*
* @param session must not be {@literal null}.
* @param converter must not be {@literal null}.
*
* @deprecated use {@link #CassandraTemplate(Session, CassandraConverter)} because session should already be connected
* to keyspace
*/
@Deprecated
public CassandraTemplate(Session session, CassandraConverter converter, String keyspace) {
setSession(session);
this.keyspace = keyspace;
@@ -937,6 +942,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
* @param callback
* @return
*/
@Override
protected <T> T doExecute(SessionCallback<T> callback) {
Assert.notNull(callback);

View File

@@ -30,6 +30,7 @@ import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@@ -42,7 +43,7 @@ import org.springframework.util.StringUtils;
public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T, CassandraPersistentProperty> implements
CassandraPersistentEntity<T>, ApplicationContextAware {
private String table;
private String tableName;
private final SpelExpressionParser spelParser;
private final StandardEvaluationContext spelContext;
private final Class<T> type;
@@ -68,7 +69,7 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
protected void determineTableName() {
Table anno = type.getAnnotation(Table.class);
this.table = anno != null && StringUtils.hasText(anno.value()) ? anno.value() : CassandraNamingUtils
this.tableName = anno != null && StringUtils.hasText(anno.value()) ? anno.value() : CassandraNamingUtils
.getPreferredTableName(type);
}
@@ -92,7 +93,13 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
@Override
public String getTableName() {
Expression expression = spelParser.parseExpression(table, ParserContext.TEMPLATE_EXPRESSION);
Expression expression = spelParser.parseExpression(tableName, ParserContext.TEMPLATE_EXPRESSION);
return expression.getValue(spelContext, String.class);
}
@Override
public void setTableName(String tableName) {
Assert.hasText(tableName);
this.tableName = tableName;
}
}

View File

@@ -30,4 +30,11 @@ public interface CassandraPersistentEntity<T> extends MutablePersistentEntity<T,
* Returns the table name to which the entity shall be persisted.
*/
String getTableName();
/**
* Sets the table name to which the entity shall be persisted.
*
* @param tableName The table name; must contain a valid Cassandra table name.
*/
void setTableName(String tableName);
}

View File

@@ -34,7 +34,7 @@ import org.w3c.dom.Element;
*/
public class CassandraRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
private static final String CASSANDRA_TEMPLATE_REF = "cassandra-template-ref";
private static final String CASSANDRA_TEMPLATE_REF = "cql-template-ref";
private static final String CREATE_QUERY_INDEXES = "create-query-indexes";
/*

View File

@@ -1 +1 @@
http\://www.springframework.org/schema/data/cassandra=org.springframework.data.cassandra.config.xml.CassandraNamespaceHandler
http\://www.springframework.org/schema/data/cassandra=org.springframework.data.cassandra.config.xml.CassandraDataNamespaceHandler

View File

@@ -18,7 +18,7 @@ Defines the configuration elements for Spring Cassandra support.
<xsd:element name="session" type="sessionType">
<xsd:annotation>
<xsd:documentation
source="org.springframework.cassandra.config.xml.SessionFactoryBean"><![CDATA[
source="org.springframework.data.cassandra.config.xml.CassandraDataSessionFactoryBean"><![CDATA[
Defines a Cassandra session.
]]></xsd:documentation>
<xsd:appinfo>
@@ -32,12 +32,13 @@ Defines a Cassandra session.
<xsd:element name="template" type="templateType">
<xsd:annotation>
<xsd:documentation
source="org.springframework.cassandra.config.xml.TemplateFactoryBean"><![CDATA[
source="org.springframework.data.cassandra.config.xml.CassandraDataTemplateFactoryBean"><![CDATA[
Defines a CassandraTemplate.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="org.springframework.cassandra.CassandraTemplate" />
<tool:exports
type="org.springframework.data.cassandra.CassandraTemplate" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
@@ -68,7 +69,7 @@ Local pooling options.
</xsd:annotation>
</xsd:element>
<xsd:element name="remote-pooling-options" type="poolingOptionsType"
maxOccurs="1" minOccurs="0">
minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
Remote pooling options.
@@ -133,32 +134,62 @@ 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:attribute name="compression" default="NONE" use="optional"
type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The protocol compression option. Default is "NONE".
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="NONE">
<xsd:annotation>
<xsd:documentation><![CDATA[
No compression.
]]></xsd:documentation>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="SNAPPY">
<xsd:annotation>
<xsd:documentation><![CDATA[
SNAPPY compression algorithm.
]]></xsd:documentation>
</xsd:annotation>
</xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="auth-info-provider" use="optional">
<xsd:attribute name="username" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
When Authentication is enabled, the username to use when connecting to the Cluster.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="password" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
When Authentication is enabled, the password to use when connecting to the Cluster.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="metricsEnabled" type="xsd:string"
default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determine whether or not to collect metrics. Defaults to true.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="jmxReportingEnabled" type="xsd:string"
default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determine whether or not to enable JMX Reporting. Defaults to true.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="deferredInitialization" type="xsd:string"
default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determine if we defer initalizing the cluster until a connection is requested. Defaults to false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="sslEnabled" type="xsd:string"
default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Determine if SSL is used for Cassandra communication. Defaults to false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auth-info-provider-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
AuthInfoProvider implementation.
@@ -175,7 +206,7 @@ AuthInfoProvider implementation.
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="load-balancing-policy" use="optional">
<xsd:attribute name="load-balancing-policy-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
LoadBalancingPolicy implementation.
@@ -193,7 +224,7 @@ LoadBalancingPolicy implementation.
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="reconnection-policy" use="optional">
<xsd:attribute name="reconnection-policy-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
ReconnectionPolicy implementation.
@@ -211,7 +242,7 @@ ReconnectionPolicy implementation.
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="retry-policy" use="optional">
<xsd:attribute name="retry-policy-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
RetryPolicy implementation.
@@ -229,8 +260,58 @@ RetryPolicy implementation.
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="ssl-options-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Custom SSL Options. sslEnabled must be true for sslOptions to be used.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to type="com.datastax.driver.core.SSLOptions" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="host-state-listener-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Custom Host State Listener for the Cassandra Cluster.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to type="com.datastax.driver.core.Host.StateListener" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="latency-tracker-ref" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Custom Latency Tracker for the Cassandra Cluster.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to type="com.datastax.driver.core.LatencyTracker" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
<xsd:simpleType name="clusterRef" final="union">
<xsd:annotation>
<xsd:appinfo>
@@ -253,18 +334,6 @@ RetryPolicy implementation.
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
<xsd:simpleType name="cassandraConverterRef" final="union">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to
type="org.springframework.data.cassandra.convert.CassandraConverter" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
<xsd:complexType name="poolingOptionsType">
<xsd:attribute name="min-simultaneous-requests" type="xsd:string">
<xsd:annotation>
@@ -297,7 +366,7 @@ More connections are created up to a configurable maximum number of connections.
</xsd:complexType>
<xsd:complexType name="socketOptionsType">
<xsd:attribute name="connect-timeout-mls" type="xsd:string">
<xsd:attribute name="connect-timeout-millis" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets connection timeout for client socket in milliseconds.
@@ -311,6 +380,13 @@ Sets the SO_KEEPALIVE socket option.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="read-timeout-millis" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets read timeout for client socket in milliseconds.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reuse-address" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -350,10 +426,6 @@ Sets the SO_SNDBUF socket option.
<xsd:complexType name="sessionType">
<xsd:sequence>
<!-- TODO: support custom table mappings
<xsd:element name="mapping" minOccurs="0" maxOccurs="1" type="mappingType"/>
-->
<xsd:element name="startup-cql" type="xsd:string"
minOccurs="0" maxOccurs="unbounded">
<!-- TODO: cql could come from a resource via a resource attribute... -->
@@ -372,6 +444,7 @@ Arbitrary CQL script to be executed against the session's keyspace during bean d
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="mapping" type="mappingType" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" use="optional">
@@ -396,14 +469,6 @@ The name of a Cassandra Keyspace. No default; for the system keyspace, use the
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="schema-actions" type="xsd:string"
use="optional" default="NONE">
<xsd:annotation>
<xsd:documentation><![CDATA[
The schema action to take on the Cassandra Keyspace. See the SchemaAction enum.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cassandra-converter-ref" type="cassandraConverterRef"
use="optional">
<xsd:annotation>
@@ -412,6 +477,14 @@ The reference to a CassandraConverter; default is "cassandra-converter".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="schema-action" type="xsd:string"
use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The schema action to perform; default is NONE.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="templateType">
@@ -462,32 +535,14 @@ The name of this keyspace. Required.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="action" use="required">
<xsd:attribute name="action" use="required" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The keyspace action to take at startup and possibly shutdown.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="CREATE">
<xsd:annotation>
<xsd:documentation><![CDATA[
Action value that causes keyspace creation during bean initialization.
]]></xsd:documentation>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="CREATE-DROP">
<xsd:annotation>
<xsd:documentation><![CDATA[
Action value that causes keyspace creation during bean initialization and keyspace dropping during bean destruction.
]]></xsd:documentation>
</xsd:annotation>
</xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="durable-writes" type="xsd:boolean"
<xsd:attribute name="durable-writes" type="xsd:string"
use="optional" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -517,11 +572,11 @@ Provides the ability to specify replication factors by data center.
default="SimpleStrategy">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the replication class; default is "SimpleStrategy".
The name of the replication class; default is "SIMPLE_STRATEGY".
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="replication-factor" type="xsd:integer"
<xsd:attribute name="replication-factor" type="xsd:string"
use="optional" default="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -530,7 +585,6 @@ The replication factor; default is 1.
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="datacenterType">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -544,7 +598,7 @@ The name of the data center.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="replication-factor" type="xsd:integer"
<xsd:attribute name="replication-factor" type="xsd:string"
use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -554,30 +608,49 @@ The replication factor for the data center.
</xsd:attribute>
</xsd:complexType>
<!-- TODO: support custom table mappings
<xsd:simpleType name="cassandraConverterRef" final="union">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to
type="org.springframework.data.cassandra.convert.CassandraConverter" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
<xsd:complexType name="mappingType">
<xsd:sequence>
<xsd:element name="table" type="tableType" minOccurs="0"
maxOccurs="1"></xsd:element>
<xsd:element name="entity" type="entityType" minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="tableType">
<xsd:attribute name="entity" type="xsd:string">
<xsd:complexType name="entityType">
<xsd:sequence>
<xsd:element name="table" type="tableType" minOccurs="0"
maxOccurs="1">
</xsd:element>
</xsd:sequence>
<xsd:attribute name="class" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Entity class name.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="table-name" type="xsd:string" use="optional">
</xsd:complexType>
<xsd:complexType name="tableType">
<xsd:attribute name="name" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Table name override.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<!-- TODO: allow specification of C* table options here -->
</xsd:complexType>
-->
</xsd:schema>
</xsd:schema>

View File

@@ -32,9 +32,13 @@ import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.test.integration.table.User;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.google.common.collect.Lists;
@@ -44,8 +48,8 @@ import com.google.common.collect.Lists;
* @author Alex Shvid
*
*/
// @ContextConfiguration
// @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class UserRepositoryIntegrationTests {
@Autowired
@@ -100,7 +104,7 @@ public class UserRepositoryIntegrationTests {
all = dataOperations.insert(Arrays.asList(tom, bob, alice, scott));
}
// @Test
@Test
public void findsUserById() throws Exception {
User user = repository.findOne(bob.getUsername());
@@ -109,7 +113,7 @@ public class UserRepositoryIntegrationTests {
}
// @Test
@Test
public void findsAll() throws Exception {
List<User> result = Lists.newArrayList(repository.findAll());
assertThat(result.size(), is(all.size()));
@@ -117,7 +121,7 @@ public class UserRepositoryIntegrationTests {
}
// @Test
@Test
public void findsAllWithGivenIds() {
Iterable<User> result = repository.findAll(Arrays.asList(bob.getUsername(), tom.getUsername()));
@@ -125,7 +129,7 @@ public class UserRepositoryIntegrationTests {
assertThat(result, not(hasItems(alice, scott)));
}
// @Test
@Test
public void deletesUserCorrectly() throws Exception {
repository.delete(tom);
@@ -136,7 +140,7 @@ public class UserRepositoryIntegrationTests {
assertThat(result, not(hasItem(tom)));
}
// @Test
@Test
public void deletesUserByIdCorrectly() {
repository.delete(tom.getUsername().toString());

View File

@@ -20,7 +20,7 @@
<cass:remote-pooling-options
min-simultaneous-requests="25" max-simultaneous-requests="100"
core-connections="1" max-connections="2" />
<cass:socket-options connect-timeout-mls="5000"
<cass:socket-options connect-timeout-millis="5000"
keep-alive="true" reuse-address="true" so-linger="60" tcp-no-delay="true"
receive-buffer-size="65536" send-buffer-size="65536" />
<cass:keyspace name="${cassandra.keyspace}" action="CREATE"
@@ -38,7 +38,7 @@
</bean>
<cass:session id="cassandra-session" keyspace-name="${cassandra.keyspace}"
schema-actions="NONE" cluster-ref="cassandra-cluster"
schema-action="NONE" cluster-ref="cassandra-cluster"
cassandra-converter-ref="cassandra-converter">
</cass:session>

View File

@@ -2,18 +2,16 @@
<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/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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
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/repository/cassandra.properties" />
<cassandra:cluster id="cassandra-cluster"
contactPoints="${cassandra.contactPoints}" port="${cassandra.native_transport_port}"
compression="SNAPPY">
contactPoints="${cassandra.contactPoints}" port="${cassandra.native_transport_port}">
<cassandra:local-pooling-options
min-simultaneous-requests="25" max-simultaneous-requests="100"
core-connections="2" max-connections="8" />
@@ -21,12 +19,14 @@
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"
connect-timeout-millis="5000" keep-alive="true" reuse-address="true"
so-linger="60" tcp-no-delay="true" receive-buffer-size="65536"
send-buffer-size="65536" />
<cassandra:keyspace name="${cassandra-keyspace}" action="CREATE" durable-writes="true">
<cassandra:replication class="SimpleStrategy" replication-factor="1"/>
<cassandra:keyspace name="${cassandra.keyspace}"
action="CREATE" durable-writes="true">
<cassandra:replication class="SIMPLE_STRATEGY"
replication-factor="1" />
</cassandra:keyspace>
</cassandra:cluster>
@@ -34,17 +34,27 @@
class="org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext" />
<bean id="cassandra-converter"
class=" org.springframework.data.cassandra.convert.MappingCassandraConverter">
class="org.springframework.data.cassandra.convert.MappingCassandraConverter">
<constructor-arg ref="cassandra-mapping" />
</bean>
<cassandra:session id="cassandra-session" keyspace-name="cassandra-keyspace"/>
<cassandra:session id="cassandra-session"
cluster-ref="cassandra-cluster" keyspace-name="${cassandra.keyspace}"
cassandra-converter-ref="cassandra-converter" schema-action="CREATE">
<cassandra:mapping>
<cassandra:entity
class="org.springframework.data.cassandra.test.integration.table.User">
<cassandra:table name="users_x" />
</cassandra:entity>
</cassandra:mapping>
</cassandra:session>
<bean id="cassandraTemplate" class="org.springframework.cassandra.core.CqlTemplate">
<constructor-arg ref="cassandra-session" />
</bean>
<bean id="cassandraDataTemplate" class="org.springframework.data.cassandra.core.CassandraTemplate">
<bean id="cassandraDataTemplate"
class="org.springframework.data.cassandra.core.CassandraTemplate">
<constructor-arg ref="cassandra-session" />
<constructor-arg ref="cassandra-converter" />
<constructor-arg value="${cassandra.keyspace}" />

View File

@@ -1,3 +1,3 @@
cassandra.contactPoints=localhost
cassandra.native_transport_port=@build.cassandra.native_transport_port@
cassandra.keyspace=TestKS123
cassandra.keyspace=UserRepositoryIntegrationTests