diff --git a/pom.xml b/pom.xml index 3bf5705a0..ce8ee5b84 100644 --- a/pom.xml +++ b/pom.xml @@ -273,6 +273,40 @@ + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + reserve-network-port + + reserve-network-port + + process-resources + + + build.cassandra.native_transport_port + build.cassandra.rpc_port + build.cassandra.storage_port + build.cassandra.ssl_storage_port + + + + + add-shared-source-dir + + add-test-source + + generate-test-sources + + + ../shared/src/test/java + + + + + org.apache.maven.plugins maven-dependency-plugin @@ -304,6 +338,7 @@ 1 -Xmx1024m -Xss512m -javaagent:${com.github.stephenc:jamm:jar} + true false **/test/integration/**/*.java @@ -326,5 +361,31 @@ + + + + src/main/resources + true + + **/* + + + + + + src/test/resources + true + + **/* + + + + ../shared/src/test/resources + true + + **/* + + + diff --git a/shared/src/test/java/org/springframework/cassandra/test/integration/support/AbstractTestJavaConfig.java b/shared/src/test/java/org/springframework/cassandra/test/integration/support/AbstractTestJavaConfig.java new file mode 100644 index 000000000..9e957e5d5 --- /dev/null +++ b/shared/src/test/java/org/springframework/cassandra/test/integration/support/AbstractTestJavaConfig.java @@ -0,0 +1,16 @@ +package org.springframework.cassandra.test.integration.support; + +import org.springframework.cassandra.config.java.AbstractCassandraConfiguration; +import org.springframework.context.annotation.Configuration; + +@Configuration +public abstract class AbstractTestJavaConfig extends AbstractCassandraConfiguration { + + public static BuildProperties PROPS = new BuildProperties(); + public static final int PORT = PROPS.getCassandraPort(); + + @Override + protected int getPort() { + return PORT; + } +} diff --git a/shared/src/test/java/org/springframework/cassandra/test/integration/support/BuildProperties.java b/shared/src/test/java/org/springframework/cassandra/test/integration/support/BuildProperties.java new file mode 100644 index 000000000..2a07fda77 --- /dev/null +++ b/shared/src/test/java/org/springframework/cassandra/test/integration/support/BuildProperties.java @@ -0,0 +1,64 @@ +package org.springframework.cassandra.test.integration.support; + +import java.io.InputStream; +import java.util.Properties; + +@SuppressWarnings("serial") +public class BuildProperties extends Properties { + + public BuildProperties() { + this("/build.properties"); + } + + public BuildProperties(String resourceName) { + loadProperties(resourceName); + } + + public void loadProperties(String resourceName) { + InputStream in = null; + try { + in = getClass().getResourceAsStream(resourceName); + if (in == null) { + return; + } + load(in); + + } catch (Exception x) { + throw new RuntimeException(x); + + } finally { + if (in != null) { + try { + in.close(); + } catch (Exception e) { + // gulp + } + } + } + } + + public int getCassandraPort() { + return getInt("build.cassandra.native_transport_port"); + } + + public int getCassandraRpcPort() { + return getInt("build.cassandra.rpc_port"); + } + + public int getCassandraStoragePort() { + return getInt("build.cassandra.storage_port"); + } + + public int getCassandraSslStoragePort() { + return getInt("build.cassandra.ssl_storage_port"); + } + + public int getInt(String key) { + String property = getProperty(key); + return Integer.parseInt(property); + } + + public boolean getBoolean(String key) { + return Boolean.parseBoolean(getProperty(key)); + } +} diff --git a/shared/src/test/resources/build.properties b/shared/src/test/resources/build.properties new file mode 100644 index 000000000..ba2281c73 --- /dev/null +++ b/shared/src/test/resources/build.properties @@ -0,0 +1,4 @@ +build.cassandra.native_transport_port=@build.cassandra.native_transport_port@ +build.cassandra.rpc_port=@build.cassandra.rpc_port@ +build.cassandra.storage_port=@build.cassandra.storage_port@ +build.cassandra.ssl_storage_port=@build.cassandra.ssl_storage_port@ diff --git a/spring-cassandra/pom.xml b/spring-cassandra/pom.xml index f675f2771..26dd63c0b 100644 --- a/spring-cassandra/pom.xml +++ b/spring-cassandra/pom.xml @@ -41,6 +41,21 @@ org.springframework spring-tx + + ${project.groupId} + spring-data-commons + ${springdata.commons} + + + com.datastax.cassandra + cassandra-driver-core + + + log4j + log4j + + + javax.enterprise cdi-api diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/CassandraClusterFactoryBean.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/CassandraClusterFactoryBean.java index cdd63f6c4..acb7375af 100644 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/config/CassandraClusterFactoryBean.java +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/CassandraClusterFactoryBean.java @@ -16,8 +16,10 @@ package org.springframework.cassandra.config; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,7 +31,7 @@ import org.springframework.cassandra.core.cql.generator.CreateKeyspaceCqlGenerat import org.springframework.cassandra.core.cql.generator.DropKeyspaceCqlGenerator; import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification; import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification; -import org.springframework.cassandra.core.keyspace.KeyspaceNameSpecification; +import org.springframework.cassandra.core.keyspace.KeyspaceActionSpecification; import org.springframework.cassandra.support.CassandraExceptionTranslator; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; @@ -37,9 +39,11 @@ import org.springframework.util.StringUtils; import com.datastax.driver.core.AuthProvider; import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.HostDistance; +import com.datastax.driver.core.Host; +import com.datastax.driver.core.LatencyTracker; import com.datastax.driver.core.PoolingOptions; import com.datastax.driver.core.ProtocolOptions.Compression; +import com.datastax.driver.core.SSLOptions; import com.datastax.driver.core.Session; import com.datastax.driver.core.SocketOptions; import com.datastax.driver.core.policies.LoadBalancingPolicy; @@ -51,32 +55,44 @@ import com.datastax.driver.core.policies.RetryPolicy; * * @author Alex Shvid * @author Matthew T. Adams + * @author David Webb */ public class CassandraClusterFactoryBean implements FactoryBean, InitializingBean, DisposableBean, PersistenceExceptionTranslator { public static final String DEFAULT_CONTACT_POINTS = "localhost"; public static final boolean DEFAULT_METRICS_ENABLED = true; + public static final boolean DEFAULT_DEFERRED_INITIALIZATION = false; + public static final boolean DEFAULT_JMX_REPORTING_ENABLED = true; + public static final boolean DEFAULT_SSL_ENABLED = false; public static final int DEFAULT_PORT = 9042; protected static final Logger log = LoggerFactory.getLogger(CassandraClusterFactoryBean.class); private Cluster cluster; - /** - * Comma-delimited string of servers. + /* + * Attributes needed for cluster builder */ 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 PoolingOptions poolingOptions; + private SocketOptions socketOptions; private AuthProvider authProvider; + private String username; + private String password; private LoadBalancingPolicy loadBalancingPolicy; private ReconnectionPolicy reconnectionPolicy; private RetryPolicy retryPolicy; private boolean metricsEnabled = DEFAULT_METRICS_ENABLED; + private boolean deferredInitialization = DEFAULT_DEFERRED_INITIALIZATION; + private boolean jmxReportingEnabled = DEFAULT_JMX_REPORTING_ENABLED; + private boolean sslEnabled = DEFAULT_SSL_ENABLED; + private SSLOptions sslOptions; + private Host.StateListener hostStateListener; + private LatencyTracker latencyTracker; + private Set> keyspaceSpecifications = new HashSet>(); private List keyspaceCreations = new ArrayList(); private List keyspaceDrops = new ArrayList(); private List startupScripts = new ArrayList(); @@ -119,20 +135,20 @@ public class CassandraClusterFactoryBean implements FactoryBean, Initia builder.withCompression(convertCompressionType(compressionType)); } - if (localPoolingOptions != null) { - builder.withPoolingOptions(configPoolingOptions(HostDistance.LOCAL, localPoolingOptions)); - } - - if (remotePoolingOptions != null) { - builder.withPoolingOptions(configPoolingOptions(HostDistance.REMOTE, remotePoolingOptions)); + if (poolingOptions != null) { + builder.withPoolingOptions(poolingOptions); } if (socketOptions != null) { - builder.withSocketOptions(configSocketOptions(socketOptions)); + builder.withSocketOptions(socketOptions); } if (authProvider != null) { builder.withAuthProvider(authProvider); + + if (username != null) { + builder.withCredentials(username, password); + } } if (loadBalancingPolicy != null) { @@ -147,14 +163,60 @@ public class CassandraClusterFactoryBean implements FactoryBean, Initia builder.withRetryPolicy(retryPolicy); } + if (deferredInitialization) { + builder.withDeferredInitialization(); + } + if (!metricsEnabled) { builder.withoutMetrics(); } + if (!jmxReportingEnabled) { + builder.withoutJMXReporting(); + } + + if (sslEnabled) { + if (sslOptions == null) { + builder.withSSL(); + } else { + builder.withSSL(sslOptions); + } + } + cluster = builder.build(); + + if (hostStateListener != null) { + cluster.register(hostStateListener); + } + + if (latencyTracker != null) { + cluster.register(latencyTracker); + } + + generateSpecificationsFromFactoryBeans(); + executeSpecsAndScripts(keyspaceCreations, startupScripts); } + /** + * Examines the contents of all the KeyspaceSpecificationFactoryBeans and generates the proper KeyspaceSpecification + * from them. + */ + private void generateSpecificationsFromFactoryBeans() { + + for (KeyspaceActionSpecification spec : keyspaceSpecifications) { + + if (spec instanceof CreateKeyspaceSpecification) { + keyspaceCreations.add((CreateKeyspaceSpecification) spec); + } + if (spec instanceof DropKeyspaceSpecification) { + keyspaceDrops.add((DropKeyspaceSpecification) spec); + } + + } + + } + protected void executeSpecsAndScripts(@SuppressWarnings("rawtypes") List specs, List scripts) { Session system = null; @@ -167,7 +229,7 @@ public class CassandraClusterFactoryBean implements FactoryBean, Initia Iterator i = specs.iterator(); while (i.hasNext()) { - KeyspaceNameSpecification spec = (KeyspaceNameSpecification) i.next(); + KeyspaceActionSpecification spec = (KeyspaceActionSpecification) i.next(); String cql = (spec instanceof CreateKeyspaceSpecification) ? new CreateKeyspaceCqlGenerator( (CreateKeyspaceSpecification) spec).toCql() : new DropKeyspaceCqlGenerator( (DropKeyspaceSpecification) spec).toCql(); @@ -229,15 +291,11 @@ public class CassandraClusterFactoryBean implements FactoryBean, Initia this.compressionType = compressionType; } - public void setLocalPoolingOptions(PoolingOptionsConfig localPoolingOptions) { - this.localPoolingOptions = localPoolingOptions; + public void setPoolingOptions(PoolingOptions poolingOptions) { + this.poolingOptions = poolingOptions; } - public void setRemotePoolingOptions(PoolingOptionsConfig remotePoolingOptions) { - this.remotePoolingOptions = remotePoolingOptions; - } - - public void setSocketOptions(SocketOptionsConfig socketOptions) { + public void setSocketOptions(SocketOptions socketOptions) { this.socketOptions = socketOptions; } @@ -295,52 +353,76 @@ public class CassandraClusterFactoryBean implements FactoryBean, Initia throw new IllegalArgumentException("unknown compression type " + type); } - private static PoolingOptions configPoolingOptions(HostDistance hostDistance, PoolingOptionsConfig config) { - PoolingOptions poolingOptions = new PoolingOptions(); - - if (config.getMinSimultaneousRequests() != null) { - poolingOptions - .setMinSimultaneousRequestsPerConnectionThreshold(hostDistance, config.getMinSimultaneousRequests()); - } - if (config.getMaxSimultaneousRequests() != null) { - poolingOptions - .setMaxSimultaneousRequestsPerConnectionThreshold(hostDistance, config.getMaxSimultaneousRequests()); - } - if (config.getCoreConnections() != null) { - poolingOptions.setCoreConnectionsPerHost(hostDistance, config.getCoreConnections()); - } - if (config.getMaxConnections() != null) { - poolingOptions.setMaxConnectionsPerHost(hostDistance, config.getMaxConnections()); - } - - return poolingOptions; + /** + * @return Returns the keyspaceSpecifications. + */ + public Set> getKeyspaceSpecifications() { + return keyspaceSpecifications; } - private static SocketOptions configSocketOptions(SocketOptionsConfig config) { - SocketOptions socketOptions = new SocketOptions(); + /** + * If accumlating is true, we append to the list, otherwise we replace the list. + * + * @param keyspaceSpecifications The keyspaceSpecifications to set. + */ + public void setKeyspaceSpecifications(Set> keyspaceSpecifications) { + log.info("Setter Called"); + this.keyspaceSpecifications = keyspaceSpecifications; + } - if (config.getConnectTimeoutMls() != null) { - socketOptions.setConnectTimeoutMillis(config.getConnectTimeoutMls()); - } - if (config.getKeepAlive() != null) { - socketOptions.setKeepAlive(config.getKeepAlive()); - } - if (config.getReuseAddress() != null) { - socketOptions.setReuseAddress(config.getReuseAddress()); - } - if (config.getSoLinger() != null) { - socketOptions.setSoLinger(config.getSoLinger()); - } - if (config.getTcpNoDelay() != null) { - socketOptions.setTcpNoDelay(config.getTcpNoDelay()); - } - if (config.getReceiveBufferSize() != null) { - socketOptions.setReceiveBufferSize(config.getReceiveBufferSize()); - } - if (config.getSendBufferSize() != null) { - socketOptions.setSendBufferSize(config.getSendBufferSize()); - } + /** + * @param username The username to set. + */ + public void setUsername(String username) { + this.username = username; + } - return socketOptions; + /** + * @param password The password to set. + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * @param deferredInitialization The deferredInitialization to set. + */ + public void setDeferredInitialization(boolean deferredInitialization) { + this.deferredInitialization = deferredInitialization; + } + + /** + * @param jmxReportingEnabled The jmxReportingEnabled to set. + */ + public void setJmxReportingEnabled(boolean jmxReportingEnabled) { + this.jmxReportingEnabled = jmxReportingEnabled; + } + + /** + * @param sslEnabled The sslEnabled to set. + */ + public void setSslEnabled(boolean sslEnabled) { + this.sslEnabled = sslEnabled; + } + + /** + * @param sslOptions The sslOptions to set. + */ + public void setSslOptions(SSLOptions sslOptions) { + this.sslOptions = sslOptions; + } + + /** + * @param hostStateListener The hostStateListener to set. + */ + public void setHostStateListener(Host.StateListener hostStateListener) { + this.hostStateListener = hostStateListener; + } + + /** + * @param latencyTracker The latencyTracker to set. + */ + public void setLatencyTracker(LatencyTracker latencyTracker) { + this.latencyTracker = latencyTracker; } } diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/KeyspaceAction.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/KeyspaceAction.java new file mode 100644 index 000000000..51f6e93c6 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/KeyspaceAction.java @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cassandra.config; + +/** + * Available actions for Keyspace Specifications + * + * @author David Webb + */ +public enum KeyspaceAction { + CREATE, CREATE_DROP, ALTER; +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/KeyspaceActionSpecificationFactoryBean.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/KeyspaceActionSpecificationFactoryBean.java new file mode 100644 index 000000000..e44d16587 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/KeyspaceActionSpecificationFactoryBean.java @@ -0,0 +1,267 @@ +/* + * Copyright 2011-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cassandra.config; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +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.keyspace.CreateKeyspaceSpecification; +import org.springframework.cassandra.core.keyspace.DefaultOption; +import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification; +import org.springframework.cassandra.core.keyspace.KeyspaceActionSpecification; +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.util.Assert; + +/** + * A single keyspace XML Element can result in multiple actions. Example: {@literal CREATE_DROP}. + * + * This FactoryBean inspects the action required to satisfy the keyspace element, and then returns a Set of atomic + * {@link KeyspaceActionSpecification} required to satisfy the configuration action. + * + * @author David Webb + * + */ +public class KeyspaceActionSpecificationFactoryBean implements FactoryBean>>, + InitializingBean, DisposableBean { + + private final static Logger log = LoggerFactory.getLogger(KeyspaceActionSpecificationFactoryBean.class); + + private KeyspaceAction action; + private String name; + private List networkTopologyDataCenters = new LinkedList(); + private List networkTopologyReplicationFactors = new LinkedList(); + private String replicationStrategy; + private long replicationFactor; + private boolean durableWrites = false; + private boolean ifNotExists = false; + + private Set> specs = new HashSet>(); + + @Override + public void destroy() throws Exception { + action = null; + name = null; + networkTopologyDataCenters = null; + networkTopologyReplicationFactors = null; + replicationStrategy = null; + specs = null; + } + + @Override + public void afterPropertiesSet() throws Exception { + + Assert.hasText(name, "Keyspace Name is required for a Keyspace Action"); + Assert.notNull(action, "Keyspace Action is required for a Keyspace Action"); + + switch (action) { + case CREATE_DROP: + specs.add(generateDropKeyspaceSpecification()); + case CREATE: + // Assert.notNull(replicationStrategy, "Replication Strategy is required to create a Keyspace"); + specs.add(generateCreateKeyspaceSpecification()); + break; + case ALTER: + break; + } + + } + + /** + * Generate a {@link CreateKeyspaceSpecification} for the keyspace. + * + * @return The {@link CreateKeyspaceSpecification} + */ + private CreateKeyspaceSpecification generateCreateKeyspaceSpecification() { + + CreateKeyspaceSpecification create = new CreateKeyspaceSpecification(); + create.name(name).ifNotExists(ifNotExists).with(KeyspaceOption.DURABLE_WRITES, durableWrites); + + Map replicationStrategyMap = new HashMap(); + replicationStrategyMap.put(new DefaultOption("class", String.class, true, false, true), ReplicationStrategy + .valueOf(replicationStrategy).getValue()); + + /* + * Just set replication factor for SimpleStrategy + */ + if (replicationStrategy.equals(ReplicationStrategy.SIMPLE_STRATEGY.name())) { + replicationStrategyMap.put(new DefaultOption("replication_factor", Long.class, true, false, false), + replicationFactor); + } + + if (replicationStrategy.equals(ReplicationStrategy.NETWORK_TOPOLOGY_STRATEGY.name())) { + int i = 0; + for (String datacenter : networkTopologyDataCenters) { + replicationStrategyMap.put(new DefaultOption(datacenter, Long.class, true, false, false), + networkTopologyReplicationFactors.get(i)); + i++; + } + } + + create.with(KeyspaceOption.REPLICATION, replicationStrategyMap); + + return create; + } + + /** + * Generate a {@link DropKeyspaceSpecification} for the keyspace. + * + * @return The {@link DropKeyspaceSpecification} + */ + private DropKeyspaceSpecification generateDropKeyspaceSpecification() { + DropKeyspaceSpecification drop = new DropKeyspaceSpecification(); + drop.name(getName()); + return drop; + } + + @Override + public Set> getObject() throws Exception { + return specs; + } + + @Override + public Class getObjectType() { + return Set.class; + } + + @Override + public boolean isSingleton() { + return false; + } + + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + + /** + * @param name The name to set. + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return Returns the ifNotExists. + */ + public boolean isIfNotExists() { + return ifNotExists; + } + + /** + * @param ifNotExists The ifNotExists to set. + */ + public void setIfNotExists(boolean ifNotExists) { + this.ifNotExists = ifNotExists; + } + + /** + * @return Returns the action. + */ + public KeyspaceAction getAction() { + return action; + } + + /** + * @param action The action to set. + */ + public void setAction(KeyspaceAction action) { + this.action = action; + } + + /** + * @return Returns the durableWrites. + */ + public boolean isDurableWrites() { + return durableWrites; + } + + /** + * @param durableWrites The durableWrites to set. + */ + public void setDurableWrites(boolean durableWrites) { + this.durableWrites = durableWrites; + } + + /** + * @return Returns the replicationStrategy. + */ + public String getReplicationStrategy() { + return replicationStrategy; + } + + /** + * @param replicationStrategy The replicationStrategy to set. + */ + public void setReplicationStrategy(String replicationStrategy) { + this.replicationStrategy = replicationStrategy; + } + + /** + * @return Returns the networkTopologyDataCenters. + */ + public List getNetworkTopologyDataCenters() { + return networkTopologyDataCenters; + } + + /** + * @param networkTopologyDataCenters The networkTopologyDataCenters to set. + */ + public void setNetworkTopologyDataCenters(List networkTopologyDataCenters) { + this.networkTopologyDataCenters = networkTopologyDataCenters; + } + + /** + * @return Returns the networkTopologyReplicationFactors. + */ + public List getNetworkTopologyReplicationFactors() { + return networkTopologyReplicationFactors; + } + + /** + * @param networkTopologyReplicationFactors The networkTopologyReplicationFactors to set. + */ + public void setNetworkTopologyReplicationFactors(List networkTopologyReplicationFactors) { + this.networkTopologyReplicationFactors = networkTopologyReplicationFactors; + } + + /** + * @return Returns the replicationFactor. + */ + public long getReplicationFactor() { + return replicationFactor; + } + + /** + * @param replicationFactor The replicationFactor to set. + */ + public void setReplicationFactor(long replicationFactor) { + this.replicationFactor = replicationFactor; + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/MultiLevelListFlattenerFactoryBean.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/MultiLevelListFlattenerFactoryBean.java new file mode 100644 index 000000000..baf973256 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/MultiLevelListFlattenerFactoryBean.java @@ -0,0 +1,71 @@ +/* + * Copyright 2011-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cassandra.config; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.FactoryBean; + +/** + * Given List of Lists where all child Lists contain the same class, then a single level List of is generated. + * + * @author David Webb + * @param + * + */ +public class MultiLevelListFlattenerFactoryBean implements FactoryBean> { + + private List> multiLevelList; + + @Override + public List getObject() throws Exception { + List list = new ArrayList(); + + for (List topList : multiLevelList) { + for (T t : topList) { + list.add(t); + } + } + + return list; + } + + @Override + public Class getObjectType() { + return List.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + /** + * @return Returns the multiLevelList. + */ + public List> getMultiLevelList() { + return multiLevelList; + } + + /** + * @param multiLevelList The multiLevelList to set. + */ + public void setMultiLevelList(List> multiLevelList) { + this.multiLevelList = multiLevelList; + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/MultiLevelSetFlattenerFactoryBean.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/MultiLevelSetFlattenerFactoryBean.java new file mode 100644 index 000000000..7692c7023 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/MultiLevelSetFlattenerFactoryBean.java @@ -0,0 +1,77 @@ +/* + * Copyright 2011-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cassandra.config; + +import java.util.HashSet; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.FactoryBean; + +/** + * Given Set of Sets where all child Sets contain the same class, then a single level Set of is generated. + * + * @author David Webb + * @param + * + */ +public class MultiLevelSetFlattenerFactoryBean implements FactoryBean> { + + private final static Logger log = LoggerFactory.getLogger(MultiLevelSetFlattenerFactoryBean.class); + + private Set> multiLevelSet; + + @Override + public Set getObject() throws Exception { + Set set = new HashSet(); + + for (Set topSet : multiLevelSet) { + for (T t : topSet) { + log.info(t.toString()); + log.info("Set contains -> " + set.contains(t)); + set.add(t); + } + } + + return set; + } + + @Override + public Class getObjectType() { + return Set.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + /** + * @return Returns the multiLevelSet. + */ + public Set> getMultiLevelSet() { + return multiLevelSet; + } + + /** + * @param multiLevelSet The multiLevelSet to set. + */ + public void setMultiLevelSet(Set> multiLevelSet) { + this.multiLevelSet = multiLevelSet; + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/PoolingOptionsConfig.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/PoolingOptionsConfig.java deleted file mode 100644 index e982e217d..000000000 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/config/PoolingOptionsConfig.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.cassandra.config; - -/** - * Pooling options. - * - * @author Alex Shvid - * @author Matthew T. Adams - */ -public class PoolingOptionsConfig { - - private Integer minSimultaneousRequests; - private Integer maxSimultaneousRequests; - private Integer coreConnections; - private Integer maxConnections; - - public Integer getMinSimultaneousRequests() { - return minSimultaneousRequests; - } - - public void setMinSimultaneousRequests(Integer minSimultaneousRequests) { - this.minSimultaneousRequests = minSimultaneousRequests; - } - - public Integer getMaxSimultaneousRequests() { - return maxSimultaneousRequests; - } - - public void setMaxSimultaneousRequests(Integer maxSimultaneousRequests) { - this.maxSimultaneousRequests = maxSimultaneousRequests; - } - - public Integer getCoreConnections() { - return coreConnections; - } - - public void setCoreConnections(Integer coreConnections) { - this.coreConnections = coreConnections; - } - - public Integer getMaxConnections() { - return maxConnections; - } - - public void setMaxConnections(Integer maxConnections) { - this.maxConnections = maxConnections; - } -} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/PoolingOptionsFactoryBean.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/PoolingOptionsFactoryBean.java new file mode 100644 index 000000000..d9f4489b3 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/PoolingOptionsFactoryBean.java @@ -0,0 +1,224 @@ +/* + * Copyright 2011-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cassandra.config; + +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; + +import com.datastax.driver.core.HostDistance; +import com.datastax.driver.core.PoolingOptions; + +/** + * Pooling Options Factory Bean. + * + * @author Matthew T. Adams + * @author David Webb + */ +public class PoolingOptionsFactoryBean implements FactoryBean, InitializingBean, DisposableBean { + + private Integer localMinSimultaneousRequests; + private Integer localMaxSimultaneousRequests; + private Integer localCoreConnections; + private Integer localMaxConnections; + private Integer remoteMinSimultaneousRequests; + private Integer remoteMaxSimultaneousRequests; + private Integer remoteCoreConnections; + private Integer remoteMaxConnections; + + PoolingOptions poolingOptions; + + @Override + public void destroy() throws Exception { + localMinSimultaneousRequests = null; + localMaxSimultaneousRequests = null; + localCoreConnections = null; + localMaxConnections = null; + remoteMinSimultaneousRequests = null; + remoteMaxSimultaneousRequests = null; + remoteCoreConnections = null; + remoteMaxConnections = null; + } + + @Override + public void afterPropertiesSet() throws Exception { + + poolingOptions = new PoolingOptions(); + + if (localMinSimultaneousRequests != null) { + poolingOptions.setMinSimultaneousRequestsPerConnectionThreshold(HostDistance.LOCAL, localMinSimultaneousRequests); + } + + if (localMaxSimultaneousRequests != null) { + poolingOptions.setMaxSimultaneousRequestsPerConnectionThreshold(HostDistance.LOCAL, localMaxSimultaneousRequests); + } + + if (localCoreConnections != null) { + poolingOptions.setCoreConnectionsPerHost(HostDistance.LOCAL, localCoreConnections); + } + + if (localMaxConnections != null) { + poolingOptions.setMaxConnectionsPerHost(HostDistance.LOCAL, localMaxConnections); + } + + if (remoteMinSimultaneousRequests != null) { + poolingOptions.setMinSimultaneousRequestsPerConnectionThreshold(HostDistance.REMOTE, + remoteMinSimultaneousRequests); + } + + if (remoteMaxSimultaneousRequests != null) { + poolingOptions.setMaxSimultaneousRequestsPerConnectionThreshold(HostDistance.REMOTE, + remoteMaxSimultaneousRequests); + } + + if (remoteCoreConnections != null) { + poolingOptions.setCoreConnectionsPerHost(HostDistance.REMOTE, remoteCoreConnections); + } + + if (remoteMaxConnections != null) { + poolingOptions.setMaxConnectionsPerHost(HostDistance.REMOTE, remoteMaxConnections); + } + + } + + @Override + public PoolingOptions getObject() throws Exception { + return poolingOptions; + } + + @Override + public Class getObjectType() { + return PoolingOptions.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + /** + * @return Returns the localMinSimultaneousRequests. + */ + public Integer getLocalMinSimultaneousRequests() { + return localMinSimultaneousRequests; + } + + /** + * @param localMinSimultaneousRequests The localMinSimultaneousRequests to set. + */ + public void setLocalMinSimultaneousRequests(Integer localMinSimultaneousRequests) { + this.localMinSimultaneousRequests = localMinSimultaneousRequests; + } + + /** + * @return Returns the localMaxSimultaneousRequests. + */ + public Integer getLocalMaxSimultaneousRequests() { + return localMaxSimultaneousRequests; + } + + /** + * @param localMaxSimultaneousRequests The localMaxSimultaneousRequests to set. + */ + public void setLocalMaxSimultaneousRequests(Integer localMaxSimultaneousRequests) { + this.localMaxSimultaneousRequests = localMaxSimultaneousRequests; + } + + /** + * @return Returns the localCoreConnections. + */ + public Integer getLocalCoreConnections() { + return localCoreConnections; + } + + /** + * @param localCoreConnections The localCoreConnections to set. + */ + public void setLocalCoreConnections(Integer localCoreConnections) { + this.localCoreConnections = localCoreConnections; + } + + /** + * @return Returns the localMaxConnections. + */ + public Integer getLocalMaxConnections() { + return localMaxConnections; + } + + /** + * @param localMaxConnections The localMaxConnections to set. + */ + public void setLocalMaxConnections(Integer localMaxConnections) { + this.localMaxConnections = localMaxConnections; + } + + /** + * @return Returns the remoteMinSimultaneousRequests. + */ + public Integer getRemoteMinSimultaneousRequests() { + return remoteMinSimultaneousRequests; + } + + /** + * @param remoteMinSimultaneousRequests The remoteMinSimultaneousRequests to set. + */ + public void setRemoteMinSimultaneousRequests(Integer remoteMinSimultaneousRequests) { + this.remoteMinSimultaneousRequests = remoteMinSimultaneousRequests; + } + + /** + * @return Returns the remoteMaxSimultaneousRequests. + */ + public Integer getRemoteMaxSimultaneousRequests() { + return remoteMaxSimultaneousRequests; + } + + /** + * @param remoteMaxSimultaneousRequests The remoteMaxSimultaneousRequests to set. + */ + public void setRemoteMaxSimultaneousRequests(Integer remoteMaxSimultaneousRequests) { + this.remoteMaxSimultaneousRequests = remoteMaxSimultaneousRequests; + } + + /** + * @return Returns the remoteCoreConnections. + */ + public Integer getRemoteCoreConnections() { + return remoteCoreConnections; + } + + /** + * @param remoteCoreConnections The remoteCoreConnections to set. + */ + public void setRemoteCoreConnections(Integer remoteCoreConnections) { + this.remoteCoreConnections = remoteCoreConnections; + } + + /** + * @return Returns the remoteMaxConnections. + */ + public Integer getRemoteMaxConnections() { + return remoteMaxConnections; + } + + /** + * @param remoteMaxConnections The remoteMaxConnections to set. + */ + public void setRemoteMaxConnections(Integer remoteMaxConnections) { + this.remoteMaxConnections = remoteMaxConnections; + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/SocketOptionsConfig.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/SocketOptionsConfig.java deleted file mode 100644 index 562377415..000000000 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/config/SocketOptionsConfig.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2011-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.cassandra.config; - -/** - * Socket options. - * - * @author Alex Shvid - * @author Matthew T. Adams - */ -public class SocketOptionsConfig { - - private Integer connectTimeoutMls; - private Boolean keepAlive; - private Boolean reuseAddress; - private Integer soLinger; - private Boolean tcpNoDelay; - private Integer receiveBufferSize; - private Integer sendBufferSize; - - public Integer getConnectTimeoutMls() { - return connectTimeoutMls; - } - - public void setConnectTimeoutMls(Integer connectTimeoutMls) { - this.connectTimeoutMls = connectTimeoutMls; - } - - public Boolean getKeepAlive() { - return keepAlive; - } - - public void setKeepAlive(Boolean keepAlive) { - this.keepAlive = keepAlive; - } - - public Boolean getReuseAddress() { - return reuseAddress; - } - - public void setReuseAddress(Boolean reuseAddress) { - this.reuseAddress = reuseAddress; - } - - public Integer getSoLinger() { - return soLinger; - } - - public void setSoLinger(Integer soLinger) { - this.soLinger = soLinger; - } - - public Boolean getTcpNoDelay() { - return tcpNoDelay; - } - - public void setTcpNoDelay(Boolean tcpNoDelay) { - this.tcpNoDelay = tcpNoDelay; - } - - public Integer getReceiveBufferSize() { - return receiveBufferSize; - } - - public void setReceiveBufferSize(Integer receiveBufferSize) { - this.receiveBufferSize = receiveBufferSize; - } - - public Integer getSendBufferSize() { - return sendBufferSize; - } - - public void setSendBufferSize(Integer sendBufferSize) { - this.sendBufferSize = sendBufferSize; - } -} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/SocketOptionsFactoryBean.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/SocketOptionsFactoryBean.java new file mode 100644 index 000000000..164aac8e5 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/SocketOptionsFactoryBean.java @@ -0,0 +1,185 @@ +/* + * Copyright 2011-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cassandra.config; + +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; + +import com.datastax.driver.core.SocketOptions; + +/** + * Socket Options Factory Bean. + * + * @author Matthew T. Adams + * @author David Webb + */ +public class SocketOptionsFactoryBean implements FactoryBean, InitializingBean, DisposableBean { + + private Integer connectTimeoutMillis; + private Boolean keepAlive; + private Integer readTimeoutMillis; + private Boolean reuseAddress; + private Integer soLinger; + private Boolean tcpNoDelay; + private Integer receiveBufferSize; + private Integer sendBufferSize; + + SocketOptions socketOptions; + + @Override + public SocketOptions getObject() throws Exception { + return socketOptions; + } + + @Override + public Class getObjectType() { + return SocketOptions.class; + } + + @Override + public void destroy() throws Exception { + connectTimeoutMillis = null; + keepAlive = null; + readTimeoutMillis = null; + reuseAddress = null; + soLinger = null; + tcpNoDelay = null; + receiveBufferSize = null; + sendBufferSize = null; + } + + @Override + public void afterPropertiesSet() throws Exception { + + socketOptions = new SocketOptions(); + + if (connectTimeoutMillis != null) { + socketOptions.setConnectTimeoutMillis(connectTimeoutMillis); + } + + if (keepAlive != null) { + socketOptions.setKeepAlive(keepAlive); + } + + if (readTimeoutMillis != null) { + socketOptions.setReadTimeoutMillis(readTimeoutMillis); + } + + if (reuseAddress != null) { + socketOptions.setReuseAddress(reuseAddress); + } + + if (soLinger != null) { + socketOptions.setSoLinger(soLinger); + } + + if (tcpNoDelay != null) { + socketOptions.setTcpNoDelay(tcpNoDelay); + } + + if (receiveBufferSize != null) { + socketOptions.setReceiveBufferSize(receiveBufferSize); + } + + if (sendBufferSize != null) { + socketOptions.setSendBufferSize(sendBufferSize); + } + + } + + @Override + public boolean isSingleton() { + return true; + } + + public Boolean getKeepAlive() { + return keepAlive; + } + + public void setKeepAlive(Boolean keepAlive) { + this.keepAlive = keepAlive; + } + + public Boolean getReuseAddress() { + return reuseAddress; + } + + public void setReuseAddress(Boolean reuseAddress) { + this.reuseAddress = reuseAddress; + } + + public Integer getSoLinger() { + return soLinger; + } + + public void setSoLinger(Integer soLinger) { + this.soLinger = soLinger; + } + + public Boolean getTcpNoDelay() { + return tcpNoDelay; + } + + public void setTcpNoDelay(Boolean tcpNoDelay) { + this.tcpNoDelay = tcpNoDelay; + } + + public Integer getReceiveBufferSize() { + return receiveBufferSize; + } + + public void setReceiveBufferSize(Integer receiveBufferSize) { + this.receiveBufferSize = receiveBufferSize; + } + + public Integer getSendBufferSize() { + return sendBufferSize; + } + + public void setSendBufferSize(Integer sendBufferSize) { + this.sendBufferSize = sendBufferSize; + } + + /** + * @return Returns the connectTimeoutMillis. + */ + public Integer getConnectTimeoutMillis() { + return connectTimeoutMillis; + } + + /** + * @param connectTimeoutMillis The connectTimeoutMillis to set. + */ + public void setConnectTimeoutMillis(Integer connectTimeoutMillis) { + this.connectTimeoutMillis = connectTimeoutMillis; + } + + /** + * @return Returns the readTimeoutMillis. + */ + public Integer getReadTimeoutMillis() { + return readTimeoutMillis; + } + + /** + * @param readTimeoutMillis The readTimeoutMillis to set. + */ + public void setReadTimeoutMillis(Integer readTimeoutMillis) { + this.readTimeoutMillis = readTimeoutMillis; + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/java/AbstractCassandraConfiguration.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/java/AbstractCassandraConfiguration.java index b9f3bb682..6e116716f 100644 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/config/java/AbstractCassandraConfiguration.java +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/java/AbstractCassandraConfiguration.java @@ -6,10 +6,6 @@ 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; @@ -17,6 +13,8 @@ import org.springframework.context.annotation.Configuration; import com.datastax.driver.core.AuthProvider; import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.PoolingOptions; +import com.datastax.driver.core.SocketOptions; import com.datastax.driver.core.policies.LoadBalancingPolicy; import com.datastax.driver.core.policies.ReconnectionPolicy; import com.datastax.driver.core.policies.RetryPolicy; @@ -42,11 +40,10 @@ public abstract class AbstractCassandraConfiguration { 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.setPoolingOptions(getPoolingOptions()); bean.setRetryPolicy(getRetryPolicy()); bean.setShutdownScripts(getShutdownScripts()); bean.setSocketOptions(getSocketOptions()); @@ -71,7 +68,7 @@ public abstract class AbstractCassandraConfiguration { return Collections.emptyList(); } - protected SocketOptionsConfig getSocketOptions() { + protected SocketOptions getSocketOptions() { return null; } @@ -87,7 +84,7 @@ public abstract class AbstractCassandraConfiguration { return null; } - protected PoolingOptionsConfig getRemotePoolingOptions() { + protected PoolingOptions getPoolingOptions() { return null; } @@ -99,10 +96,6 @@ public abstract class AbstractCassandraConfiguration { return CassandraClusterFactoryBean.DEFAULT_METRICS_ENABLED; } - protected PoolingOptionsConfig getLocalPoolingOptions() { - return null; - } - protected LoadBalancingPolicy getLoadBalancingPolicy() { return null; } diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/config/xml/CassandraClusterParser.java b/spring-cassandra/src/main/java/org/springframework/cassandra/config/xml/CassandraClusterParser.java index b931fb325..b750d4faf 100644 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/config/xml/CassandraClusterParser.java +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/config/xml/CassandraClusterParser.java @@ -15,44 +15,47 @@ */ package org.springframework.cassandra.config.xml; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import static org.springframework.data.config.ParsingUtils.getSourceBeanDefinition; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.BeanDefinitionStoreException; 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.AbstractSimpleBeanDefinitionParser; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.support.ManagedSet; +import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.cassandra.config.CassandraClusterFactoryBean; -import org.springframework.cassandra.config.CompressionType; +import org.springframework.cassandra.config.KeyspaceActionSpecificationFactoryBean; import org.springframework.cassandra.config.KeyspaceAttributes; -import org.springframework.cassandra.config.PoolingOptionsConfig; -import org.springframework.cassandra.config.SocketOptionsConfig; -import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification; -import org.springframework.cassandra.core.keyspace.DefaultOption; -import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification; -import org.springframework.cassandra.core.keyspace.KeyspaceOption; -import org.springframework.cassandra.core.keyspace.Option; +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; -import org.w3c.dom.NodeList; + +import com.datastax.driver.core.HostDistance; +import com.datastax.driver.core.PoolingOptions; +import com.datastax.driver.core.SocketOptions; /** - * Parser for <cluster;gt; definitions. + * Parses the {@literal } element of the XML Configuration. * - * @author Alex Shvid * @author Matthew T. Adams + * @author David Webb */ -public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser { +public class CassandraClusterParser extends AbstractBeanDefinitionParser { - @Override - protected Class getBeanClass(Element element) { - return CassandraClusterFactoryBean.class; - } + private final static Logger log = LoggerFactory.getLogger(CassandraClusterParser.class); @Override protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) @@ -63,7 +66,34 @@ public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser { } @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CassandraClusterFactoryBean.class); + builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); + builder.getRawBeanDefinition().setDestroyMethodName("destroy"); + if (parserContext.isNested()) { + // Inner bean definition must receive same scope as containing bean. + builder.setScope(parserContext.getContainingBeanDefinition().getScope()); + } + + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + builder.setLazyInit(true); + } + + doParse(element, parserContext, builder); + + return builder.getBeanDefinition(); + } + + /** + * Parses the attributes on the top level element, then parses all children. + * + * @param element The Element being parsed + * @param context The Parser Context + * @param builder The parent {@link BeanDefinitionBuilder} + */ + protected void doParse(Element element, ParserContext context, BeanDefinitionBuilder builder) { String contactPoints = element.getAttribute("contactPoints"); if (StringUtils.hasText(contactPoints)) { @@ -77,41 +107,118 @@ public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser { String compression = element.getAttribute("compression"); if (StringUtils.hasText(compression)) { - builder.addPropertyValue("compressionType", CompressionType.valueOf(compression)); + builder.addPropertyValue("compressionType", compression); } - parseChildElements(builder, element); + 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); + } + + parseChildElements(element, context, builder); } - protected void parseChildElements(BeanDefinitionBuilder builder, Element element) { + /** + * Parse the Child Elemement of {@link BeanNames.CASSANDRA_CLUSTER} + * + * @param element The Element being parsed + * @param context The Parser Context + * @param builder The parent {@link BeanDefinitionBuilder} + */ + protected void parseChildElements(Element element, ParserContext context, BeanDefinitionBuilder builder) { - List creates = new ArrayList(); - List drops = new ArrayList(); + ManagedSet keyspaceActionSpecificationBeanDefinitions = new ManagedSet(); List startupScripts = new ArrayList(); List shutdownScripts = new ArrayList(); List elements = DomUtils.getChildElements(element); + BeanDefinition keyspaceActionSpecificationBeanDefinition = null; - // parse nested elements + /* + * PoolingOptionsBuilder has two potential parsing cycles so it is defined + * before the child elements are iterated over, then converted to a BeanDefinition + * just in time. + */ + BeanDefinitionBuilder poolingOptionsBuilder = null; + + /* + * Parse each of the child elements + */ for (Element subElement : elements) { + String name = subElement.getLocalName(); if ("local-pooling-options".equals(name)) { - builder.addPropertyValue("localPoolingOptions", parsePoolingOptions(subElement)); + poolingOptionsBuilder = parsePoolingOptions(subElement, poolingOptionsBuilder, HostDistance.LOCAL); } else if ("remote-pooling-options".equals(name)) { - builder.addPropertyValue("remotePoolingOptions", parsePoolingOptions(subElement)); + poolingOptionsBuilder = parsePoolingOptions(subElement, poolingOptionsBuilder, HostDistance.REMOTE); } else if ("socket-options".equals(name)) { - builder.addPropertyValue("socketOptions", parseSocketOptions(subElement)); + builder.addPropertyValue("socketOptions", getSocketOptionsBeanDefinition(subElement, context)); } else if ("keyspace".equals(name)) { - KeyspaceSpecifications specifications = parseKeyspace(subElement); + keyspaceActionSpecificationBeanDefinition = getKeyspaceSpecificationBeanDefinition(subElement, context); + keyspaceActionSpecificationBeanDefinitions.add(keyspaceActionSpecificationBeanDefinition); - if (specifications.create != null) { - creates.add(specifications.create); - } - if (specifications.drop != null) { - drops.add(specifications.drop); - } } else if ("startup-cql".equals(name)) { startupScripts.add(parseScript(subElement)); } else if ("shutdown-cql".equals(name)) { @@ -119,123 +226,169 @@ public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser { } } - builder.addPropertyValue("keyspaceCreations", creates); - builder.addPropertyValue("keyspaceDrops", drops); + /* + * If the PoolingOptionsBuilder was initilized during parsing, process it now. + */ + if (poolingOptionsBuilder != null) { + builder.addPropertyValue("poolingOptions", getSourceBeanDefinition(poolingOptionsBuilder, context, element)); + } + + builder.addPropertyValue("keyspaceSpecifications", + getKeyspaceSetFlattenerBeanDefinition(element, context, keyspaceActionSpecificationBeanDefinitions)); builder.addPropertyValue("startupScripts", startupScripts); builder.addPropertyValue("shutdownScripts", startupScripts); } - protected KeyspaceSpecifications parseKeyspace(Element element) { + /** + * Create the Single Factory Bean that will flatten all List> + * + * @param element The Element being parsed + * @param context The Parser Context + * @param keyspaceActionSpecificationBeanDefinitions The List of Definitions to flatten + * @return A single level List of KeyspaceActionSpecifications + */ + private Object getKeyspaceSetFlattenerBeanDefinition(Element element, ParserContext context, + ManagedSet keyspaceActionSpecificationBeanDefinitions) { - CreateKeyspaceSpecification create = null; - DropKeyspaceSpecification drop = null; + BeanDefinitionBuilder flat = BeanDefinitionBuilder.genericBeanDefinition(MultiLevelSetFlattenerFactoryBean.class); + flat.addPropertyValue("multiLevelSet", keyspaceActionSpecificationBeanDefinitions); + return getSourceBeanDefinition(flat, context, element); - String name = element.getAttribute("name"); - if (name == null || name.trim().length() == 0) { - name = BeanNames.CASSANDRA_KEYSPACE; - } - - boolean durableWrites = Boolean.valueOf(element.getAttribute("durable-writes")); - - String action = element.getAttribute("action"); - if (action == null || action.trim().length() == 0) { - throw new IllegalArgumentException("attribute action must be given"); - } - - if (action.startsWith("CREATE")) { - - create = CreateKeyspaceSpecification.createKeyspace().name(name) - .with(KeyspaceOption.DURABLE_WRITES, durableWrites); - - NodeList nodes = element.getElementsByTagName("replication"); - create = parseReplication((Element) (nodes.getLength() == 1 ? nodes.item(0) : null), create); - } - - if (action.equals("CREATE-DROP")) { - drop = DropKeyspaceSpecification.dropKeyspace().name(create.getName()); - } - - return new KeyspaceSpecifications(create, drop); } - protected CreateKeyspaceSpecification parseReplication(Element element, CreateKeyspaceSpecification create) { + /** + * Parses the keyspace replication options and adds them to the supplied {@link BeanDefinitionBuilder}. + * + * @param element The Element being parsed + * @param builder The {@link BeanDefinitionBuilder} to add the replication to + */ + protected void parseReplication(Element element, BeanDefinitionBuilder builder) { + ManagedList networkTopologyDataCenters = new ManagedList(); + ManagedList networkTopologyReplicationFactors = new ManagedList(); String strategyClass = null; + String replicationFactor = null; + if (element != null) { + strategyClass = element.getAttribute("class"); - } - if (strategyClass == null || (strategyClass = strategyClass.trim()).length() == 0) { - strategyClass = KeyspaceAttributes.DEFAULT_REPLICATION_STRATEGY; - } - - Long replicationFactor = null; - if (element != null) { - String s = element.getAttribute("replication-factor"); - replicationFactor = (s == null || s.trim().length() == 0) ? null : Long.parseLong(s); - } - if (replicationFactor == null) { - replicationFactor = KeyspaceAttributes.DEFAULT_REPLICATION_FACTOR; - } - - Map replicationMap = new HashMap(); - replicationMap.put(new DefaultOption("class", String.class, false, false, true), strategyClass); - replicationMap.put(new DefaultOption("replication_factor", Long.class, true, false, false), replicationFactor); - - if (element != null) { - - NodeList dataCenters = element.getElementsByTagName("data-center"); - - int length = dataCenters.getLength(); - for (int i = 0; i < length; i++) { - - Element dataCenter = (Element) dataCenters.item(i); - - replicationMap.put(new DefaultOption(dataCenter.getAttribute("name"), Long.class, false, false, true), - dataCenter.getAttribute("replication-factor")); + if (!StringUtils.hasText(strategyClass)) { + strategyClass = KeyspaceAttributes.DEFAULT_REPLICATION_STRATEGY; } + + replicationFactor = element.getAttribute("replication-factor"); + if (!StringUtils.hasText(replicationFactor)) { + replicationFactor = KeyspaceAttributes.DEFAULT_REPLICATION_FACTOR + ""; + } + + /* + * DataCenters only apply to NetworkTolopogyStrategy + */ + List dcElements = DomUtils.getChildElementsByTagName(element, "data-center"); + for (Element dataCenter : dcElements) { + networkTopologyDataCenters.add(dataCenter.getAttribute("name")); + networkTopologyReplicationFactors.add(dataCenter.getAttribute("replication-factor")); + } + } else { + strategyClass = ReplicationStrategy.SIMPLE_STRATEGY.name(); + replicationFactor = KeyspaceAttributes.DEFAULT_REPLICATION_FACTOR + ""; } - return create.with(KeyspaceOption.REPLICATION, replicationMap); + builder.addPropertyValue("replicationStrategy", strategyClass); + builder.addPropertyValue("replicationFactor", replicationFactor); + builder.addPropertyValue("networkTopologyDataCenters", networkTopologyDataCenters); + builder.addPropertyValue("networkTopologyReplicationFactors", networkTopologyReplicationFactors); + } + /** + * Parse CQL Script Elements + * + * @param element The Element being parsed + * @return + */ protected String parseScript(Element element) { return element.getTextContent(); } - protected BeanDefinition parsePoolingOptions(Element element) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(PoolingOptionsConfig.class); + /** + * Returns a {@link BeanDefinition} for a {@link PoolingOptions} object. + * + * @param element The Element being parsed + * @param builder The {@link BeanDefinition} to use for building if one already exists + * @param hostDistance The scope of the PoolingOptions to apply + * @return The {@link BeanDefinitionBuilder} + */ + protected BeanDefinitionBuilder parsePoolingOptions(Element element, BeanDefinitionBuilder builder, + HostDistance hostDistance) { - ParsingUtils.setPropertyValue(builder, element, "min-simultaneous-requests", "minSimultaneousRequests"); - ParsingUtils.setPropertyValue(builder, element, "max-simultaneous-requests", "maxSimultaneousRequests"); - ParsingUtils.setPropertyValue(builder, element, "core-connections", "coreConnections"); - ParsingUtils.setPropertyValue(builder, element, "max-connections", "maxConnections"); + if (builder == null) { + builder = BeanDefinitionBuilder.genericBeanDefinition(PoolingOptionsFactoryBean.class); + } - return builder.getBeanDefinition(); + 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"); + } + 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"); + } + + return builder; } - protected BeanDefinition parseSocketOptions(Element element) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SocketOptionsConfig.class); + /** + * Returns a {@link BeanDefinition} for a {@link SocketOptions} object. + * + * @param element The Element being parsed + * @param context The ParserContext + * @return The {@link BeanDefinition} + */ + protected BeanDefinition getSocketOptionsBeanDefinition(Element element, ParserContext context) { - ParsingUtils.setPropertyValue(builder, element, "connect-timeout-mls", "connectTimeoutMls"); + 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"); - return builder.getBeanDefinition(); + return getSourceBeanDefinition(builder, context, element); } - protected static class KeyspaceSpecifications { + /** + * Returns a {@link BeanDefinition} for a {@link KeyspaceActionSpecification} object. + * + * @param element The Element being parsed + * @param context The Parser Context + * @return The {@link BeanDefinition} or {@literal null} if action is not given. + */ + private BeanDefinition getKeyspaceSpecificationBeanDefinition(Element element, ParserContext context) { - public KeyspaceSpecifications(CreateKeyspaceSpecification create, DropKeyspaceSpecification drop) { - this.create = create; - this.drop = drop; - } + String action = element.getAttribute("action"); - public CreateKeyspaceSpecification create; - public DropKeyspaceSpecification drop; - // TODO: public AlterKeyspaceSpecification alter; + 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"); + + Element replicationElement = DomUtils.getChildElementByTagName(element, "replication"); + parseReplication(replicationElement, keyspaceBuilder); + + return getSourceBeanDefinition(keyspaceBuilder, context, element); } + } diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/cql/generator/KeyspaceNameCqlGenerator.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/cql/generator/KeyspaceNameCqlGenerator.java index fbaa6b7dc..66092d235 100644 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/cql/generator/KeyspaceNameCqlGenerator.java +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/cql/generator/KeyspaceNameCqlGenerator.java @@ -15,20 +15,20 @@ */ package org.springframework.cassandra.core.cql.generator; -import org.springframework.cassandra.core.keyspace.KeyspaceNameSpecification; +import org.springframework.cassandra.core.keyspace.KeyspaceActionSpecification; import org.springframework.util.Assert; -public abstract class KeyspaceNameCqlGenerator> { +public abstract class KeyspaceNameCqlGenerator> { public abstract StringBuilder toCql(StringBuilder cql); - private KeyspaceNameSpecification specification; + private KeyspaceActionSpecification specification; - public KeyspaceNameCqlGenerator(KeyspaceNameSpecification specification) { + public KeyspaceNameCqlGenerator(KeyspaceActionSpecification specification) { setSpecification(specification); } - protected void setSpecification(KeyspaceNameSpecification specification) { + protected void setSpecification(KeyspaceActionSpecification specification) { Assert.notNull(specification); this.specification = specification; } diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/DropKeyspaceSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/DropKeyspaceSpecification.java index 839e793c5..5e7511f8d 100644 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/DropKeyspaceSpecification.java +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/DropKeyspaceSpecification.java @@ -1,28 +1,28 @@ -package org.springframework.cassandra.core.keyspace; - -public class DropKeyspaceSpecification extends KeyspaceNameSpecification { - - private boolean ifExists; - - public DropKeyspaceSpecification ifExists() { - return ifExists(true); - } - - public DropKeyspaceSpecification ifExists(boolean ifExists) { - this.ifExists = ifExists; - return this; - } - - public boolean getIfExists() { - return ifExists; - } - - /** - * Entry point into the {@link DropKeyspaceSpecification}'s fluent API to drop a keyspace. Convenient if imported - * statically. - */ - public static DropKeyspaceSpecification dropKeyspace() { - return new DropKeyspaceSpecification(); - } - -} +package org.springframework.cassandra.core.keyspace; + +public class DropKeyspaceSpecification extends KeyspaceActionSpecification { + + private boolean ifExists; + + public DropKeyspaceSpecification ifExists() { + return ifExists(true); + } + + public DropKeyspaceSpecification ifExists(boolean ifExists) { + this.ifExists = ifExists; + return this; + } + + public boolean getIfExists() { + return ifExists; + } + + /** + * Entry point into the {@link DropKeyspaceSpecification}'s fluent API to drop a keyspace. Convenient if imported + * statically. + */ + public static DropKeyspaceSpecification dropKeyspace() { + return new DropKeyspaceSpecification(); + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceActionSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceActionSpecification.java new file mode 100644 index 000000000..cddc2115d --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceActionSpecification.java @@ -0,0 +1,76 @@ +package org.springframework.cassandra.core.keyspace; + +import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier; +import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize; + +/** + * Abstract builder class to support the construction of keyspace specifications. + * + * @author John McPeek + * @author David Webb + * @param The subtype of the {@link KeyspaceActionSpecification} + */ +public abstract class KeyspaceActionSpecification> { + + /** + * The name of the table. + */ + private String name; + + /** + * Sets the keyspace name. + * + * @return this + */ + @SuppressWarnings("unchecked") + public T name(String name) { + checkIdentifier(name); + this.name = name; + return (T) this; + } + + public String getName() { + return name; + } + + public String getNameAsIdentifier() { + return identifize(name); + } + + /** + * For debugging KeyspaceActionSprcifications + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Keyspace Action Specification {name: " + name + ", class: " + this.getClass() + "}"); + return sb.toString(); + } + + /** + * Determine the KeyspaceActionSpecifications are the same if they have the same "name" and same class. + * + * @param that The object to compare this to. + * @return Are this and that the same? + */ + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (!(that instanceof KeyspaceActionSpecification)) { + return false; + } + KeyspaceActionSpecification thatSpec = (KeyspaceActionSpecification) that; + return this.name.equals(thatSpec.name) && this.getClass().equals(that.getClass()); + } + + @Override + public int hashCode() { + return this.name.hashCode() ^ this.getClass().hashCode(); + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceNameSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceNameSpecification.java deleted file mode 100644 index 0bec92437..000000000 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceNameSpecification.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.springframework.cassandra.core.keyspace; - -import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier; -import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize; - -/** - * Abstract builder class to support the construction of keyspace specifications. - * - * @author John McPeek - * @param The subtype of the {@link KeyspaceNameSpecification} - */ -public abstract class KeyspaceNameSpecification> { - - /** - * The name of the table. - */ - private String name; - - /** - * Sets the keyspace name. - * - * @return this - */ - @SuppressWarnings( "unchecked" ) - public T name(String name) { - checkIdentifier(name); - this.name = name; - return (T) this; - } - - public String getName() { - return name; - } - - public String getNameAsIdentifier() { - return identifize(name); - } - -} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOption.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOption.java index 3e5905f64..0d02f15c6 100644 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOption.java +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOption.java @@ -1,79 +1,79 @@ -package org.springframework.cassandra.core.keyspace; - -import java.util.Map; - -public enum KeyspaceOption implements Option { - REPLICATION("replication", Map.class, true, false, false), - - DURABLE_WRITES("durable_writes", Boolean.class, false, false, false); - - private Option delegate; - - private KeyspaceOption(String name, Class type, boolean requiresValue, boolean escapesValue, boolean quotesValue) { - this.delegate = new DefaultOption(name, type, requiresValue, escapesValue, quotesValue); - } - - public Class getType() { - return delegate.getType(); - } - - public boolean takesValue() { - return delegate.takesValue(); - } - - public String getName() { - return delegate.getName(); - } - - public boolean escapesValue() { - return delegate.escapesValue(); - } - - public boolean quotesValue() { - return delegate.quotesValue(); - } - - public boolean requiresValue() { - return delegate.requiresValue(); - } - - public void checkValue(Object value) { - delegate.checkValue(value); - } - - public boolean isCoerceable(Object value) { - return delegate.isCoerceable(value); - } - - public String toString() { - return delegate.toString(); - } - - public String toString(Object value) { - return delegate.toString(value); - } - - /** - * Known Replication Strategy options. - * - * @author John McPeek - * - */ - public enum ReplicationStrategy { - SIMPLE_STRATEGY("SimpleStrategy"), NETWORK_TOPOLOGY_STRATEGY("NetworkTopologyStrategy"); - - private String value; - - private ReplicationStrategy(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public String toString() { - return getValue(); - } - } -} +package org.springframework.cassandra.core.keyspace; + +import java.util.Map; + +public enum KeyspaceOption implements Option { + REPLICATION("replication", Map.class, true, false, false), + + DURABLE_WRITES("durable_writes", Boolean.class, false, false, false); + + private Option delegate; + + private KeyspaceOption(String name, Class type, boolean requiresValue, boolean escapesValue, boolean quotesValue) { + this.delegate = new DefaultOption(name, type, requiresValue, escapesValue, quotesValue); + } + + public Class getType() { + return delegate.getType(); + } + + public boolean takesValue() { + return delegate.takesValue(); + } + + public String getName() { + return delegate.getName(); + } + + public boolean escapesValue() { + return delegate.escapesValue(); + } + + public boolean quotesValue() { + return delegate.quotesValue(); + } + + public boolean requiresValue() { + return delegate.requiresValue(); + } + + public void checkValue(Object value) { + delegate.checkValue(value); + } + + public boolean isCoerceable(Object value) { + return delegate.isCoerceable(value); + } + + public String toString() { + return delegate.toString(); + } + + public String toString(Object value) { + return delegate.toString(value); + } + + /** + * Known Replication Strategy options. + * + * @author John McPeek + * + */ + public enum ReplicationStrategy { + SIMPLE_STRATEGY("SimpleStrategy"), NETWORK_TOPOLOGY_STRATEGY("NetworkTopologyStrategy"); + + private String value; + + private ReplicationStrategy(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public String toString() { + return getValue(); + } + } +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOptionsSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOptionsSpecification.java index 574e166a6..23cf20698 100644 --- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOptionsSpecification.java +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOptionsSpecification.java @@ -1,94 +1,94 @@ -package org.springframework.cassandra.core.keyspace; - -import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle; -import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.cassandra.core.cql.CqlStringUtils; - -/** - * Abstract builder class to support the construction of table specifications that have table options, that is, those - * options normally specified by WITH ... AND .... - *

- * It is important to note that although this class depends on {@link KeyspaceOption} for convenient and typesafe use, it - * ultimately stores its options in a Map for flexibility. This means that - * {@link #with(KeyspaceOption)} and {@link #with(KeyspaceOption, Object)} delegate to - * {@link #with(String, Object, boolean, boolean)}. This design allows the API to support new Cassandra options as they - * are introduced without having to update the code immediately. - * - * @author John McPeek - * @param The subtype of the {@link KeyspaceOptionsSpecification}. - */ -public abstract class KeyspaceOptionsSpecification> extends - KeyspaceNameSpecification> { - - protected Map options = new LinkedHashMap(); - - @SuppressWarnings( "unchecked" ) - public T name(String name) { - return (T) super.name(name); - } - - /** - * Convenience method that calls with(option, null). - * - * @return this - */ - public T with(KeyspaceOption option) { - return with(option, null); - } - - /** - * Sets the given table option. This is a convenience method that calls - * {@link #with(String, Object, boolean, boolean)} appropriately from the given {@link KeyspaceOption} and value for that - * option. - * - * @param option The option to set. - * @param value The value of the option. Must be type-compatible with the {@link KeyspaceOption}. - * @return this - * @see #with(String, Object, boolean, boolean) - */ - public T with(KeyspaceOption option, Object value) { - option.checkValue(value); - return (T) with(option.getName(), value, option.escapesValue(), option.quotesValue()); - } - - /** - * Adds the given option by name to this keyspaces's options. - *

- * Options that have null values are considered single string options where the name of the option is the - * string to be used. Otherwise, the result of {@link Object#toString()} is considered to be the value of the option - * with the given name. The value, after conversion to string, may have embedded single quotes escaped according to - * parameter escape and may be single-quoted according to parameter quote. - * - * @param name The name of the option - * @param value The value of the option. If null, the value is ignored and the option is considered to be - * composed of only the name, otherwise the value's {@link Object#toString()} value is used. - * @param escape Whether to escape the value via {@link CqlStringUtils#escapeSingle(Object)}. Ignored if given value - * is an instance of a {@link Map}. - * @param quote Whether to quote the value via {@link CqlStringUtils#singleQuote(Object)}. Ignored if given value is - * an instance of a {@link Map}. - * @return this - */ - @SuppressWarnings("unchecked") - public T with(String name, Object value, boolean escape, boolean quote) { - if (!(value instanceof Map)) { - if (escape) { - value = escapeSingle(value); - } - if (quote) { - value = singleQuote(value); - } - } - options.put(name, value); - return (T) this; - } - - public Map getOptions() { - return Collections.unmodifiableMap(options); - } - -} +package org.springframework.cassandra.core.keyspace; + +import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle; +import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.springframework.cassandra.core.cql.CqlStringUtils; + +/** + * Abstract builder class to support the construction of table specifications that have table options, that is, those + * options normally specified by WITH ... AND .... + *

+ * It is important to note that although this class depends on {@link KeyspaceOption} for convenient and typesafe use, it + * ultimately stores its options in a Map for flexibility. This means that + * {@link #with(KeyspaceOption)} and {@link #with(KeyspaceOption, Object)} delegate to + * {@link #with(String, Object, boolean, boolean)}. This design allows the API to support new Cassandra options as they + * are introduced without having to update the code immediately. + * + * @author John McPeek + * @param The subtype of the {@link KeyspaceOptionsSpecification}. + */ +public abstract class KeyspaceOptionsSpecification> extends + KeyspaceActionSpecification> { + + protected Map options = new LinkedHashMap(); + + @SuppressWarnings( "unchecked" ) + public T name(String name) { + return (T) super.name(name); + } + + /** + * Convenience method that calls with(option, null). + * + * @return this + */ + public T with(KeyspaceOption option) { + return with(option, null); + } + + /** + * Sets the given table option. This is a convenience method that calls + * {@link #with(String, Object, boolean, boolean)} appropriately from the given {@link KeyspaceOption} and value for that + * option. + * + * @param option The option to set. + * @param value The value of the option. Must be type-compatible with the {@link KeyspaceOption}. + * @return this + * @see #with(String, Object, boolean, boolean) + */ + public T with(KeyspaceOption option, Object value) { + option.checkValue(value); + return (T) with(option.getName(), value, option.escapesValue(), option.quotesValue()); + } + + /** + * Adds the given option by name to this keyspaces's options. + *

+ * Options that have null values are considered single string options where the name of the option is the + * string to be used. Otherwise, the result of {@link Object#toString()} is considered to be the value of the option + * with the given name. The value, after conversion to string, may have embedded single quotes escaped according to + * parameter escape and may be single-quoted according to parameter quote. + * + * @param name The name of the option + * @param value The value of the option. If null, the value is ignored and the option is considered to be + * composed of only the name, otherwise the value's {@link Object#toString()} value is used. + * @param escape Whether to escape the value via {@link CqlStringUtils#escapeSingle(Object)}. Ignored if given value + * is an instance of a {@link Map}. + * @param quote Whether to quote the value via {@link CqlStringUtils#singleQuote(Object)}. Ignored if given value is + * an instance of a {@link Map}. + * @return this + */ + @SuppressWarnings("unchecked") + public T with(String name, Object value, boolean escape, boolean quote) { + if (!(value instanceof Map)) { + if (escape) { + value = escapeSingle(value); + } + if (quote) { + value = singleQuote(value); + } + } + options.put(name, value); + return (T) this; + } + + public Map getOptions() { + return Collections.unmodifiableMap(options); + } + +} diff --git a/spring-cassandra/src/main/resources/org/springframework/cassandra/config/spring-cassandra-1.0.xsd b/spring-cassandra/src/main/resources/org/springframework/cassandra/config/spring-cassandra-1.0.xsd index 9e31eb010..6eed171ab 100644 --- a/spring-cassandra/src/main/resources/org/springframework/cassandra/config/spring-cassandra-1.0.xsd +++ b/spring-cassandra/src/main/resources/org/springframework/cassandra/config/spring-cassandra-1.0.xsd @@ -59,22 +59,16 @@ Defines a Cassandra cluster. - - - - - - + + + @@ -133,32 +127,59 @@ The native CQL port to connect to. Default is 9042. ]]> - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -285,7 +359,7 @@ More connections are created up to a configurable maximum number of connections. - + + + + + + - + - - - - - - - - - - - - - - - - - - null, get a {@link Session} for the from the {@link #cluster}. - */ - protected String keyspace = "ks" + UUID.randomUUID().toString().replace("-", ""); - - /** - * The {@link Session} for the {@link #keyspace} from the {@link #cluster}. - */ - protected static Session session; - - protected String keyspace() { - return keyspace; - } - - /** - * Returns whether we're currently connected to the cluster. - */ - public boolean connected() { - return session != null; - } - - public Cluster cluster() { + public static Cluster cluster() { return Cluster.builder().addContactPoint(CASSANDRA_HOST).withPort(CASSANDRA_NATIVE_PORT).build(); } - public void connect() { + /** + * Ensures that the cluster is created and that the session {@link #SYSTEM} is connected to it. + */ + public static void ensureClusterConnection() { - if (connect && !connected()) { + // check cluster + if (CLUSTER == null) { + CLUSTER = cluster(); + } - log.info("Connecting to Cassandra"); - - cluster = cluster(); - - if (keyspace() == null) { - session = cluster.connect(); - } else { - - KeyspaceMetadata kmd = cluster.getMetadata().getKeyspace(keyspace()); - if (kmd == null) { // then create keyspace - session = cluster.connect(); - session.execute("CREATE KEYSPACE " + keyspace() - + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};"); - session.execute("USE " + keyspace() + ";"); - } else {// else keyspace already exists - session = cluster.connect(keyspace()); - } - } + // check system session connected + if (SYSTEM == null) { + SYSTEM = CLUSTER.connect(); } } - @After - public void after() { - log.info("After: clear -> " + clear + ", connected -> " + connected()); - if (clear && connected()) { - log.info("Cleaning Cassandra"); - EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); - } + public AbstractEmbeddedCassandraIntegrationTest() { + ensureClusterConnection(); } - } diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/AbstractKeyspaceCreatingIntegrationTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/AbstractKeyspaceCreatingIntegrationTest.java new file mode 100644 index 000000000..b9e04f827 --- /dev/null +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/AbstractKeyspaceCreatingIntegrationTest.java @@ -0,0 +1,109 @@ +package org.springframework.cassandra.test.integration; + +import org.junit.After; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.Session; + +/** + * Abstract base integration test class that creates a keyspace + * + * @author Matthew T. Adams + */ +public abstract class AbstractKeyspaceCreatingIntegrationTest extends AbstractEmbeddedCassandraIntegrationTest { + + static Logger log = LoggerFactory.getLogger(AbstractKeyspaceCreatingIntegrationTest.class); + + /** + * The session that's connected to the keyspace used in the current instance's test. + */ + protected static Session SESSION; + + /** + * The name of the keyspace to use for this test instance. + */ + protected String keyspace; + + public AbstractKeyspaceCreatingIntegrationTest() { + this(randomKeyspaceName()); + } + + public AbstractKeyspaceCreatingIntegrationTest(String keyspace) { + + this.keyspace = keyspace; + ensureKeyspaceAndSession(); + } + + /** + * Returns whether we're currently connected to the keyspace. + */ + public static boolean connected() { + return SESSION != null; + } + + /** + * Whether to drop the keyspace that was created after the test has completed. Subclasses should override and return + * true, since this default implementation returns false. + */ + public boolean dropKeyspaceAfterTest() { + return false; + } + + public void ensureKeyspaceAndSession() { + + // ensure that test keyspace exists + + if (!StringUtils.hasText(keyspace)) { + keyspace = null; + } + + if (keyspace != null) { + // see if we need to create the keyspace + KeyspaceMetadata kmd = CLUSTER.getMetadata().getKeyspace(keyspace); + if (kmd == null) { // then create keyspace + + String cql = "CREATE KEYSPACE " + keyspace + + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};"; + log.info("creating keyspace {} via CQL [{}]", keyspace, cql); + + SYSTEM.execute(cql); + } + } + + // keyspace now exists; ensure the session is using it + if (SESSION == null) { + + log.info("connecting to keyspace {}", keyspace == null ? "system" : keyspace + "..."); + + SESSION = keyspace == null ? CLUSTER.connect() : CLUSTER.connect(keyspace); + + log.info("connected to keyspace {}", keyspace == null ? "system" : keyspace); + + } else { + + log.info("session already connected to a keyspace; attempting to change to use {}", keyspace); + + String cql = "USE " + (keyspace == null ? "system" : keyspace) + ";"; + SESSION.execute(cql); + + log.info("now using keyspace " + keyspace); + } + } + + @After + public void after() { + if (dropKeyspaceAfterTest() && keyspace != null) { + + SESSION.execute("USE system"); + + log.info("dropping keyspace {} ...", keyspace); + + SYSTEM.execute("DROP KEYSPACE " + keyspace); + + log.info("dropped keyspace {}", keyspace); + } + } +} diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/Config.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/Config.java index 7768526a0..502fc574d 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/Config.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/Config.java @@ -1,10 +1,10 @@ package org.springframework.cassandra.test.integration.config.java; -import org.springframework.cassandra.config.java.AbstractCassandraConfiguration; import org.springframework.context.annotation.Configuration; +import org.springframework.cassandra.test.integration.support.AbstractTestJavaConfig; @Configuration -public class Config extends AbstractCassandraConfiguration { +public class Config extends AbstractTestJavaConfig { @Override protected String getKeyspaceName() { diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/KeyspaceCreatingJavaConfig.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/KeyspaceCreatingJavaConfig.java index 4b0f9be88..3db7d94f4 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/KeyspaceCreatingJavaConfig.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/KeyspaceCreatingJavaConfig.java @@ -4,13 +4,13 @@ import java.util.ArrayList; import java.util.List; import org.springframework.cassandra.config.KeyspaceAttributes; -import org.springframework.cassandra.config.java.AbstractCassandraConfiguration; import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification; import org.springframework.cassandra.core.keyspace.KeyspaceOption; +import org.springframework.cassandra.test.integration.support.AbstractTestJavaConfig; import org.springframework.context.annotation.Configuration; @Configuration -public class KeyspaceCreatingJavaConfig extends AbstractCassandraConfiguration { +public class KeyspaceCreatingJavaConfig extends AbstractTestJavaConfig { public static final String KEYSPACE_NAME = "foo"; diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/KeyspaceCreatingJavaConfigTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/KeyspaceCreatingJavaConfigTest.java index 0f639ec57..fe827695c 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/KeyspaceCreatingJavaConfigTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/java/KeyspaceCreatingJavaConfigTest.java @@ -1,28 +1,13 @@ 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); diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest.java index 44ac32069..228a3c70d 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest.java @@ -15,11 +15,6 @@ import com.datastax.driver.core.Session; @ContextConfiguration public class FullySpecifiedKeyspaceCreatingXmlConfigTest extends AbstractEmbeddedCassandraIntegrationTest { - @Override - protected String keyspace() { - return null; - } - @Inject Session s; diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/MinimalKeyspaceCreatingXmlConfigTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/MinimalKeyspaceCreatingXmlConfigTest.java index 492605316..6759daa2c 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/MinimalKeyspaceCreatingXmlConfigTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/MinimalKeyspaceCreatingXmlConfigTest.java @@ -15,11 +15,6 @@ import com.datastax.driver.core.Session; @ContextConfiguration public class MinimalKeyspaceCreatingXmlConfigTest extends AbstractEmbeddedCassandraIntegrationTest { - @Override - protected String keyspace() { - return null; - } - @Inject Session s; diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/MinimalXmlConfigTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/MinimalXmlConfigTest.java index 760c00192..045d9788e 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/MinimalXmlConfigTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/MinimalXmlConfigTest.java @@ -1,13 +1,13 @@ package org.springframework.cassandra.test.integration.config.xml; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNotNull; import javax.inject.Inject; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.cassandra.core.CassandraOperations; -import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.cassandra.test.integration.config.IntegrationTestUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -16,10 +16,12 @@ import com.datastax.driver.core.Session; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration -public class MinimalXmlConfigTest extends AbstractEmbeddedCassandraIntegrationTest { +public class MinimalXmlConfigTest extends AbstractKeyspaceCreatingIntegrationTest { - protected String keyspace() { - return "minimalxmlconfigtest"; + public static final String KEYSPACE = "minimalxmlconfigtest"; + + public MinimalXmlConfigTest() { + super(KEYSPACE); } @Inject @@ -31,7 +33,7 @@ public class MinimalXmlConfigTest extends AbstractEmbeddedCassandraIntegrationTe @Test public void test() { IntegrationTestUtils.assertSession(s); - IntegrationTestUtils.assertKeyspaceExists(keyspace(), s); + IntegrationTestUtils.assertKeyspaceExists(KEYSPACE, s); assertNotNull(ops); } diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/PropertyPlaceholderNamespaceCreatingXmlConfigTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/PropertyPlaceholderNamespaceCreatingXmlConfigTest.java new file mode 100644 index 000000000..93d8bd205 --- /dev/null +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/PropertyPlaceholderNamespaceCreatingXmlConfigTest.java @@ -0,0 +1,40 @@ +package org.springframework.cassandra.test.integration.config.xml; + +import static org.junit.Assert.assertNotNull; + +import javax.inject.Inject; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cassandra.core.CassandraOperations; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; +import org.springframework.cassandra.test.integration.config.IntegrationTestUtils; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.datastax.driver.core.Session; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class PropertyPlaceholderNamespaceCreatingXmlConfigTest extends AbstractKeyspaceCreatingIntegrationTest { + + private static Logger log = LoggerFactory.getLogger(PropertyPlaceholderNamespaceCreatingXmlConfigTest.class); + + @Inject + Session s; + + @Inject + CassandraOperations ops; + + @Test + public void test() { + IntegrationTestUtils.assertSession(s); + + IntegrationTestUtils.assertKeyspaceExists("ppncxct", s); + + assertNotNull(ops); + } + +} diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/TestHostStateListener.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/TestHostStateListener.java new file mode 100644 index 000000000..9ea86c48c --- /dev/null +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/TestHostStateListener.java @@ -0,0 +1,52 @@ +/* + * Copyright 2011-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cassandra.test.integration.config.xml; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.datastax.driver.core.Host; +import com.datastax.driver.core.Host.StateListener; + +/** + * @author David Webb + * + */ +public class TestHostStateListener implements StateListener { + + private final static Logger log = LoggerFactory.getLogger(TestHostStateListener.class); + + @Override + public void onAdd(Host host) { + log.info("Host Added: " + host.getAddress()); + } + + @Override + public void onUp(Host host) { + log.info("Host Up: " + host.getAddress()); + } + + @Override + public void onDown(Host host) { + log.info("Host Down: " + host.getAddress()); + } + + @Override + public void onRemove(Host host) { + log.info("Host Removed: " + host.getAddress()); + } + +} diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/TestLatencyTracker.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/TestLatencyTracker.java new file mode 100644 index 000000000..221e408be --- /dev/null +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/TestLatencyTracker.java @@ -0,0 +1,37 @@ +/* + * Copyright 2011-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cassandra.test.integration.config.xml; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.datastax.driver.core.Host; +import com.datastax.driver.core.LatencyTracker; + +/** + * @author David Webb + * + */ +public class TestLatencyTracker implements LatencyTracker { + + private final static Logger log = LoggerFactory.getLogger(TestLatencyTracker.class); + + @Override + public void update(Host host, long newLatencyNanos) { + log.info("Latency Tracker: " + host.getAddress() + ", " + newLatencyNanos + " nanoseconds."); + } + +} diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest.java index b8eb27ea8..7f77c3791 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest.java @@ -4,7 +4,7 @@ import javax.inject.Inject; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.cassandra.test.integration.config.IntegrationTestUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -12,19 +12,21 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.datastax.driver.core.Session; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration -public class XmlConfigTest extends AbstractEmbeddedCassandraIntegrationTest { +@ContextConfiguration(locations = "classpath:/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest-context.xml") +public class XmlConfigTest extends AbstractKeyspaceCreatingIntegrationTest { - protected String keyspace() { - return "xmlconfigtest"; - } + public static final String KEYSPACE = "xmlconfigtest"; @Inject Session s; + public XmlConfigTest() { + super(KEYSPACE); + } + @Test public void test() { IntegrationTestUtils.assertSession(s); - IntegrationTestUtils.assertKeyspaceExists(keyspace(), s); + IntegrationTestUtils.assertKeyspaceExists(KEYSPACE, s); } } diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateIndexCqlGeneratorIntegrationTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateIndexCqlGeneratorIntegrationTests.java index 5c0add73b..d9c043916 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateIndexCqlGeneratorIntegrationTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateIndexCqlGeneratorIntegrationTests.java @@ -6,7 +6,7 @@ import org.cassandraunit.CassandraCQLUnit; import org.cassandraunit.dataset.cql.ClassPathCQLDataSet; import org.junit.Rule; import org.junit.Test; -import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateIndexCqlGeneratorTests.BasicTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateIndexCqlGeneratorTests.CreateIndexTest; @@ -24,7 +24,7 @@ public class CreateIndexCqlGeneratorIntegrationTests { * * @param The concrete unit test class to which this integration test corresponds. */ - public static abstract class Base extends AbstractEmbeddedCassandraIntegrationTest { + public static abstract class Base extends AbstractKeyspaceCreatingIntegrationTest { T unit; public abstract T unit(); @@ -34,9 +34,9 @@ public class CreateIndexCqlGeneratorIntegrationTests { unit = unit(); unit.prepare(); - session.execute(unit.cql); + SESSION.execute(unit.cql); - assertIndex(unit.specification, keyspace, session); + assertIndex(unit.specification, keyspace, SESSION); } } diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateKeyspaceCqlGeneratorIntegrationTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateKeyspaceCqlGeneratorIntegrationTests.java index 2524e0205..d71e79f14 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateKeyspaceCqlGeneratorIntegrationTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateKeyspaceCqlGeneratorIntegrationTests.java @@ -30,9 +30,9 @@ public class CreateKeyspaceCqlGeneratorIntegrationTests { unit = unit(); unit.prepare(); - session.execute(unit.cql); + SYSTEM.execute(unit.cql); - assertKeyspace(unit.specification, unit.keyspace, session); + assertKeyspace(unit.specification, unit.keyspace, SYSTEM); } } @@ -50,5 +50,5 @@ public class CreateKeyspaceCqlGeneratorIntegrationTests { public NetworkTopologyTest unit() { return new NetworkTopologyTest(); } - } + } } \ No newline at end of file diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateTableCqlGeneratorIntegrationTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateTableCqlGeneratorIntegrationTests.java index 63806cbc7..fc4de3fbf 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateTableCqlGeneratorIntegrationTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/CreateTableCqlGeneratorIntegrationTests.java @@ -5,7 +5,7 @@ import static org.springframework.cassandra.test.integration.core.cql.generator. import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests.BasicTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests.CompositePartitionKeyTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests.CreateTableTest; @@ -26,7 +26,7 @@ public class CreateTableCqlGeneratorIntegrationTests { * * @param The concrete unit test class to which this integration test corresponds. */ - public static abstract class Base extends AbstractEmbeddedCassandraIntegrationTest { + public static abstract class Base extends AbstractKeyspaceCreatingIntegrationTest { T unit; public abstract T unit(); @@ -36,9 +36,9 @@ public class CreateTableCqlGeneratorIntegrationTests { unit = unit(); unit.prepare(); - session.execute(unit.cql); + SESSION.execute(unit.cql); - assertTable(unit.specification, keyspace, session); + assertTable(unit.specification, keyspace, SESSION); } } diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/IndexLifecycleCqlGeneratorIntegrationTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/IndexLifecycleCqlGeneratorIntegrationTests.java index 0c01fdbd0..801655677 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/IndexLifecycleCqlGeneratorIntegrationTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/IndexLifecycleCqlGeneratorIntegrationTests.java @@ -9,7 +9,7 @@ import org.junit.Rule; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateIndexCqlGeneratorTests; import org.springframework.cassandra.test.unit.core.cql.generator.DropIndexCqlGeneratorTests; @@ -18,7 +18,7 @@ import org.springframework.cassandra.test.unit.core.cql.generator.DropIndexCqlGe * * @author Matthew T. Adams */ -public class IndexLifecycleCqlGeneratorIntegrationTests extends AbstractEmbeddedCassandraIntegrationTest { +public class IndexLifecycleCqlGeneratorIntegrationTests extends AbstractKeyspaceCreatingIntegrationTest { Logger log = LoggerFactory.getLogger(IndexLifecycleCqlGeneratorIntegrationTests.class); @@ -42,19 +42,19 @@ public class IndexLifecycleCqlGeneratorIntegrationTests extends AbstractEmbedded dropIfExists.prepare(); log.info(createTest.cql); - session.execute(createTest.cql); + SESSION.execute(createTest.cql); - assertIndex(createTest.specification, keyspace, session); + assertIndex(createTest.specification, keyspace, SESSION); log.info(dropTest.cql); - session.execute(dropTest.cql); + SESSION.execute(dropTest.cql); - assertNoIndex(createTest.specification, keyspace, session); + assertNoIndex(createTest.specification, keyspace, SESSION); // log.info(dropIfExists.cql); - // session.execute(dropIfExists.cql); + // SESSION.execute(dropIfExists.cql); // - // assertNoIndex(createTest.specification, keyspace, session); + // assertNoIndex(createTest.specification, keyspace, SESSION); } diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/TableLifecycleIntegrationTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/TableLifecycleIntegrationTest.java index 689895a81..ca836b2af 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/TableLifecycleIntegrationTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/TableLifecycleIntegrationTest.java @@ -26,7 +26,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cassandra.core.cql.generator.DropTableCqlGenerator; import org.springframework.cassandra.core.keyspace.DropTableSpecification; -import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.cassandra.test.unit.core.cql.generator.AlterTableCqlGeneratorTests; import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests; import org.springframework.cassandra.test.unit.core.cql.generator.DropTableCqlGeneratorTests; @@ -36,7 +36,7 @@ import org.springframework.cassandra.test.unit.core.cql.generator.DropTableCqlGe * * @author David Webb */ -public class TableLifecycleIntegrationTest extends AbstractEmbeddedCassandraIntegrationTest { +public class TableLifecycleIntegrationTest extends AbstractKeyspaceCreatingIntegrationTest { private final static Logger log = LoggerFactory.getLogger(TableLifecycleIntegrationTest.class); @@ -44,10 +44,14 @@ public class TableLifecycleIntegrationTest extends AbstractEmbeddedCassandraInte public TableLifecycleIntegrationTest() { super("tlit"); - clear = true; } - // This only ensures the keyspace exists before each test, while using a static session from the parent object. + @Override + public boolean dropKeyspaceAfterTest() { + return true; + } + + // This only ensures the keyspace exists before each test, while using a static SESSION from the parent object. // TODO - DW Make this better. @Rule public CassandraCQLUnit cassandraCQLUnit = new CassandraCQLUnit(new ClassPathCQLDataSet( @@ -61,18 +65,18 @@ public class TableLifecycleIntegrationTest extends AbstractEmbeddedCassandraInte log.info(createTableTest.cql); - session.execute(createTableTest.cql); + SESSION.execute(createTableTest.cql); - assertTable(createTableTest.specification, keyspace, session); + assertTable(createTableTest.specification, keyspace, SESSION); DropTableTest dropTest = new DropTableTest(); dropTest.prepare(); log.info(dropTest.cql); - session.execute(dropTest.cql); + SESSION.execute(dropTest.cql); - assertNoTable(dropTest.specification, keyspace, session); + assertNoTable(dropTest.specification, keyspace, SESSION); } @Test @@ -82,18 +86,18 @@ public class TableLifecycleIntegrationTest extends AbstractEmbeddedCassandraInte log.info(createTableTest.cql); - session.execute(createTableTest.cql); + SESSION.execute(createTableTest.cql); - assertTable(createTableTest.specification, keyspace, session); + assertTable(createTableTest.specification, keyspace, SESSION); AlterTableCqlGeneratorTests.MultipleOptionsTest alterTest = new AlterTableCqlGeneratorTests.MultipleOptionsTest(); alterTest.prepare(); log.info(alterTest.cql); - session.execute(alterTest.cql); + SESSION.execute(alterTest.cql); - // assertTable(alterTest.specification, keyspace, session); + // assertTable(alterTest.specification, keyspace, SESSION); } diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/TableOptionsIntegrationTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/TableOptionsIntegrationTest.java index b0d0bd92b..5c2e3ae25 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/TableOptionsIntegrationTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/cql/generator/TableOptionsIntegrationTest.java @@ -21,6 +21,7 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCqlGeneratorTests; /** @@ -28,7 +29,7 @@ import org.springframework.cassandra.test.unit.core.cql.generator.CreateTableCql * * @author David Webb */ -public class TableOptionsIntegrationTest extends AbstractEmbeddedCassandraIntegrationTest { +public class TableOptionsIntegrationTest extends AbstractKeyspaceCreatingIntegrationTest { private final static Logger log = LoggerFactory.getLogger(TableOptionsIntegrationTest.class); @@ -41,8 +42,8 @@ public class TableOptionsIntegrationTest extends AbstractEmbeddedCassandraIntegr log.info(optionsTest.cql); - session.execute(optionsTest.cql); + SESSION.execute(optionsTest.cql); - assertTable(optionsTest.specification, keyspace, session); + assertTable(optionsTest.specification, keyspace, SESSION); } } \ No newline at end of file diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/template/CassandraOperationsTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/template/CassandraOperationsTest.java index da5a4f636..3b31ecffe 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/template/CassandraOperationsTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/integration/core/template/CassandraOperationsTest.java @@ -46,7 +46,7 @@ import org.springframework.cassandra.core.RowCallbackHandler; import org.springframework.cassandra.core.RowIterator; import org.springframework.cassandra.core.RowMapper; import org.springframework.cassandra.core.SessionCallback; -import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest; +import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIntegrationTest; import org.springframework.dao.DataAccessException; import org.springframework.util.CollectionUtils; @@ -65,7 +65,7 @@ import com.datastax.driver.core.exceptions.DriverException; * @author David Webb * */ -public class CassandraOperationsTest extends AbstractEmbeddedCassandraIntegrationTest { +public class CassandraOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { private static CassandraOperations cassandraTemplate; @@ -89,8 +89,8 @@ public class CassandraOperationsTest extends AbstractEmbeddedCassandraIntegratio CASSANDRA_NATIVE_PORT); public CassandraOperationsTest() { - super("sdctest"); - clear = true; + super(); + // TODO clear = true; } @Before @@ -106,7 +106,7 @@ public class CassandraOperationsTest extends AbstractEmbeddedCassandraIntegratio // "cassandraOperationsTest-cql-dataload.cql", keyspace), CASSANDRA_CONFIG, CASSANDRA_HOST, // CASSANDRA_NATIVE_PORT); - cassandraTemplate = new CassandraTemplate(session); + cassandraTemplate = new CassandraTemplate(SESSION); } } @@ -160,8 +160,6 @@ public class CassandraOperationsTest extends AbstractEmbeddedCassandraIntegratio @SuppressWarnings("unchecked") public void ingestionTestListOfList() { - log.info("Keyspace => " + keyspace); - String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; List> values = new LinkedList>(); @@ -185,8 +183,6 @@ public class CassandraOperationsTest extends AbstractEmbeddedCassandraIntegratio @Test public void ingestionTestObjectArray() { - log.info("Keyspace => " + keyspace); - String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; Object[][] values = new Object[3][]; diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/AlterKeyspaceCqlGeneratorTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/AlterKeyspaceCqlGeneratorTests.java index f54ef316e..04e8eac5e 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/AlterKeyspaceCqlGeneratorTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/AlterKeyspaceCqlGeneratorTests.java @@ -11,6 +11,7 @@ import org.springframework.cassandra.core.keyspace.AlterKeyspaceSpecification; 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.test.unit.support.Utils; public class AlterKeyspaceCqlGeneratorTests { @@ -23,8 +24,8 @@ public class AlterKeyspaceCqlGeneratorTests { private static void assertReplicationMap(Map replicationMap, String cql) { assertTrue(cql.contains(" WITH replication = { ")); - - for (Map.Entry entry : replicationMap.entrySet() ) { + + for (Map.Entry entry : replicationMap.entrySet()) { String keyValuePair = "'" + entry.getKey().getName() + "' : '" + entry.getValue().toString() + "'"; assertTrue(cql.contains(keyValuePair)); } @@ -38,28 +39,28 @@ public class AlterKeyspaceCqlGeneratorTests { * Convenient base class that other test classes can use so as not to repeat the generics declarations. */ public static abstract class AlterKeyspaceTest extends - KeyspaceOperationCqlGeneratorTest { + KeyspaceOperationCqlGeneratorTest { } public static class CompleteTest extends AlterKeyspaceTest { - public String name = "mykeyspace"; + public String name = Utils.randomKeyspaceName(); public Boolean durableWrites = true; - + public Map replicationMap = new HashMap(); + @Override public AlterKeyspaceSpecification specification() { - replicationMap.put( new DefaultOption( "class", String.class, false, false, true ), "SimpleStrategy" ); - replicationMap.put( new DefaultOption( "replication_factor", Long.class, false, false, true ), 1 ); - replicationMap.put( new DefaultOption( "dc1", Long.class, false, false, true ), 2 ); - replicationMap.put( new DefaultOption( "dc2", Long.class, false, false, true ), 3 ); - - return AlterKeyspaceSpecification.alterKeyspace() - .name(name) - .with(KeyspaceOption.REPLICATION, replicationMap) + replicationMap.put(new DefaultOption("class", String.class, false, false, true), "SimpleStrategy"); + replicationMap.put(new DefaultOption("replication_factor", Long.class, false, false, true), 1); + replicationMap.put(new DefaultOption("dc1", Long.class, false, false, true), 2); + replicationMap.put(new DefaultOption("dc2", Long.class, false, false, true), 3); + + return AlterKeyspaceSpecification.alterKeyspace().name(name).with(KeyspaceOption.REPLICATION, replicationMap) .with(KeyspaceOption.DURABLE_WRITES, durableWrites); } + @Override public AlterKeyspaceCqlGenerator generator() { return new AlterKeyspaceCqlGenerator(specification); } @@ -78,20 +79,20 @@ public class AlterKeyspaceCqlGeneratorTests { public String name = "mytable"; public Boolean durableWrites = true; - + public Map replicationMap = new HashMap(); + @Override public AlterKeyspaceSpecification specification() { - replicationMap.put( new DefaultOption( "class", String.class, false, false, true ), "SimpleStrategy" ); - replicationMap.put( new DefaultOption( "replication_factor", Long.class, false, false, true ), 1 ); - replicationMap.put( new DefaultOption( "dc1", Long.class, false, false, true ), 2 ); - replicationMap.put( new DefaultOption( "dc2", Long.class, false, false, true ), 3 ); - - return AlterKeyspaceSpecification.alterKeyspace() - .name(name) - .with(KeyspaceOption.REPLICATION, replicationMap); + replicationMap.put(new DefaultOption("class", String.class, false, false, true), "SimpleStrategy"); + replicationMap.put(new DefaultOption("replication_factor", Long.class, false, false, true), 1); + replicationMap.put(new DefaultOption("dc1", Long.class, false, false, true), 2); + replicationMap.put(new DefaultOption("dc2", Long.class, false, false, true), 3); + + return AlterKeyspaceSpecification.alterKeyspace().name(name).with(KeyspaceOption.REPLICATION, replicationMap); } + @Override public AlterKeyspaceCqlGenerator generator() { return new AlterKeyspaceCqlGenerator(specification); } diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/CreateKeyspaceCqlGeneratorTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/CreateKeyspaceCqlGeneratorTests.java index fbcdba60f..9d3f87c19 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/CreateKeyspaceCqlGeneratorTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/CreateKeyspaceCqlGeneratorTests.java @@ -13,6 +13,7 @@ import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification; 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.test.unit.support.Utils; public class CreateKeyspaceCqlGeneratorTests { @@ -52,7 +53,7 @@ public class CreateKeyspaceCqlGeneratorTests { public static class BasicTest extends CreateKeyspaceTest { - public String name = randomKeyspaceName(); + public String name = Utils.randomKeyspaceName(); public Boolean durableWrites = true; public Map replicationMap = KeyspaceAttributes.newSimpleReplication(); @@ -77,7 +78,7 @@ public class CreateKeyspaceCqlGeneratorTests { public static class NetworkTopologyTest extends CreateKeyspaceTest { - public String name = randomKeyspaceName(); + public String name = Utils.randomKeyspaceName(); public Boolean durableWrites = false; public Map replicationMap = new HashMap(); diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/DropKeyspaceCqlGeneratorTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/DropKeyspaceCqlGeneratorTests.java index 2090042dc..daa302090 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/DropKeyspaceCqlGeneratorTests.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/DropKeyspaceCqlGeneratorTests.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; import org.springframework.cassandra.core.cql.generator.DropKeyspaceCqlGenerator; import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification; +import org.springframework.cassandra.test.unit.support.Utils; public class DropKeyspaceCqlGeneratorTests { @@ -24,7 +25,7 @@ public class DropKeyspaceCqlGeneratorTests { public static class BasicTest extends DropTableTest { - public String name = randomKeyspaceName(); + public String name = Utils.randomKeyspaceName(); @Override public DropKeyspaceSpecification specification() { diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/KeyspaceOperationCqlGeneratorTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/KeyspaceOperationCqlGeneratorTest.java index 391465994..cc45ad69b 100644 --- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/KeyspaceOperationCqlGeneratorTest.java +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/KeyspaceOperationCqlGeneratorTest.java @@ -6,7 +6,7 @@ import org.apache.commons.lang.StringUtils; import org.junit.Test; import org.springframework.cassandra.core.cql.generator.KeyspaceNameCqlGenerator; import org.springframework.cassandra.core.cql.generator.TableNameCqlGenerator; -import org.springframework.cassandra.core.keyspace.KeyspaceNameSpecification; +import org.springframework.cassandra.core.keyspace.KeyspaceActionSpecification; import org.springframework.cassandra.core.keyspace.TableNameSpecification; /** @@ -19,7 +19,7 @@ import org.springframework.cassandra.core.keyspace.TableNameSpecification; * @param The type of the {@link TableNameSpecification} * @param The type of the {@link TableNameCqlGenerator} */ -public abstract class KeyspaceOperationCqlGeneratorTest, G extends KeyspaceNameCqlGenerator> { +public abstract class KeyspaceOperationCqlGeneratorTest, G extends KeyspaceNameCqlGenerator> { public abstract S specification(); diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/support/Utils.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/support/Utils.java new file mode 100644 index 000000000..29b136cdc --- /dev/null +++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/support/Utils.java @@ -0,0 +1,11 @@ +package org.springframework.cassandra.test.unit.support; + +import java.util.UUID; + +public class Utils { + + public static String randomKeyspaceName() { + return "ks" + UUID.randomUUID().toString().replace("-", ""); + } + +} diff --git a/spring-cassandra/src/test/resources/logback-test.xml b/spring-cassandra/src/test/resources/logback-test.xml index 7db55523f..a410f7fb5 100644 --- a/spring-cassandra/src/test/resources/logback-test.xml +++ b/spring-cassandra/src/test/resources/logback-test.xml @@ -10,8 +10,8 @@ - - + + diff --git a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest-context.xml b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest-context.xml index 24b776df2..ca02147d5 100644 --- a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest-context.xml +++ b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest-context.xml @@ -8,21 +8,19 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + location="classpath:build.properties,classpath:/org/springframework/cassandra/test/integration/config/xml/FullySpecifiedKeyspaceCreatingXmlConfigTest.properties" /> - - + - + - - + diff --git a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/MinimalKeyspaceCreatingXmlConfigTest-context.xml b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/MinimalKeyspaceCreatingXmlConfigTest-context.xml index 688cb3dba..109528a9d 100644 --- a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/MinimalKeyspaceCreatingXmlConfigTest-context.xml +++ b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/MinimalKeyspaceCreatingXmlConfigTest-context.xml @@ -7,8 +7,11 @@ 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"> - - + + + + diff --git a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/MinimalXmlConfigTest-context.xml b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/MinimalXmlConfigTest-context.xml index e0939fdc3..fb716513d 100644 --- a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/MinimalXmlConfigTest-context.xml +++ b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/MinimalXmlConfigTest-context.xml @@ -6,7 +6,10 @@ 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"> - + + + diff --git a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/PropertyPlaceholderNamespaceCreatingXmlConfigTest-context.xml b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/PropertyPlaceholderNamespaceCreatingXmlConfigTest-context.xml new file mode 100644 index 000000000..317317470 --- /dev/null +++ b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/PropertyPlaceholderNamespaceCreatingXmlConfigTest-context.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest-context.xml b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest-context.xml index 39e2ff612..ca3483d66 100644 --- a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest-context.xml +++ b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest-context.xml @@ -7,10 +7,10 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + location="classpath:build.properties" /> + contactPoints="localhost" port="${build.cassandra.native_transport_port}"> @@ -18,13 +18,13 @@ min-simultaneous-requests="25" max-simultaneous-requests="100" core-connections="1" max-connections="2" /> + keyspace-name="xmlconfigtest" /> diff --git a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/ppncxct.properties b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/ppncxct.properties new file mode 100644 index 000000000..5ecb62dcf --- /dev/null +++ b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/ppncxct.properties @@ -0,0 +1,34 @@ +cluster.contactPoints=localhost +cluster.port=@build.cassandra.native_transport_port@ +cluster.compression=SNAPPY +cluster.deferredInit=true +cluster.metricsEnabled=false +cluster.jmxReportingEnabled=false +cluster.reconnection.delayMillis=5000 +cluster.sslEnabled= true +keyspace.name=ppncxct +keyspace.action=CREATE +dc1.name=DCJAX +dc1.rf=2 +dc2.name=DCCTL +dc2.rf=3 +lb.policy.dcAware.remoteHosts=4 +lb.policy.dcAware.localDc=DCJAX +auth.username=test +auth.password=pass +socket.connectTimeoutMillis=5000 +socket.keepAlive=true +socket.readTimeoutMillis=60000 +socket.receiveBufferSize=1024 +socket.sendBufferSize=2048 +socket.reuseAddress=true +socket.soLinger=5 +socket.tcpNoDelay=false +local.min.requests=10 +local.max.requests=20 +local.core.connections=30 +local.max.connections=40 +remote.min.requests=5 +remote.max.requests=10 +remote.core.connections=15 +remote.max.connections=20 diff --git a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/xmlconfigtest.properties b/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/xmlconfigtest.properties deleted file mode 100644 index 2d7a6eb68..000000000 --- a/spring-cassandra/src/test/resources/org/springframework/cassandra/test/integration/config/xml/xmlconfigtest.properties +++ /dev/null @@ -1,3 +0,0 @@ -cassandra.contactPoints=localhost -cassandra.port=9042 -cassandra.keyspace=xmlconfigtest diff --git a/spring-cassandra/src/test/resources/spring-cassandra.yaml b/spring-cassandra/src/test/resources/spring-cassandra.yaml index 67c59aba4..b81dca685 100644 --- a/spring-cassandra/src/test/resources/spring-cassandra.yaml +++ b/spring-cassandra/src/test/resources/spring-cassandra.yaml @@ -303,11 +303,11 @@ trickle_fsync: false trickle_fsync_interval_in_kb: 10240 # TCP port, for commands and data -storage_port: 7000 +storage_port: ${build.cassandra.storage_port} # SSL port, for encrypted communication. Unused unless enabled in # encryption_options -ssl_storage_port: 7001 +ssl_storage_port: ${build.cassandra.ssl_storage_port} # Address to bind to and tell other Cassandra nodes to connect to. You # _must_ change this if you want multiple nodes to be able to @@ -334,7 +334,7 @@ listen_address: localhost # same as the rpc_address. The port however is different and specified below. start_native_transport: true # port for the CQL native transport to listen for clients on -native_transport_port: 9042 +native_transport_port: ${build.cassandra.native_transport_port} # The minimum and maximum threads for handling requests when the native # transport is used. They are similar to rpc_min_threads and rpc_max_threads, # though the defaults differ slightly. @@ -352,7 +352,7 @@ start_rpc: true # (i.e. it will be based on the configured hostname of the node). rpc_address: localhost # port for Thrift to listen for clients on -rpc_port: 9160 +rpc_port: ${build.cassandra.rpc_port} # enable or disable keepalive on rpc connections rpc_keepalive: true diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/config/DriverTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/config/DriverTests.java deleted file mode 100644 index df4ef09e6..000000000 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/config/DriverTests.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.springframework.data.cassandra.test.integration.config; - -import java.io.IOException; - -import org.apache.cassandra.exceptions.ConfigurationException; -import org.apache.thrift.transport.TTransportException; -import org.cassandraunit.utils.EmbeddedCassandraServerHelper; -import org.junit.After; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.Session; - -public class DriverTests { - - @BeforeClass - public static void startCassandra() throws IOException, TTransportException, ConfigurationException, - InterruptedException { - EmbeddedCassandraServerHelper.startEmbeddedCassandra("cassandra.yaml"); - } - - @Test - public void test() throws Exception { - - Cluster.Builder builder = Cluster.builder().addContactPoint("127.0.0.1"); - - // builder.withCompression(ProtocolOptions.Compression.SNAPPY); - - Cluster cluster = builder.build(); - - Session session = cluster.connect(); - - session.shutdown(); - - cluster.shutdown(); - - } - - @After - public void clearCassandra() { - EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); - } -} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/config/TestConfig.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/config/TestConfig.java index 44f657d4b..8df1af695 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/config/TestConfig.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/config/TestConfig.java @@ -1,5 +1,6 @@ package org.springframework.data.cassandra.test.integration.config; +import org.springframework.cassandra.test.integration.support.BuildProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.cassandra.config.java.AbstractSpringDataCassandraConfiguration; @@ -18,11 +19,20 @@ import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext @Configuration public class TestConfig extends AbstractSpringDataCassandraConfiguration { - public static final String keyspaceName = "test"; + public static final BuildProperties PROPS = new BuildProperties(); + public static final int PORT = PROPS.getCassandraPort(); + public static final int RPC_PORT = PROPS.getCassandraRpcPort(); + + public static final String KEYSPACE_NAME = "test"; @Override protected String getKeyspaceName() { - return keyspaceName; + return KEYSPACE_NAME; + } + + @Override + protected int getPort() { + return PORT; } @Bean @@ -32,6 +42,6 @@ public class TestConfig extends AbstractSpringDataCassandraConfiguration { @Bean public CassandraDataOperations cassandraDataTemplate() throws Exception { - return new CassandraDataTemplate(session().getObject(), converter(), keyspaceName); + return new CassandraDataTemplate(session().getObject(), converter(), KEYSPACE_NAME); } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraAdminTest.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraAdminTest.java index ff1b8f81e..0b06d0a99 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraAdminTest.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraAdminTest.java @@ -63,7 +63,7 @@ public class CassandraAdminTest { /* * Load data file to creat the test keyspace before we init the template */ - DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:9160"); + DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:" + TestConfig.RPC_PORT); dataLoader.load(new ClassPathYamlDataSet("cassandra-keyspace.yaml")); } @@ -74,7 +74,7 @@ public class CassandraAdminTest { /* * Load data file to creat the test keyspace before we init the template */ - DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:9160"); + DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:" + TestConfig.RPC_PORT); dataLoader.load(new ClassPathYamlDataSet("cassandra-keyspace.yaml")); } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraDataOperationsTest.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraDataOperationsTest.java index bc4bff66c..95da10e4d 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraDataOperationsTest.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraDataOperationsTest.java @@ -40,6 +40,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cassandra.core.ConsistencyLevel; import org.springframework.cassandra.core.QueryOptions; import org.springframework.cassandra.core.RetryPolicy; +import org.springframework.cassandra.test.integration.support.BuildProperties; import org.springframework.data.cassandra.core.CassandraDataOperations; import org.springframework.data.cassandra.test.integration.config.TestConfig; import org.springframework.data.cassandra.test.integration.table.Book; @@ -65,11 +66,12 @@ public class CassandraDataOperationsTest { private static Logger log = LoggerFactory.getLogger(CassandraDataOperationsTest.class); + private final static BuildProperties PROPS = new BuildProperties(); private final static String CASSANDRA_CONFIG = "cassandra.yaml"; private final static String KEYSPACE_NAME = "test"; private final static String CASSANDRA_HOST = "localhost"; - private final static int CASSANDRA_NATIVE_PORT = 9042; - private final static int CASSANDRA_THRIFT_PORT = 9160; + private final static int CASSANDRA_NATIVE_PORT = PROPS.getCassandraPort(); + private final static int CASSANDRA_THRIFT_PORT = PROPS.getCassandraRpcPort(); @Rule public CassandraCQLUnit cassandraCQLUnit = new CassandraCQLUnit(new ClassPathCQLDataSet("cql-dataload.cql", diff --git a/spring-data-cassandra/src/test/resources/cassandra.yaml b/spring-data-cassandra/src/test/resources/cassandra.yaml index 82fcfc5ad..1fed13912 100644 --- a/spring-data-cassandra/src/test/resources/cassandra.yaml +++ b/spring-data-cassandra/src/test/resources/cassandra.yaml @@ -303,11 +303,11 @@ trickle_fsync: false trickle_fsync_interval_in_kb: 10240 # TCP port, for commands and data -storage_port: 7000 +storage_port: ${build.cassandra.storage_port} # SSL port, for encrypted communication. Unused unless enabled in # encryption_options -ssl_storage_port: 7001 +ssl_storage_port: ${build.cassandra.ssl_storage_port} # Address to bind to and tell other Cassandra nodes to connect to. You # _must_ change this if you want multiple nodes to be able to @@ -334,7 +334,7 @@ listen_address: localhost # same as the rpc_address. The port however is different and specified below. start_native_transport: true # port for the CQL native transport to listen for clients on -native_transport_port: 9042 +native_transport_port: ${build.cassandra.native_transport_port} # The minimum and maximum threads for handling requests when the native # transport is used. They are similar to rpc_min_threads and rpc_max_threads, # though the defaults differ slightly. @@ -352,7 +352,7 @@ start_rpc: true # (i.e. it will be based on the configured hostname of the node). rpc_address: localhost # port for Thrift to listen for clients on -rpc_port: 9160 +rpc_port: ${build.cassandra.rpc_port} # enable or disable keepalive on rpc connections rpc_keepalive: true diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/config/CassandraNamespaceTests-context.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/config/CassandraNamespaceTests-context.xml index b3fd33498..360df39ce 100644 --- a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/config/CassandraNamespaceTests-context.xml +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/config/CassandraNamespaceTests-context.xml @@ -11,8 +11,9 @@ - + @@ -22,7 +23,7 @@ - @@ -36,7 +37,7 @@ - diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/config/cassandra.properties b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/config/cassandra.properties index f60144610..242812e68 100644 --- a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/config/cassandra.properties +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/config/cassandra.properties @@ -1,3 +1,3 @@ cassandra.contactPoints=localhost -cassandra.port=9042 +cassandra.native_transport_port=${build.cassandra.native_transport_port} cassandra.keyspace=TestKS123 diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml index 543fe6614..65c4cc4d9 100644 --- a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml @@ -13,7 +13,7 @@ location="classpath:/org/springframework/data/cassandra/test/integration/repository/cassandra.properties" /> diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/cassandra.properties b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/cassandra.properties index 6a0dd3197..242812e68 100644 --- a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/cassandra.properties +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/cassandra.properties @@ -1,7 +1,3 @@ cassandra.contactPoints=localhost -cassandra.port=9042 +cassandra.native_transport_port=${build.cassandra.native_transport_port} cassandra.keyspace=TestKS123 - - - -