DATACASS-55: WIP: all working ok
This commit is contained in:
@@ -55,62 +55,50 @@ import com.datastax.driver.core.policies.RetryPolicy;
|
||||
public class CassandraClusterFactoryBean implements FactoryBean<Cluster>, InitializingBean, DisposableBean,
|
||||
PersistenceExceptionTranslator {
|
||||
|
||||
protected static final Logger log = LoggerFactory.getLogger(CassandraClusterFactoryBean.class);
|
||||
public static final String DEFAULT_CONTACT_POINTS = "localhost";
|
||||
public static final boolean DEFAULT_METRICS_ENABLED = true;
|
||||
public static final int DEFAULT_PORT = 9042;
|
||||
|
||||
private static final int DEFAULT_PORT = 9042;
|
||||
protected static final Logger log = LoggerFactory.getLogger(CassandraClusterFactoryBean.class);
|
||||
|
||||
private Cluster cluster;
|
||||
|
||||
private String contactPoints;
|
||||
private int port = DEFAULT_PORT;
|
||||
/**
|
||||
* Comma-delimited string of servers.
|
||||
*/
|
||||
private String contactPoints = DEFAULT_CONTACT_POINTS;
|
||||
private int port = CassandraClusterFactoryBean.DEFAULT_PORT;
|
||||
private CompressionType compressionType;
|
||||
|
||||
private PoolingOptionsConfig localPoolingOptions;
|
||||
private PoolingOptionsConfig remotePoolingOptions;
|
||||
private SocketOptionsConfig socketOptions;
|
||||
|
||||
private AuthProvider authProvider;
|
||||
private LoadBalancingPolicy loadBalancingPolicy;
|
||||
private ReconnectionPolicy reconnectionPolicy;
|
||||
private RetryPolicy retryPolicy;
|
||||
|
||||
private boolean metricsEnabled = true;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
|
||||
|
||||
private boolean metricsEnabled = DEFAULT_METRICS_ENABLED;
|
||||
private List<CreateKeyspaceSpecification> keyspaceCreations = new ArrayList<CreateKeyspaceSpecification>();
|
||||
private List<DropKeyspaceSpecification> keyspaceDrops = new ArrayList<DropKeyspaceSpecification>();
|
||||
|
||||
private List<String> startupScripts = new ArrayList<String>();
|
||||
private List<String> shutdownScripts = new ArrayList<String>();
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
|
||||
|
||||
@Override
|
||||
public Cluster getObject() throws Exception {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
@Override
|
||||
public Class<? extends Cluster> getObjectType() {
|
||||
return Cluster.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
@@ -163,44 +151,56 @@ public class CassandraClusterFactoryBean implements FactoryBean<Cluster>, Initia
|
||||
builder.withoutMetrics();
|
||||
}
|
||||
|
||||
Cluster cluster = builder.build();
|
||||
|
||||
// initialize property
|
||||
this.cluster = cluster;
|
||||
|
||||
cluster = builder.build();
|
||||
executeSpecsAndScripts(keyspaceCreations, startupScripts);
|
||||
}
|
||||
|
||||
protected void executeSpecsAndScripts(@SuppressWarnings("rawtypes") List specs, List<String> scripts) {
|
||||
|
||||
Session system = null;
|
||||
CassandraTemplate template = null;
|
||||
|
||||
try {
|
||||
system = specs.size() > 0 ? cluster.connect() : null;
|
||||
CassandraTemplate template = system == null ? null : new CassandraTemplate(system);
|
||||
if (specs != null) {
|
||||
system = specs.size() == 0 ? null : cluster.connect();
|
||||
template = system == null ? null : new CassandraTemplate(system);
|
||||
|
||||
Iterator<?> i = specs.iterator();
|
||||
while (i.hasNext()) {
|
||||
KeyspaceNameSpecification<?> spec = (KeyspaceNameSpecification<?>) i.next();
|
||||
String cql = (spec instanceof CreateKeyspaceSpecification) ? new CreateKeyspaceCqlGenerator(
|
||||
(CreateKeyspaceSpecification) spec).toCql()
|
||||
: new DropKeyspaceCqlGenerator((DropKeyspaceSpecification) spec).toCql();
|
||||
Iterator<?> i = specs.iterator();
|
||||
while (i.hasNext()) {
|
||||
KeyspaceNameSpecification<?> spec = (KeyspaceNameSpecification<?>) i.next();
|
||||
String cql = (spec instanceof CreateKeyspaceSpecification) ? new CreateKeyspaceCqlGenerator(
|
||||
(CreateKeyspaceSpecification) spec).toCql() : new DropKeyspaceCqlGenerator(
|
||||
(DropKeyspaceSpecification) spec).toCql();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.info("executing CQL [{}]", cql);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("executing CQL [{}]", cql);
|
||||
}
|
||||
|
||||
template.execute(cql);
|
||||
}
|
||||
|
||||
template.execute(cql);
|
||||
}
|
||||
|
||||
for (String script : startupScripts) {
|
||||
if (scripts != null) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.info("executing raw CQL [{}]", script);
|
||||
if (system == null) {
|
||||
system = scripts.size() == 0 ? null : cluster.connect();
|
||||
}
|
||||
|
||||
template.execute(script);
|
||||
}
|
||||
if (template == null) {
|
||||
template = system == null ? null : new CassandraTemplate(system);
|
||||
}
|
||||
|
||||
for (String script : scripts) {
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("executing raw CQL [{}]", script);
|
||||
}
|
||||
|
||||
template.execute(script);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
if (system != null) {
|
||||
system.shutdown();
|
||||
}
|
||||
@@ -211,10 +211,12 @@ public class CassandraClusterFactoryBean implements FactoryBean<Cluster>, Initia
|
||||
public void destroy() throws Exception {
|
||||
|
||||
executeSpecsAndScripts(keyspaceDrops, shutdownScripts);
|
||||
|
||||
cluster.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a comma-delimited string of the contact points (hosts) to connect to.
|
||||
*/
|
||||
public void setContactPoints(String contactPoints) {
|
||||
this.contactPoints = contactPoints;
|
||||
}
|
||||
|
||||
@@ -15,14 +15,19 @@
|
||||
*/
|
||||
package org.springframework.cassandra.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cassandra.core.CassandraTemplate;
|
||||
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;
|
||||
@@ -41,69 +46,101 @@ public class CassandraSessionFactoryBean implements FactoryBean<Session>, Initia
|
||||
|
||||
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 Cluster cluster;
|
||||
private Session session;
|
||||
private String keyspaceName;
|
||||
|
||||
private List<String> startupScripts = new ArrayList<String>();
|
||||
private List<String> shutdownScripts = new ArrayList<String>();
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
|
||||
|
||||
@Override
|
||||
public Session getObject() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
@Override
|
||||
public Class<? extends Session> getObjectType() {
|
||||
return Session.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
if (cluster == null) {
|
||||
throw new IllegalArgumentException("at least one cluster is required");
|
||||
}
|
||||
|
||||
this.session = StringUtils.hasText(this.keyspaceName) ? cluster.connect(keyspaceName) : cluster.connect();
|
||||
session = StringUtils.hasText(keyspaceName) ? cluster.connect(keyspaceName) : cluster.connect();
|
||||
executeScripts(startupScripts);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
/**
|
||||
* Executes given scripts. Session must be connected when this method is called.
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
this.session.shutdown();
|
||||
protected void executeScripts(List<String> scripts) {
|
||||
|
||||
if (scripts == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CassandraTemplate template = new CassandraTemplate(session);
|
||||
|
||||
for (String script : scripts) {
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("executing raw CQL [{}]", script);
|
||||
}
|
||||
|
||||
template.execute(script);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
|
||||
executeScripts(shutdownScripts);
|
||||
session.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the keyspace name to connect to. Using <code>null</code>, empty string, or only whitespace will cause the
|
||||
* system keyspace to be used.
|
||||
*/
|
||||
public void setKeyspaceName(String keyspaceName) {
|
||||
this.keyspaceName = keyspaceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cluster to use. Must not be null.
|
||||
*/
|
||||
public void setCluster(Cluster cluster) {
|
||||
if (cluster == null) {
|
||||
throw new IllegalArgumentException("cluster must not be null");
|
||||
}
|
||||
this.cluster = cluster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets CQL scripts to be executed immediately after the session is connected.
|
||||
*/
|
||||
public void setStartupScripts(List<String> scripts) {
|
||||
this.startupScripts = scripts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets CQL scripts to be executed immediately before the session is shutdown.
|
||||
*/
|
||||
public void setShutdownScripts(List<String> scripts) {
|
||||
this.shutdownScripts = scripts;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ package org.springframework.cassandra.config;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.cassandra.core.keyspace.DefaultOption;
|
||||
import org.springframework.cassandra.core.keyspace.KeyspaceOption;
|
||||
import org.springframework.cassandra.core.keyspace.Option;
|
||||
import org.springframework.cassandra.core.util.MapBuilder;
|
||||
|
||||
/**
|
||||
* Keyspace attributes.
|
||||
*
|
||||
@@ -33,6 +38,54 @@ public class KeyspaceAttributes {
|
||||
public static final long DEFAULT_REPLICATION_FACTOR = 1;
|
||||
public static final boolean DEFAULT_DURABLE_WRITES = true;
|
||||
|
||||
/**
|
||||
* Returns a map of {@link Option}s suitable as the value of a {@link KeyspaceOption#REPLICATION} option with
|
||||
* replication strategy class "SimpleStrategy" and with a replication factor of one.
|
||||
*/
|
||||
public static Map<Option, Object> newSimpleReplication() {
|
||||
return newSimpleReplication(DEFAULT_REPLICATION_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of {@link Option}s suitable as the value of a {@link KeyspaceOption#REPLICATION} option with
|
||||
* 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)
|
||||
.entry(new DefaultOption("replication_factor", Long.class, true, false, false), replicationFactor).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of {@link Option}s suitable as the value of a {@link KeyspaceOption#REPLICATION} option with
|
||||
* replication strategy class "NetworkTopologyStrategy" and with data centers each with their corresponding
|
||||
* replication factors.
|
||||
*/
|
||||
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);
|
||||
|
||||
for (DataCenterReplication dcr : dataCenterReplications) {
|
||||
builder.entry(new DefaultOption(dcr.dataCenter, Long.class, true, false, false), dcr.replicationFactor);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple data structure to be used when setting the replication factor for a given data center.
|
||||
*/
|
||||
public static class DataCenterReplication {
|
||||
public String dataCenter;
|
||||
public long replicationFactor;
|
||||
|
||||
public DataCenterReplication(String dataCenter, long replicationFactor) {
|
||||
this.dataCenter = dataCenter;
|
||||
this.replicationFactor = replicationFactor;
|
||||
}
|
||||
}
|
||||
|
||||
private String replicationStrategy = DEFAULT_REPLICATION_STRATEGY;
|
||||
private long replicationFactor = DEFAULT_REPLICATION_FACTOR;
|
||||
private boolean durableWrites = DEFAULT_DURABLE_WRITES;
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package org.springframework.cassandra.config.java;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cassandra.config.CassandraClusterFactoryBean;
|
||||
import org.springframework.cassandra.config.CassandraSessionFactoryBean;
|
||||
import org.springframework.cassandra.config.CompressionType;
|
||||
import org.springframework.cassandra.config.PoolingOptionsConfig;
|
||||
import org.springframework.cassandra.config.SocketOptionsConfig;
|
||||
import org.springframework.cassandra.core.CassandraOperations;
|
||||
import org.springframework.cassandra.core.CassandraTemplate;
|
||||
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
|
||||
import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.datastax.driver.core.AuthProvider;
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.policies.LoadBalancingPolicy;
|
||||
import com.datastax.driver.core.policies.ReconnectionPolicy;
|
||||
import com.datastax.driver.core.policies.RetryPolicy;
|
||||
|
||||
/**
|
||||
* Base class for Spring Cassandra configuration that can handle creating namespaces, execute arbitrary CQL on startup &
|
||||
* shutdown, and optionally drop namespaces.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractCassandraFactoryBeanConfiguration {
|
||||
|
||||
protected abstract String getKeyspaceName();
|
||||
|
||||
@Bean
|
||||
public CassandraClusterFactoryBean cluster() throws Exception {
|
||||
|
||||
CassandraClusterFactoryBean bean = new CassandraClusterFactoryBean();
|
||||
bean.setAuthProvider(getAuthProvider());
|
||||
bean.setCompressionType(getCompressionType());
|
||||
bean.setContactPoints(getContactPoints());
|
||||
bean.setKeyspaceCreations(getKeyspaceCreations());
|
||||
bean.setKeyspaceDrops(getKeyspaceDrops());
|
||||
bean.setLoadBalancingPolicy(getLoadBalancingPolicy());
|
||||
bean.setLocalPoolingOptions(getLocalPoolingOptions());
|
||||
bean.setMetricsEnabled(getMetricsEnabled());
|
||||
bean.setPort(getPort());
|
||||
bean.setReconnectionPolicy(getReconnectionPolicy());
|
||||
bean.setRemotePoolingOptions(getRemotePoolingOptions());
|
||||
bean.setRetryPolicy(getRetryPolicy());
|
||||
bean.setShutdownScripts(getShutdownScripts());
|
||||
bean.setSocketOptions(getSocketOptions());
|
||||
bean.setStartupScripts(getStartupScripts());
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CassandraSessionFactoryBean session() throws Exception {
|
||||
|
||||
Cluster cluster = cluster().getObject();
|
||||
|
||||
CassandraSessionFactoryBean bean = new CassandraSessionFactoryBean();
|
||||
bean.setCluster(cluster);
|
||||
bean.setKeyspaceName(getKeyspaceName());
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CassandraOperations template() throws Exception {
|
||||
return new CassandraTemplate(session().getObject());
|
||||
}
|
||||
|
||||
protected List<String> getStartupScripts() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected SocketOptionsConfig getSocketOptions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected List<String> getShutdownScripts() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected ReconnectionPolicy getReconnectionPolicy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected RetryPolicy getRetryPolicy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected PoolingOptionsConfig getRemotePoolingOptions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected int getPort() {
|
||||
return CassandraClusterFactoryBean.DEFAULT_PORT;
|
||||
}
|
||||
|
||||
protected boolean getMetricsEnabled() {
|
||||
return CassandraClusterFactoryBean.DEFAULT_METRICS_ENABLED;
|
||||
}
|
||||
|
||||
protected PoolingOptionsConfig getLocalPoolingOptions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected LoadBalancingPolicy getLoadBalancingPolicy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected List<DropKeyspaceSpecification> getKeyspaceDrops() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected String getContactPoints() {
|
||||
return CassandraClusterFactoryBean.DEFAULT_CONTACT_POINTS;
|
||||
}
|
||||
|
||||
protected CompressionType getCompressionType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected AuthProvider getAuthProvider() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.cassandra.config.xml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -23,6 +26,7 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.cassandra.config.CassandraSessionFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Parser for <session> definitions.
|
||||
@@ -38,10 +42,6 @@ public class CassandraSessionParser extends AbstractSimpleBeanDefinitionParser {
|
||||
return CassandraSessionFactoryBean.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
@@ -64,5 +64,30 @@ public class CassandraSessionParser extends AbstractSimpleBeanDefinitionParser {
|
||||
clusterRef = BeanNames.CASSANDRA_CLUSTER;
|
||||
}
|
||||
builder.addPropertyReference("cluster", clusterRef);
|
||||
|
||||
parseChildElements(element, builder);
|
||||
}
|
||||
|
||||
protected void parseChildElements(Element element, BeanDefinitionBuilder builder) {
|
||||
|
||||
List<String> scripts = parseScripts(element, "startup-cql");
|
||||
builder.addPropertyValue("startupScripts", scripts);
|
||||
|
||||
scripts = parseScripts(element, "shutdown-cql");
|
||||
builder.addPropertyValue("shutdownScripts", scripts);
|
||||
}
|
||||
|
||||
protected List<String> parseScripts(Element element, String elementName) {
|
||||
|
||||
NodeList nodes = element.getElementsByTagName("startup-cql");
|
||||
int length = nodes.getLength();
|
||||
List<String> scripts = new ArrayList<String>(length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
Element script = (Element) nodes.item(i);
|
||||
scripts.add(script.getTextContent());
|
||||
}
|
||||
|
||||
return scripts;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* Builder for maps, which also conveniently implements {@link Map} via delegation for convenience so you don't have to
|
||||
* actually {@link #build()} it (or forget to).
|
||||
* actually {@link #build()} it.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
* @param <K> The key type of the map.
|
||||
@@ -83,58 +83,72 @@ public class MapBuilder<K, V> implements Map<K, V> {
|
||||
return new LinkedHashMap<K, V>(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return map.containsValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
map.putAll(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<java.util.Map.Entry<K, V>> entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return map.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return map.hashCode();
|
||||
}
|
||||
|
||||
@@ -337,6 +337,27 @@ Sets the SO_SNDBUF socket option.
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="sessionType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="startup-cql" type="xsd:string"
|
||||
minOccurs="0" maxOccurs="unbounded">
|
||||
<!-- TODO: cql could come from a resource via a resource attribute... -->
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Arbitrary CQL script to be executed against the session's keyspace during bean initialization. Multiple elements will be executed in document order.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="shutdown-cql" type="xsd:string"
|
||||
minOccurs="0" maxOccurs="unbounded">
|
||||
<!-- TODO: cql could come from a resource via a resource attribute... -->
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Arbitrary CQL script to be executed against the session's keyspace during bean destruction. Multiple elements will be executed in document order.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.datastax.driver.core.Session;
|
||||
public abstract class AbstractIntegrationTest extends AbstractEmbeddedCassandraIntegrationTest {
|
||||
|
||||
@Inject
|
||||
public Session session;
|
||||
protected Session session;
|
||||
|
||||
@Before
|
||||
public void assertSession() {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import org.springframework.cassandra.config.KeyspaceAttributes;
|
||||
import org.springframework.cassandra.config.PoolingOptionsConfig;
|
||||
import org.springframework.cassandra.config.SocketOptionsConfig;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -38,20 +35,4 @@ public abstract class AbstractKeyspaceCreatingConfiguration extends AbstractInte
|
||||
+ " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };");
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
protected KeyspaceAttributes getKeyspaceAttributes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected PoolingOptionsConfig getLocalPoolingOptionsConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected PoolingOptionsConfig getRemotePoolingOptionsConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected SocketOptionsConfig getSocketOptionsConfig() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class KeyspaceCreatingConfig extends AbstractKeyspaceCreatingConfiguration {
|
||||
|
||||
public static final String KEYSPACE = "kcc";
|
||||
|
||||
@Override
|
||||
protected String getKeyspaceName() {
|
||||
return KEYSPACE;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
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)
|
||||
public class KeyspaceCreatingConfigTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
IntegrationTestUtils.assertKeyspaceExists(KeyspaceCreatingConfig.KEYSPACE, session);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cassandra.config.KeyspaceAttributes;
|
||||
import org.springframework.cassandra.config.java.AbstractCassandraFactoryBeanConfiguration;
|
||||
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
|
||||
import org.springframework.cassandra.core.keyspace.KeyspaceOption;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class KeyspaceCreatingJavaConfig extends AbstractCassandraFactoryBeanConfiguration {
|
||||
|
||||
public static final String KEYSPACE_NAME = "foo";
|
||||
|
||||
@Override
|
||||
protected String getKeyspaceName() {
|
||||
return KEYSPACE_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
|
||||
ArrayList<CreateKeyspaceSpecification> list = new ArrayList<CreateKeyspaceSpecification>();
|
||||
|
||||
CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace().name(getKeyspaceName());
|
||||
specification.with(KeyspaceOption.REPLICATION, KeyspaceAttributes.newSimpleReplication(1L));
|
||||
|
||||
list.add(specification);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.springframework.cassandra.test.integration.config.java;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
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(classes = KeyspaceCreatingJavaConfig.class)
|
||||
public class KeyspaceCreatingJavaConfigTest extends AbstractIntegrationTest {
|
||||
|
||||
@Inject
|
||||
protected Session session;
|
||||
|
||||
@Override
|
||||
protected String keyspace() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Assert.assertNotNull(session);
|
||||
IntegrationTestUtils.assertKeyspaceExists(KeyspaceCreatingJavaConfig.KEYSPACE_NAME, session);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cassandra.config.KeyspaceAttributes;
|
||||
import org.springframework.cassandra.core.cql.generator.CreateKeyspaceCqlGenerator;
|
||||
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
|
||||
import org.springframework.cassandra.core.keyspace.DefaultOption;
|
||||
@@ -23,9 +24,10 @@ public class CreateKeyspaceCqlGeneratorTests {
|
||||
|
||||
private static void assertReplicationMap(Map<Option, Object> replicationMap, String cql) {
|
||||
assertTrue(cql.contains(" WITH replication = { "));
|
||||
|
||||
for (Map.Entry<Option, Object> entry : replicationMap.entrySet() ) {
|
||||
String keyValuePair = "'" + entry.getKey().getName() + "' : '" + entry.getValue().toString() + "'";
|
||||
|
||||
for (Map.Entry<Option, Object> entry : replicationMap.entrySet()) {
|
||||
String keyValuePair = "'" + entry.getKey().getName() + "' : " + (entry.getKey().quotesValue() ? "'" : "")
|
||||
+ entry.getValue().toString() + (entry.getKey().quotesValue() ? "'" : "");
|
||||
assertTrue(cql.contains(keyValuePair));
|
||||
}
|
||||
}
|
||||
@@ -41,6 +43,7 @@ public class CreateKeyspaceCqlGeneratorTests {
|
||||
public static abstract class CreateKeyspaceTest extends
|
||||
KeyspaceOperationCqlGeneratorTest<CreateKeyspaceSpecification, CreateKeyspaceCqlGenerator> {
|
||||
|
||||
@Override
|
||||
public CreateKeyspaceCqlGenerator generator() {
|
||||
return new CreateKeyspaceCqlGenerator(specification);
|
||||
}
|
||||
@@ -50,20 +53,15 @@ public class CreateKeyspaceCqlGeneratorTests {
|
||||
|
||||
public String name = "mykeyspace";
|
||||
public Boolean durableWrites = true;
|
||||
|
||||
public Map<Option, Object> replicationMap = new HashMap<Option, Object>();
|
||||
|
||||
public Map<Option, Object> replicationMap = KeyspaceAttributes.newSimpleReplication();
|
||||
|
||||
@Override
|
||||
public CreateKeyspaceSpecification specification() {
|
||||
keyspace = name;
|
||||
|
||||
replicationMap.put( new DefaultOption( "class", String.class, false, false, true ), "SimpleStrategy" );
|
||||
replicationMap.put( new DefaultOption( "replication_factor", Long.class, false, false, true ), 1 );
|
||||
|
||||
return (CreateKeyspaceSpecification) CreateKeyspaceSpecification.createKeyspace()
|
||||
.name(keyspace)
|
||||
.with(KeyspaceOption.REPLICATION, replicationMap)
|
||||
.with(KeyspaceOption.DURABLE_WRITES, durableWrites);
|
||||
|
||||
return CreateKeyspaceSpecification.createKeyspace().name(keyspace)
|
||||
.with(KeyspaceOption.REPLICATION, replicationMap).with(KeyspaceOption.DURABLE_WRITES, durableWrites);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -80,21 +78,19 @@ public class CreateKeyspaceCqlGeneratorTests {
|
||||
|
||||
public String name = "mykeyspace";
|
||||
public Boolean durableWrites = false;
|
||||
|
||||
|
||||
public Map<Option, Object> replicationMap = new HashMap<Option, Object>();
|
||||
|
||||
@Override
|
||||
public CreateKeyspaceSpecification specification() {
|
||||
keyspace = name;
|
||||
|
||||
replicationMap.put( new DefaultOption( "class", String.class, false, false, true ), "NetworkTopologyStrategy" );
|
||||
replicationMap.put( new DefaultOption( "dc1", Long.class, false, false, true ), 2 );
|
||||
replicationMap.put( new DefaultOption( "dc2", Long.class, false, false, true ), 3 );
|
||||
|
||||
return (CreateKeyspaceSpecification) CreateKeyspaceSpecification.createKeyspace()
|
||||
.name(keyspace)
|
||||
.with(KeyspaceOption.REPLICATION, replicationMap)
|
||||
.with(KeyspaceOption.DURABLE_WRITES, durableWrites);
|
||||
|
||||
replicationMap.put(new DefaultOption("class", String.class, false, false, true), "NetworkTopologyStrategy");
|
||||
replicationMap.put(new DefaultOption("dc1", Long.class, false, false, true), 2);
|
||||
replicationMap.put(new DefaultOption("dc2", Long.class, false, false, true), 3);
|
||||
|
||||
return CreateKeyspaceSpecification.createKeyspace().name(keyspace)
|
||||
.with(KeyspaceOption.REPLICATION, replicationMap).with(KeyspaceOption.DURABLE_WRITES, durableWrites);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.context" level="info" />
|
||||
<logger name="org.springframework.cassandra" level="info" />
|
||||
<logger name="org.springframework.data.cassandra" level="info" />
|
||||
<logger name="org.springframework.data.cassandra" level="info" />
|
||||
<logger name="com.datastax" level="info" />
|
||||
|
||||
<root level="warn">
|
||||
<appender-ref ref="console" />
|
||||
|
||||
Reference in New Issue
Block a user