DATACASS-271 - Polishing.

Add author tags. Add/update license headers where needed. Remove calls to deprecated methods. Adopt pooling options after the driver update. Add hints_directory for Cassandra 3.

Reduce driver baseline to core driver 3.0.1. The DSE driver requires the core driver itself and can be added as dependency to user projects while retaining full compatibility. As of now the DSE driver is rc1 hence it requires core rc1.

Use getTimestamp for timestamp type methods as the driver aligned the method to the type. Support short, byte and time. Enable LocalDate return type and add tests for native supported types.

Change long to bigint type as long was mapped to the counter type when creating tables. Align the default to bigint as bigint is the better choice since table creation uses mostly regular tables and not counter tables. Type can be overriden using @CassandraType.

We now support setting NettyOptions on CassandraCqlClusterFactoryBean and AbstractClusterConfiguration. The cassandra driver 2.1.9 changed its default shutdown behavior by introducing a 2 second quiet period when shutting down Cluster instances. This change was retained throughout the 3.0 driver which slow the test down by an order of magnitude. Configure QueryOptions on tests to prevent delays caused by the asynchronous schema refresh.

Original pull request: #56.
Related pull request: #52.
Related ticket: DATACASS-169.
This commit is contained in:
Mark Paluch
2016-05-04 15:33:35 +02:00
committed by John Blum
parent a920b530df
commit be495728d9
45 changed files with 1269 additions and 385 deletions

87
pom.xml
View File

@@ -21,25 +21,6 @@
<description>Spring Data Cassandra</description>
<url>http://projects.spring.io/spring-data-cassandra/</url>
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-cassandra</dist.id>
<springdata.commons>1.13.0.BUILD-SNAPSHOT</springdata.commons>
<cassandra-unit.version>3.0.0.1</cassandra-unit.version>
<el.version>1.0</el.version>
<failsafe.version>2.16</failsafe.version>
<jamm.version>0.3.1</jamm.version>
<cassandra.version>3.0.0</cassandra.version>
<cassandra-driver-dse.version>3.0.0-rc1</cassandra-driver-dse.version>
<build.cassandra.mode>embedded</build.cassandra.mode>
<build.cassandra.host>localhost</build.cassandra.host>
<build.cassandra.native_transport_port>19042</build.cassandra.native_transport_port>
<build.cassandra.rpc_port>19160</build.cassandra.rpc_port>
<build.cassandra.storage_port>17000</build.cassandra.storage_port>
<build.cassandra.ssl_storage_port>17001</build.cassandra.ssl_storage_port>
</properties>
<developers>
<developer>
<id>madams</id>
@@ -83,6 +64,22 @@
<module>spring-data-cassandra-distribution</module>
</modules>
<properties>
<build.cassandra.host>localhost</build.cassandra.host>
<build.cassandra.mode>embedded</build.cassandra.mode>
<build.cassandra.native_transport_port>19042</build.cassandra.native_transport_port>
<build.cassandra.rpc_port>19160</build.cassandra.rpc_port>
<build.cassandra.ssl_storage_port>17001</build.cassandra.ssl_storage_port>
<build.cassandra.storage_port>17000</build.cassandra.storage_port>
<cassandra.version>3.0.0</cassandra.version>
<cassandra-driver.version>3.0.1</cassandra-driver.version>
<dist.id>spring-data-cassandra</dist.id>
<el.version>1.0</el.version>
<failsafe.version>2.16</failsafe.version>
<project.type>multi</project.type>
<springdata.commons>1.13.0.BUILD-SNAPSHOT</springdata.commons>
</properties>
<repositories>
<repository>
<id>spring-libs-snapshot</id>
@@ -99,38 +96,24 @@
<dependencyManagement>
<dependencies>
<!-- Cassandra Driver -->
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-dse</artifactId>
<version>${cassandra-driver-dse.version}</version>
<artifactId>cassandra-driver-core</artifactId>
<version>${cassandra-driver.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<artifactId>netty-handler</artifactId>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Logging Dependencies -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j}</version>
<scope>test</scope>
</dependency>
<!-- CDI -->
<dependency>
<groupId>javax.enterprise</groupId>
@@ -140,6 +123,24 @@
<optional>true</optional>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>cassandra-all</artifactId>
<version>${cassandra.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
@@ -194,7 +195,7 @@
<dependencies>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-dse</artifactId>
<artifactId>cassandra-driver-core</artifactId>
</dependency>
</dependencies>

View File

@@ -50,7 +50,7 @@
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-dse</artifactId>
<artifactId>cassandra-driver-core</artifactId>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
@@ -76,18 +76,6 @@
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>cassandra-all</artifactId>
<version>${cassandra.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>

View File

@@ -42,6 +42,7 @@ import com.datastax.driver.core.AuthProvider;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.LatencyTracker;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.PoolingOptions;
import com.datastax.driver.core.ProtocolOptions.Compression;
import com.datastax.driver.core.ProtocolVersion;
@@ -93,6 +94,7 @@ public class CassandraCqlClusterFactoryBean
private AuthProvider authProvider;
private String username;
private String password;
private NettyOptions nettyOptions;
private ProtocolVersion protocolVersion;
// Policies
@@ -189,6 +191,10 @@ public class CassandraCqlClusterFactoryBean
}
}
if (nettyOptions != null) {
builder.withNettyOptions(nettyOptions);
}
if (loadBalancingPolicy != null) {
builder.withLoadBalancingPolicy(loadBalancingPolicy);
}
@@ -275,8 +281,8 @@ public class CassandraCqlClusterFactoryBean
for (Object spec : specs) {
String cql = (spec instanceof CreateKeyspaceSpecification)
? new CreateKeyspaceCqlGenerator((CreateKeyspaceSpecification) spec).toCql()
: new DropKeyspaceCqlGenerator((DropKeyspaceSpecification) spec).toCql();
? new CreateKeyspaceCqlGenerator((CreateKeyspaceSpecification) spec).toCql()
: new DropKeyspaceCqlGenerator((DropKeyspaceSpecification) spec).toCql();
if (log.isDebugEnabled()) {
log.debug("executing raw CQL [{}]", cql);
@@ -329,7 +335,7 @@ public class CassandraCqlClusterFactoryBean
}
/**
* Set the {@link PoolingOptions}.
* Set the {@link PoolingOptions} to configure the connection pooling behavior.
*/
public void setPoolingOptions(PoolingOptions poolingOptions) {
this.poolingOptions = poolingOptions;
@@ -352,7 +358,7 @@ public class CassandraCqlClusterFactoryBean
}
/**
* Set the {@link QueryOptions}.
* Set the {@link QueryOptions} to tune to defaults for individual queries.
*/
public void setQueryOptions(QueryOptions queryOptions) {
this.queryOptions = queryOptions;
@@ -366,21 +372,31 @@ public class CassandraCqlClusterFactoryBean
}
/**
* Set the {@link LoadBalancingPolicy}.
* Set the {@link NettyOptions} used by a client to customize the driver's underlying Netty layer.
*
* @param nettyOptions
* @since 1.5
*/
public void setNettyOptions(NettyOptions nettyOptions) {
this.nettyOptions = nettyOptions;
}
/**
* Set the {@link LoadBalancingPolicy} that decides which Cassandra hosts to contact for each new query.
*/
public void setLoadBalancingPolicy(LoadBalancingPolicy loadBalancingPolicy) {
this.loadBalancingPolicy = loadBalancingPolicy;
}
/**
* Set the {@link ReconnectionPolicy}.
* Set the {@link ReconnectionPolicy} that decides how often the reconnection to a dead node is attempted.
*/
public void setReconnectionPolicy(ReconnectionPolicy reconnectionPolicy) {
this.reconnectionPolicy = reconnectionPolicy;
}
/**
* Set the {@link RetryPolicy}.
* Set the {@link RetryPolicy} that defines a default behavior to adopt when a request fails.
*/
public void setRetryPolicy(RetryPolicy retryPolicy) {
this.retryPolicy = retryPolicy;

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors.
*
* Copyright 2013-2016 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.
@@ -24,9 +24,10 @@ import com.datastax.driver.core.PoolingOptions;
/**
* Pooling Options Factory Bean.
*
*
* @author Matthew T. Adams
* @author David Webb
* @author Mark Paluch
*/
public class PoolingOptionsFactoryBean implements FactoryBean<PoolingOptions>, InitializingBean, DisposableBean {
@@ -79,7 +80,7 @@ public class PoolingOptionsFactoryBean implements FactoryBean<PoolingOptions>, I
}
if (localMaxSimultaneousRequests != null) {
poolingOptions.setNewConnectionThreshold(HostDistance.LOCAL, localMaxSimultaneousRequests);
poolingOptions.setMaxRequestsPerConnection(HostDistance.LOCAL, localMaxSimultaneousRequests);
}
if (remoteMaxConnections != null) {
@@ -103,7 +104,7 @@ public class PoolingOptionsFactoryBean implements FactoryBean<PoolingOptions>, I
}
if (remoteMaxSimultaneousRequests != null) {
poolingOptions.setNewConnectionThreshold(HostDistance.REMOTE,
poolingOptions.setMaxRequestsPerConnection(HostDistance.REMOTE,
remoteMaxSimultaneousRequests);
}

View File

@@ -26,6 +26,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.datastax.driver.core.AuthProvider;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.PoolingOptions;
import com.datastax.driver.core.ProtocolVersion;
import com.datastax.driver.core.QueryOptions;
@@ -61,6 +62,7 @@ public abstract class AbstractClusterConfiguration {
bean.setReconnectionPolicy(getReconnectionPolicy());
bean.setRetryPolicy(getRetryPolicy());
bean.setMetricsEnabled(getMetricsEnabled());
bean.setNettyOptions(getNettyOptions());
bean.setPoolingOptions(getPoolingOptions());
bean.setQueryOptions(getQueryOptions());
@@ -158,6 +160,16 @@ public abstract class AbstractClusterConfiguration {
return CassandraCqlClusterFactoryBean.DEFAULT_METRICS_ENABLED;
}
/**
* Returns the {@link NettyOptions}. Defaults to {@link NettyOptions#DEFAULT_INSTANCE}.
*
* @return
* @since 1.5
*/
protected NettyOptions getNettyOptions() {
return NettyOptions.DEFAULT_INSTANCE;
}
/**
* Returns the {@link PoolingOptions}.
*

View File

@@ -1,8 +1,34 @@
/*
* Copyright 2016 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.java;
import org.springframework.cassandra.core.CqlTemplate;
import org.springframework.context.annotation.Bean;
/**
* Abstract configuration class to create a {@link CqlTemplate} and inheriting {@link com.datastax.driver.core.Session}
* and {@link com.datastax.driver.core.Cluster} creation. This class is usually extended by user configuration classes.
*
* @author Matthew T. Adams
* @see org.springframework.cassandra.config.java.AbstractClusterConfiguration
* @see org.springframework.cassandra.config.java.AbstractSessionConfiguration
* @see com.datastax.driver.core.Session
* @see com.datastax.driver.core.Cluster
* @see CqlTemplate
*/
public abstract class AbstractCqlTemplateConfiguration extends AbstractSessionConfiguration {
@Bean

View File

@@ -89,6 +89,7 @@ import com.datastax.driver.core.querybuilder.Update;
* @author David Webb
* @author Matthew Adams
* @author Ryan Scheidter
* @author Antoine Toulme
*/
public class CqlTemplate extends CassandraAccessor implements CqlOperations {

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cassandra.core.converter;
import java.util.ArrayList;
@@ -34,6 +33,7 @@ import com.datastax.driver.core.Row;
* @author Matthew T. Adams
* @author Stefan Birkner
* @author Mark Paluch
* @author Antoine Toulme
*/
@ReadingConverter
public class RowToListConverter implements Converter<Row, List<Object>> {
@@ -47,13 +47,16 @@ public class RowToListConverter implements Converter<Row, List<Object>> {
return null;
}
CodecRegistry codecRegistry = CodecRegistry.DEFAULT_INSTANCE;
ColumnDefinitions cols = row.getColumnDefinitions();
List<Object> list = new ArrayList<Object>(cols.size());
for (Definition def : cols.asList()) {
String name = def.getName();
list.add(row.isNull(name) ? null : CodecRegistry.DEFAULT_INSTANCE.codecFor(def.getType()).deserialize(
row.getBytesUnsafe(name), ProtocolVersion.NEWEST_SUPPORTED));
list.add(row.isNull(name) ? null
: codecRegistry.codecFor(def.getType()).deserialize(row.getBytesUnsafe(name),
ProtocolVersion.NEWEST_SUPPORTED));
}
return list;

View File

@@ -34,6 +34,7 @@ import com.datastax.driver.core.Row;
* @author Matthew T. Adams
* @author David Webb
* @author Mark Paluch
* @author Antoine Toulme
*/
@ReadingConverter
public class RowToMapConverter implements Converter<Row, Map<String, Object>> {
@@ -47,16 +48,18 @@ public class RowToMapConverter implements Converter<Row, Map<String, Object>> {
return null;
}
CodecRegistry codecRegistry = CodecRegistry.DEFAULT_INSTANCE;
ColumnDefinitions cols = row.getColumnDefinitions();
Map<String, Object> map = new HashMap<String, Object>(cols.size());
for (Definition def : cols.asList()) {
String name = def.getName();
map.put(
name,
row.isNull(name) ? null : CodecRegistry.DEFAULT_INSTANCE.codecFor(def.getType())
.deserialize(row.getBytesUnsafe(name), ProtocolVersion.NEWEST_SUPPORTED));
map.put(name,
row.isNull(name) ? null
: codecRegistry.codecFor(def.getType()).deserialize(row.getBytesUnsafe(name),
ProtocolVersion.NEWEST_SUPPORTED));
}
return map;

View File

@@ -24,6 +24,7 @@ import org.springframework.test.util.ReflectionTestUtils;
import com.datastax.driver.core.AuthProvider;
import com.datastax.driver.core.Configuration;
import com.datastax.driver.core.JdkSSLOptions;
import com.datastax.driver.core.PlainTextAuthProvider;
import com.datastax.driver.core.PoolingOptions;
import com.datastax.driver.core.ProtocolOptions.Compression;
@@ -257,7 +258,7 @@ public class CassandraCqlClusterFactoryBeanUnitTests {
@Test
public void shouldSetSslOptions() throws Exception {
SSLOptions sslOptions = new SSLOptions();
SSLOptions sslOptions = JdkSSLOptions.builder().build();
CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean();
bean.setSslEnabled(true);
@@ -278,7 +279,7 @@ public class CassandraCqlClusterFactoryBeanUnitTests {
bean.setMetricsEnabled(false);
bean.afterPropertiesSet();
assertThat(getConfiguration(bean).getMetricsOptions(), is(nullValue()));
assertThat(getConfiguration(bean).getMetricsOptions().isEnabled(), is(false));
}
/**

View File

@@ -245,7 +245,7 @@ public class AbstractClusterConfigurationUnitTests {
};
Cluster cluster = getCluster(clusterConfiguration);
assertThat(getConfiguration(cluster).getMetricsOptions(), is(nullValue()));
assertThat(getConfiguration(cluster).getMetricsOptions().isEnabled(), is(false));
}
/**

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2016 the original author or authors.
* Copyright 2013-2016 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
* 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,
@@ -73,7 +73,7 @@ public class CassandraExceptionTranslatorTest {
@Test
public void testInvalidConfigurationInQueryException() {
String msg = "msg";
InvalidQueryException cx = new InvalidConfigurationInQueryException(msg);
InvalidQueryException cx = new InvalidConfigurationInQueryException(null, msg);
DataAccessException dax = tx.translateExceptionIfPossible(cx);
assertNotNull(dax);
assertTrue(dax instanceof CassandraInvalidConfigurationInQueryException);

View File

@@ -27,11 +27,13 @@ import org.junit.rules.ExternalResource;
import org.springframework.cassandra.core.SessionCallback;
import org.springframework.cassandra.test.integration.support.CassandraConnectionProperties;
import org.springframework.cassandra.test.integration.support.CqlDataSet;
import org.springframework.cassandra.test.integration.support.FastShutdownNettyOptions;
import org.springframework.dao.DataAccessException;
import org.springframework.util.Assert;
import org.springframework.util.SocketUtils;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.QueryOptions;
import com.datastax.driver.core.Session;
/**
@@ -48,6 +50,7 @@ import com.datastax.driver.core.Session;
* </pre>
*
* @author Mark Paluch
* @since 1.5
*/
public class CassandraRule extends ExternalResource {
@@ -70,7 +73,7 @@ public class CassandraRule extends ExternalResource {
* @param yamlConfigurationResource name of the configuration resource, must not be {@literal null} and not empty
*/
public CassandraRule(String yamlConfigurationResource) {
this(yamlConfigurationResource, EmbeddedCassandraServerHelper.DEFAULT_STARTUP_TIMEOUT);
this(yamlConfigurationResource, EmbeddedCassandraServerHelper.DEFAULT_STARTUP_TIMEOUT_MS);
}
/**
@@ -310,7 +313,15 @@ public class CassandraRule extends ExternalResource {
port = properties.getCassandraPort();
}
cassandraPort = port;
cluster = new Cluster.Builder().addContactPoints(hostIp).withPort(port).build();
QueryOptions queryOptions = new QueryOptions();
queryOptions.setRefreshSchemaIntervalMillis(0);
cluster = new Cluster.Builder().addContactPoints(hostIp).//
withPort(port).//
withQueryOptions(queryOptions).//
withNettyOptions(FastShutdownNettyOptions.INSTANCE).//
build();
} else {
cluster = parent.cluster;
cassandraPort = parent.cassandraPort;

View File

@@ -22,10 +22,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.cassandra.config.DatabaseDescriptor;
@@ -45,7 +42,7 @@ class EmbeddedCassandraServerHelper {
private static Logger log = LoggerFactory.getLogger(EmbeddedCassandraServerHelper.class);
public static final long DEFAULT_STARTUP_TIMEOUT = 10000;
public static final long DEFAULT_STARTUP_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(20);
public static final String DEFAULT_TMP_DIR = "target/embeddedCassandra";
private final static AtomicReference<Object> sync = new AtomicReference<Object>();

View File

@@ -15,13 +15,16 @@
*/
package org.springframework.cassandra.test.integration.config;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cassandra.config.CassandraCqlClusterFactoryBean;
import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest;
import org.springframework.cassandra.test.integration.support.FastShutdownNettyOptions;
import org.springframework.test.util.ReflectionTestUtils;
import com.datastax.driver.core.ProtocolVersion;
@@ -29,8 +32,9 @@ import com.datastax.driver.core.ProtocolVersion;
* Unit tests for {@link CassandraCqlClusterFactoryBean}.
*
* @author Kirk Clemens
* @author Mark Paluch
*/
public class CassandraCqlClusterFactoryBeanIntegrationTests extends AbstractEmbeddedCassandraIntegrationTest {
public class CassandraCqlClusterFactoryBeanIntegrationTests {
private CassandraCqlClusterFactoryBean cassandraCqlClusterFactoryBean;
@@ -47,27 +51,26 @@ public class CassandraCqlClusterFactoryBeanIntegrationTests extends AbstractEmbe
@Test
public void configuredProtocolVersionShouldBeSet() throws Exception {
cassandraCqlClusterFactoryBean.setProtocolVersion(ProtocolVersion.V4);
cassandraCqlClusterFactoryBean.setPort(cassandraEnvironment.getPort());
cassandraCqlClusterFactoryBean.setNettyOptions(FastShutdownNettyOptions.INSTANCE);
cassandraCqlClusterFactoryBean.setProtocolVersion(ProtocolVersion.V2);
cassandraCqlClusterFactoryBean.afterPropertiesSet();
assertEquals(ProtocolVersion.V4, getProtocolVersionEnum(cassandraCqlClusterFactoryBean));
assertEquals(ProtocolVersion.V2, getProtocolVersionEnum(cassandraCqlClusterFactoryBean));
}
@Test
public void defaultProtocolVersionShouldBeSet() throws Exception {
cassandraCqlClusterFactoryBean.setPort(cassandraEnvironment.getPort());
cassandraCqlClusterFactoryBean.afterPropertiesSet();
assertEquals(ProtocolVersion.NEWEST_SUPPORTED, getProtocolVersionEnum(cassandraCqlClusterFactoryBean));
assertThat(getProtocolVersionEnum(cassandraCqlClusterFactoryBean), is(nullValue()));
}
private ProtocolVersion getProtocolVersionEnum(CassandraCqlClusterFactoryBean cassandraCqlClusterFactoryBean)
throws Exception {
// initialize connection factory
cassandraCqlClusterFactoryBean.getObject().init();
return cassandraCqlClusterFactoryBean.getObject().getConfiguration().getProtocolOptions().getProtocolVersion();
return (ProtocolVersion) ReflectionTestUtils.getField(
cassandraCqlClusterFactoryBean.getObject().getConfiguration().getProtocolOptions(), "initialProtocolVersion");
}
}

View File

@@ -23,23 +23,24 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.cassandra.config.java.AbstractCqlTemplateConfiguration;
import org.springframework.cassandra.core.CqlTemplate;
import org.springframework.cassandra.support.RandomKeySpaceName;
import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest;
import org.springframework.cassandra.test.integration.support.FastShutdownNettyOptions;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.Session;
/**
* Integration tests for {@link AbstractCqlTemplateConfiguration}.
*
* @author Matthews T. Adams
* @author Oliver Gierke
* @author Mark Paluch
*/
public class CqlTemplateConfigIntegrationTests extends AbstractEmbeddedCassandraIntegrationTest {
public static final String KEYSPACE_NAME = RandomKeySpaceName.create();
@Configuration
public static class Config extends AbstractCqlTemplateConfiguration {
@@ -52,6 +53,11 @@ public class CqlTemplateConfigIntegrationTests extends AbstractEmbeddedCassandra
protected int getPort() {
return cassandraEnvironment.getPort();
}
@Override
protected NettyOptions getNettyOptions() {
return FastShutdownNettyOptions.INSTANCE;
}
}
Session session;
@@ -59,6 +65,7 @@ public class CqlTemplateConfigIntegrationTests extends AbstractEmbeddedCassandra
@Before
public void setUp() {
this.context = new AnnotationConfigApplicationContext(Config.class);
this.session = context.getBean(Session.class);
}

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors.
*
* Copyright 2013-2016 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.
@@ -24,6 +24,10 @@ import org.springframework.cassandra.core.keyspace.KeyspaceOption;
import org.springframework.cassandra.test.integration.support.AbstractTestJavaConfig;
import org.springframework.context.annotation.Configuration;
/**
* @author Matthew T. Adams
* @author Mark Paluch
*/
@Configuration
public class KeyspaceCreatingJavaConfig extends AbstractTestJavaConfig {

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors.
*
* Copyright 2013-2016 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.
@@ -23,7 +23,11 @@ import com.datastax.driver.core.Host;
import com.datastax.driver.core.Host.StateListener;
/**
* {@link StateListener} that logs latency events and their payload. This class can be considered a test dummy and is
* suitable for mocking.
*
* @author David Webb
* @author Antoine Toulme
*/
public class TestHostStateListener implements StateListener {
@@ -31,32 +35,32 @@ public class TestHostStateListener implements StateListener {
@Override
public void onAdd(Host host) {
log.info("Host Added: " + host.getAddress());
log.info("Host Added: {}", host.getAddress());
}
@Override
public void onUp(Host host) {
log.info("Host Up: " + host.getAddress());
log.info("Host Up: {}", host.getAddress());
}
@Override
public void onDown(Host host) {
log.info("Host Down: " + host.getAddress());
log.info("Host Down: {}", host.getAddress());
}
@Override
public void onRemove(Host host) {
log.info("Host Removed: " + host.getAddress());
log.info("Host Removed: {}", host.getAddress());
}
@Override
public void onRegister(Cluster cluster) {
log.info("Cluster registered: " + cluster.getClusterName());
log.info("Cluster registered: {}", cluster.getClusterName());
}
@Override
public void onUnregister(Cluster cluster) {
log.info("Cluster unregistered: " + cluster.getClusterName());
log.info("Cluster unregistered: {}", cluster.getClusterName());
}
}

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Copyright 2013-2016 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.
@@ -24,8 +24,12 @@ import com.datastax.driver.core.LatencyTracker;
import com.datastax.driver.core.Statement;
/**
* {@link LatencyTracker} that logs latency events and their payload. This class can be considered a test dummy and is suitable for
* mocking.
*
* @author David Webb
* @author Oliver Gierke
* @author Antoine Toulme
*/
public class TestLatencyTracker implements LatencyTracker {
@@ -33,15 +37,16 @@ public class TestLatencyTracker implements LatencyTracker {
@Override
public void update(Host host, Statement statement, Exception exception, long newLatencyNanos) {
LOG.info("Latency Tracker: " + host.getAddress() + ", " + newLatencyNanos + " nanoseconds.");
}
@Override
public void onRegister(Cluster cluster) {
}
@Override
public void onUnregister(Cluster cluster) {
LOG.info("Latency Tracker update: {}, {} nanoseconds.", host.getAddress(), newLatencyNanos);
}
@Override
public void onRegister(Cluster cluster) {
LOG.info("Latency Tracker onRegister: {}", cluster);
}
@Override
public void onUnregister(Cluster cluster) {
LOG.info("Latency Tracker onUnregister: {}", cluster);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,6 +15,7 @@
*/
package org.springframework.cassandra.test.integration.core.cql.generator;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.springframework.cassandra.core.keyspace.IndexDescriptor;
@@ -26,24 +27,40 @@ import com.datastax.driver.core.TableMetadata;
/**
* @author David Webb
* @author Matthew T. Adams
* @author Antoine Toulme
*/
public class CqlIndexSpecificationAssertions {
/**
* Assert the existence of an index using the index name.
*
* @param expected
* @param keyspace
* @param session
*/
public static void assertIndex(IndexDescriptor expected, String keyspace, Session session) {
TableMetadata tableMetadata = session.getCluster().getMetadata().getKeyspace(keyspace.toLowerCase())
.getTable(expected.getTableName().toCql());
IndexMetadata imd = tableMetadata.getIndex(expected.getName().toCql());
assertEquals(expected.getName(), imd == null ? null : imd.getName());
IndexMetadata indexMetadata = tableMetadata.getIndex(expected.getName().toCql());
assertThat(indexMetadata, is(not(nullValue())));
assertThat(indexMetadata.getName(), is(equalTo(expected.getName().toCql())));
}
/**
* Assert the absence of an index using the index name.
*
* @param expected
* @param keyspace
* @param session
*/
public static void assertNoIndex(IndexDescriptor expected, String keyspace, Session session) {
TableMetadata tableMetadata = session.getCluster().getMetadata().getKeyspace(keyspace.toLowerCase())
.getTable(expected.getTableName().toCql());
IndexMetadata imd = tableMetadata.getIndex(expected.getName().toCql());
assertNull(imd);
IndexMetadata indexMetadata = tableMetadata.getIndex(expected.getName().toCql());
assertThat(indexMetadata, is(nullValue()));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 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.
@@ -35,8 +35,9 @@ import com.datastax.driver.core.TableOptionsMetadata;
/**
* @author Matthew T. Adams
* @author Matthew T. Adams
* @author David Webb
* @author Alex Shvid
* @author Antoine Toulme
*/
public class CqlTableSpecificationAssertions {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 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.
@@ -18,8 +18,14 @@ package org.springframework.cassandra.test.integration.support;
import org.springframework.cassandra.config.java.AbstractSessionConfiguration;
import org.springframework.context.annotation.Configuration;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.QueryOptions;
/**
* Java-based configuration for integration tests using defaults for a smooth test run.
*
* @author Matthew T. Adams
* @author Mark Paluch
*/
@Configuration
public abstract class AbstractTestJavaConfig extends AbstractSessionConfiguration {
@@ -30,4 +36,20 @@ public abstract class AbstractTestJavaConfig extends AbstractSessionConfiguratio
protected int getPort() {
return PROPERTIES.getCassandraPort();
}
@Override
protected NettyOptions getNettyOptions() {
return FastShutdownNettyOptions.INSTANCE;
}
@Override
protected QueryOptions getQueryOptions() {
// The driver blocks otherwise up to 1 sec on schema refreshes.
// see also https://datastax-oss.atlassian.net/browse/JAVA-1120
// ideally, this issue will be resolved with Cassandra Java Driver 3.0.2
QueryOptions queryOptions = new QueryOptions();
queryOptions.setRefreshSchemaIntervalMillis(0);
return queryOptions;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2016 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.support;
import java.util.concurrent.TimeUnit;
import com.datastax.driver.core.NettyOptions;
import io.netty.channel.EventLoopGroup;
/**
* {@link NettyOptions} to shutdown a {@link com.datastax.driver.core.Cluster} instance without wait time.
*
* @author Mark Paluch
* @since 1.5
*/
public class FastShutdownNettyOptions extends NettyOptions {
public final static FastShutdownNettyOptions INSTANCE = new FastShutdownNettyOptions();
@Override
public void onClusterClose(EventLoopGroup eventLoopGroup) {
eventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS);
}
}

View File

@@ -9,9 +9,12 @@
<context:property-placeholder
location="classpath:/org/springframework/cassandra/test/integration/config/xml/ppncxct.properties" />
<bean id="authProvider" class="com.datastax.driver.auth.DseAuthProvider" />
<bean id="authProvider" class="com.datastax.driver.core.PlainTextAuthProvider">
<constructor-arg index="0" value="foo" />
<constructor-arg index="1" value="bar" />
</bean>
<!--
<!--
<bean id="loadBalancingPolicy"
class="com.datastax.driver.core.policies.DCAwareRoundRobinPolicy">
<constructor-arg name="localDc" value="${lb.policy.dcAware.localDc}" />

View File

@@ -76,18 +76,6 @@
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>cassandra-all</artifactId>
<version>${cassandra.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>

View File

@@ -31,6 +31,7 @@ import org.springframework.data.convert.ReadingConverter;
import org.springframework.util.Assert;
import org.springframework.util.NumberUtils;
import com.datastax.driver.core.LocalDate;
import com.datastax.driver.core.Row;
/**
@@ -55,6 +56,7 @@ abstract class CassandraConverters {
List<Object> converters = new ArrayList<Object>();
converters.add(RowToCassandraLocalDateConverter.INSTANCE);
converters.add(RowToNumberConverterFactory.INSTANCE);
converters.add(RowToBooleanConverter.INSTANCE);
converters.add(RowToDateConverter.INSTANCE);
@@ -184,4 +186,19 @@ abstract class CassandraConverters {
return row.getUUID(0);
}
}
/**
* Simple singleton to convert {@link Row}s to their Cassandra {@link LocalDate} representation.
*
* @author Mark Paluch
*/
@ReadingConverter
public enum RowToCassandraLocalDateConverter implements Converter<Row, LocalDate> {
INSTANCE;
@Override
public LocalDate convert(Row row) {
return row.getDate(0);
}
}
}

View File

@@ -1,3 +1,18 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.convert;
import java.util.List;
@@ -7,21 +22,27 @@ import org.springframework.cassandra.core.cql.CqlIdentifier;
import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.ColumnDefinitions;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.DataType.Name;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.TypeCodec;
/**
* Helpful class to read a column's value from a row, with possible type conversion.
*
*
* @author Matthew T. Adams
* @author Antoine Toulme
* @author Mark Paluch
*/
public class ColumnReader {
protected Row row;
protected ColumnDefinitions columns;
private final CodecRegistry codecRegistry;
public ColumnReader(Row row) {
this.row = row;
this.columns = row.getColumnDefinitions();
this.codecRegistry = CodecRegistry.DEFAULT_INSTANCE;
}
/**
@@ -39,70 +60,66 @@ public class ColumnReader {
return get(indexOf);
}
public Object get(int i) {
/**
* Read data from a Column using the {@code index}.
*
* @param index
* @return
*/
public Object get(int index) {
if (row.isNull(i)) {
if (row.isNull(index)) {
return null;
}
DataType type = columns.getType(i);
DataType type = columns.getType(index);
if (type.isCollection()) {
return getCollection(index, type);
}
List<DataType> collectionTypes = type.getTypeArguments();
if (collectionTypes.size() == 2) {
return row.getMap(i, CodecRegistry.DEFAULT_INSTANCE.codecFor(collectionTypes.get(0)).getJavaType().getRawType(), CodecRegistry.DEFAULT_INSTANCE.codecFor(collectionTypes.get(1)).getJavaType().getRawType());
if (Name.TUPLE.equals(type.getName())) {
return row.getTupleValue(index);
}
if (Name.UDT.equals(type.getName())) {
return row.getUDTValue(index);
}
return row.getObject(index);
}
public Object getCollection(int i, DataType type) {
List<DataType> collectionTypes = type.getTypeArguments();
// List/Set
if (collectionTypes.size() == 1) {
DataType valueType = collectionTypes.get(0);
TypeCodec<Object> typeCodec = codecRegistry.codecFor(valueType);
if (type.equals(DataType.list(valueType))) {
return row.getList(i, typeCodec.getJavaType().getRawType());
}
if (type.equals(DataType.list(collectionTypes.get(0)))) {
return row.getList(i, CodecRegistry.DEFAULT_INSTANCE.codecFor(collectionTypes.get(0)).getJavaType().getRawType());
if (type.equals(DataType.set(valueType))) {
return row.getSet(i, typeCodec.getJavaType().getRawType());
}
if (type.equals(DataType.set(collectionTypes.get(0)))) {
return row.getSet(i, CodecRegistry.DEFAULT_INSTANCE.codecFor(collectionTypes.get(0)).getJavaType().getRawType());
}
throw new IllegalStateException("Unknown Collection type encountered. Valid collections are Set, List and Map.");
}
if (type.equals(DataType.text()) || type.equals(DataType.ascii()) || type.equals(DataType.varchar())) {
return row.getString(i);
}
if (type.equals(DataType.cint())) {
return new Integer(row.getInt(i));
}
if (type.equals(DataType.varint())) {
return row.getVarint(i);
}
if (type.equals(DataType.cdouble())) {
return new Double(row.getDouble(i));
}
if (type.equals(DataType.bigint()) || type.equals(DataType.counter())) {
return new Long(row.getLong(i));
}
if (type.equals(DataType.cfloat())) {
return new Float(row.getFloat(i));
}
if (type.equals(DataType.decimal())) {
return row.getDecimal(i);
}
if (type.equals(DataType.cboolean())) {
return new Boolean(row.getBool(i));
}
if (type.equals(DataType.timestamp())) {
return row.getDate(i);
}
if (type.equals(DataType.blob())) {
return row.getBytes(i);
}
if (type.equals(DataType.inet())) {
return row.getInet(i);
}
if (type.equals(DataType.uuid()) || type.equals(DataType.timeuuid())) {
return row.getUUID(i);
// Map
if (collectionTypes.size() == 2) {
DataType keyType = collectionTypes.get(0);
TypeCodec<Object> keyTypeCodec = codecRegistry.codecFor(keyType);
DataType valueType = collectionTypes.get(1);
TypeCodec<Object> valueTypeCodec = codecRegistry.codecFor(valueType);
return row.getMap(i, keyTypeCodec.getJavaType().getRawType(), valueTypeCodec.getJavaType().getRawType());
}
return row.getBytesUnsafe(i);
throw new IllegalStateException("Unknown Collection type encountered. Valid collections are Set, List and Map.");
}
public Row getRow() {
@@ -111,7 +128,7 @@ public class ColumnReader {
/**
* Returns the row's column value as an instance of the given type.
*
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
public <T> T get(CqlIdentifier name, Class<T> requestedType) {
@@ -120,7 +137,7 @@ public class ColumnReader {
/**
* Returns the row's column value as an instance of the given type.
*
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
public <T> T get(String name, Class<T> requestedType) {
@@ -129,7 +146,7 @@ public class ColumnReader {
/**
* Returns the row's column value as an instance of the given type.
*
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
@SuppressWarnings("unchecked")
@@ -145,6 +162,7 @@ public class ColumnReader {
}
private int getColumnIndex(String name) {
int indexOf = columns.getIndexOf(name);
if (indexOf == -1) {
throw new IllegalArgumentException("Column does not exist in Cassandra table: " + name);

View File

@@ -61,6 +61,7 @@ import com.datastax.driver.core.querybuilder.Update;
* @author Matthew T. Adams
* @author Oliver Gierke
* @author Mark Paluch
* @author Antoine Toulme
* @see org.springframework.beans.factory.InitializingBean
* @see org.springframework.context.ApplicationContextAware
* @see org.springframework.beans.factory.BeanClassLoaderAware

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors
*
* Copyright 2013-2016 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.
@@ -28,8 +28,9 @@ import com.datastax.driver.core.Row;
/**
* {@link PropertyAccessor} to read values from a {@link Row}.
*
*
* @author Alex Shvid
* @author Antoine Toulme
*/
enum RowReaderPropertyAccessor implements PropertyAccessor {

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors
*
* Copyright 2013-2016 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.
@@ -47,23 +47,27 @@ import com.datastax.driver.core.DataType;
/**
* Cassandra specific {@link org.springframework.data.mapping.model.AnnotationBasedPersistentProperty} implementation.
*
*
* @author Alex Shvid
* @author Matthew T. Adams
* @author Antoine Toulme
*/
public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentProperty<CassandraPersistentProperty>
implements CassandraPersistentProperty, ApplicationContextAware {
protected ApplicationContext context;
protected StandardEvaluationContext spelContext;
/**
* An unmodifiable list of this property's column names.
*/
protected List<CqlIdentifier> columnNames;
/**
* An unmodifiable list of this property's explicitly set column names.
*/
protected List<CqlIdentifier> explicitColumnNames;
/**
* Whether this property has been explicitly instructed to force quote column names.
*/
@@ -71,7 +75,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
/**
* Creates a new {@link BasicCassandraPersistentProperty}.
*
*
* @param field
* @param propertyDescriptor
* @param owner
@@ -140,17 +144,17 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
@Override
public Ordering getPrimaryKeyOrdering() {
PrimaryKeyColumn anno = findAnnotation(PrimaryKeyColumn.class);
PrimaryKeyColumn primaryKeyColumn = findAnnotation(PrimaryKeyColumn.class);
return anno == null ? null : anno.ordering();
return primaryKeyColumn == null ? null : primaryKeyColumn.ordering();
}
@Override
public DataType getDataType() {
CassandraType annotation = findAnnotation(CassandraType.class);
if (annotation != null) {
return getDataTypeFor(annotation);
CassandraType cassandraType = findAnnotation(CassandraType.class);
if (cassandraType != null) {
return getDataTypeFor(cassandraType);
}
if (isMap()) {

View File

@@ -36,6 +36,7 @@ import com.datastax.driver.core.DataType.Name;
* @author Alex Shvid
* @author Matthew T. Adams
* @author Mark Paluch
* @author Antoine Toulme
*/
public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
@@ -46,6 +47,8 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
static {
CodecRegistry codecRegistry = CodecRegistry.DEFAULT_INSTANCE;
Map<Class<?>, Class<?>> primitiveWrappers = new HashMap<Class<?>, Class<?>>(8);
primitiveWrappers.put(Boolean.class, boolean.class);
primitiveWrappers.put(Byte.class, byte.class);
@@ -56,10 +59,10 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
primitiveWrappers.put(Long.class, long.class);
primitiveWrappers.put(Short.class, short.class);
Set<Class<?>> simpleTypes = getCassandraPrimitiveTypes();
Set<Class<?>> simpleTypes = getCassandraPrimitiveTypes(codecRegistry);
simpleTypes.add(Number.class);
classToDataType = Collections.unmodifiableMap(classToDataType(primitiveWrappers));
classToDataType = Collections.unmodifiableMap(classToDataType(primitiveWrappers, codecRegistry));
nameToDataType = Collections.unmodifiableMap(nameToDataType());
CASSANDRA_SIMPLE_TYPES = Collections.unmodifiableSet(simpleTypes);
}
@@ -82,14 +85,14 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
/**
* @return the map between {@link Class} and {@link DataType}.
* @param primitiveWrappers
* @param primitiveWrappers map of primitive to wrapper type
* @param codecRegistry the Cassandra codec registry
*/
private static Map<Class<?>, DataType> classToDataType(Map<Class<?>, Class<?>> primitiveWrappers) {
private static Map<Class<?>, DataType> classToDataType(Map<Class<?>, Class<?>> primitiveWrappers,
CodecRegistry codecRegistry) {
Map<Class<?>, DataType> classToDataType = new HashMap<Class<?>, DataType>(16);
CodecRegistry codecRegistry = CodecRegistry.DEFAULT_INSTANCE;
for (DataType dataType : DataType.allPrimitiveTypes()) {
Class<?> javaClass = codecRegistry.codecFor(dataType).getJavaType().getRawType();
@@ -104,20 +107,27 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
// override String to text datatype as String is used multiple times
classToDataType.put(String.class, DataType.text());
// map Long to bigint as counter columns (last type aver multiple overrides)
// are a special use case so map it to a more common type by
// default
classToDataType.put(Long.class, DataType.bigint());
classToDataType.put(long.class, DataType.bigint());
return classToDataType;
}
/**
* Returns a {@link Set} containing all Cassandra primitive types.
*
* @return
* @param codecRegistry the Cassandra codec registry
* @return the set of Cassandra primitive types.
*/
private static Set<Class<?>> getCassandraPrimitiveTypes() {
private static Set<Class<?>> getCassandraPrimitiveTypes(CodecRegistry codecRegistry) {
Set<Class<?>> simpleTypes = new HashSet<Class<?>>();
for (DataType dataType : DataType.allPrimitiveTypes()) {
Class<?> javaClass = CodecRegistry.DEFAULT_INSTANCE.codecFor(dataType).getJavaType().getRawType();
Class<?> javaClass = codecRegistry.codecFor(dataType).getJavaType().getRawType();
simpleTypes.add(javaClass);
}
return simpleTypes;

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.config.xml;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.core.Is.is;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Configuration;
import com.datastax.driver.core.HostDistance;
import com.datastax.driver.core.PoolingOptions;
import com.datastax.driver.core.ProtocolOptions.Compression;
import com.datastax.driver.core.SocketOptions;
/**
* Integration tests for XML-based Cassandra configuration using the Cassandra namespace parsed with
* {@link CassandraNamespaceHandler}.
*
* @author Mark Paluch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class CassandraNamespaceIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
@Autowired ApplicationContext applicationContext;
/**
* @see DATACASS-271
*/
@Test
public void clusterShouldHaveCompressionSet() {
Cluster cluster = applicationContext.getBean(Cluster.class);
Configuration configuration = cluster.getConfiguration();
assertThat(configuration.getProtocolOptions().getCompression(), is(Compression.SNAPPY));
}
/**
* @see DATACASS-271
*/
@Test
public void clusterShouldHavePoolingOptionsConfigured() {
Cluster cluster = applicationContext.getBean(Cluster.class);
PoolingOptions poolingOptions = cluster.getConfiguration().getPoolingOptions();
assertThat(poolingOptions.getMaxRequestsPerConnection(HostDistance.LOCAL), is(101));
assertThat(poolingOptions.getMaxRequestsPerConnection(HostDistance.REMOTE), is(100));
assertThat(poolingOptions.getCoreConnectionsPerHost(HostDistance.LOCAL), is(3));
assertThat(poolingOptions.getCoreConnectionsPerHost(HostDistance.REMOTE), is(1));
assertThat(poolingOptions.getMaxConnectionsPerHost(HostDistance.LOCAL), is(9));
assertThat(poolingOptions.getMaxConnectionsPerHost(HostDistance.REMOTE), is(2));
}
/**
* @see DATACASS-271
*/
@Test
public void clusterShouldHaveSocketOptionsConfigured() {
Cluster cluster = applicationContext.getBean(Cluster.class);
SocketOptions socketOptions = cluster.getConfiguration().getSocketOptions();
assertThat(socketOptions.getConnectTimeoutMillis(), is(5000));
assertThat(socketOptions.getKeepAlive(), is(true));
assertThat(socketOptions.getReuseAddress(), is(true));
assertThat(socketOptions.getTcpNoDelay(), is(true));
assertThat(socketOptions.getSoLinger(), is(equalTo(60)));
assertThat(socketOptions.getReceiveBufferSize(), is(equalTo(65536)));
assertThat(socketOptions.getSendBufferSize(), is(equalTo(65536)));
}
}

View File

@@ -54,6 +54,7 @@ import org.springframework.test.util.ReflectionTestUtils;
import com.datastax.driver.core.ColumnDefinitions;
import com.datastax.driver.core.DataType.Name;
import com.datastax.driver.core.LocalDate;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.querybuilder.Assignment;
import com.datastax.driver.core.querybuilder.BuiltStatement;
@@ -384,9 +385,10 @@ public class MappingCassandraConverterUnitTests {
/**
* @see DATACASS-280
* @see DATACASS-271
*/
@Test
public void shouldReadDateCorrectly() throws UnknownHostException {
public void shouldReadTimestampCorrectly() throws UnknownHostException {
Date date = new Date(1);
when(rowMock.getTimestamp(0)).thenReturn(date);
@@ -396,6 +398,20 @@ public class MappingCassandraConverterUnitTests {
assertThat(result, is(equalTo(date)));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReadDateCorrectly() throws UnknownHostException {
LocalDate date = LocalDate.fromDaysSinceEpoch(1234);
when(rowMock.getDate(0)).thenReturn(date);
LocalDate result = mappingCassandraConverter.readRow(LocalDate.class, rowMock);
assertThat(result, is(equalTo(date)));
}
/**
* @see DATACASS-280
*/
@@ -497,8 +513,7 @@ public class MappingCassandraConverterUnitTests {
@PrimaryKeyColumn(ordinal = 1, type = PrimaryKeyType.PARTITIONED) private Condition condition;
public EnumCompositePrimaryKey() {
}
public EnumCompositePrimaryKey() {}
public EnumCompositePrimaryKey(Condition condition) {
this.condition = condition;
@@ -532,8 +547,7 @@ public class MappingCassandraConverterUnitTests {
@PrimaryKey private EnumCompositePrimaryKey key;
public CompositeKeyThing() {
}
public CompositeKeyThing() {}
public CompositeKeyThing(EnumCompositePrimaryKey key) {
this.key = key;

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.domain;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.springframework.data.cassandra.mapping.CassandraType;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.cassandra.test.integration.mapping.types.CassandraTypeMappingIntegrationTest.Condition;
import com.datastax.driver.core.DataType.Name;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* @author Mark Paluch
*/
@Table
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class AllPossibleTypes {
@PrimaryKey @NonNull private String id;
private InetAddress inet;
@CassandraType(type = Name.UUID) private UUID uuid;
@CassandraType(type = Name.INT) private Number justNumber;
private Byte boxedByte;
private byte primitiveByte;
private Short boxedShort;
private short primitiveShort;
private Long boxedLong;
private long primitiveLong;
private Integer boxedInteger;
private int primitiveInteger;
private Float boxedFloat;
private float primitiveFloat;
private Double boxedDouble;
private double primitiveDouble;
private Boolean boxedBoolean;
private boolean primitiveBoolean;
private com.datastax.driver.core.LocalDate date;
private Date timestamp;
private BigDecimal bigDecimal;
private BigInteger bigInteger;
private ByteBuffer blob;
private Set<String> setOfString;
private List<String> listOfString;
private Map<String, String> mapOfString;
private Condition anEnum;
}

View File

@@ -0,0 +1,380 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.repository.isolated;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.domain.AllPossibleTypes;
import org.springframework.data.cassandra.repository.Query;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
import org.springframework.data.repository.CrudRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.datastax.driver.core.LocalDate;
/**
* Integration tests for various return types on a Cassandra repository.
*
* @author Mark Paluch
* @see DATACASS-271
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@SuppressWarnings("Since15")
public class RepositoryReturnTypesIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
@Configuration
@EnableCassandraRepositories(basePackageClasses = RepositoryReturnTypesIntegrationTests.class,
considerNestedRepositories = true)
public static class Config extends IntegrationTestConfig {
@Override
public String[] getEntityBasePackages() {
return new String[] { AllPossibleTypes.class.getPackage().getName() };
}
@Override
public SchemaAction getSchemaAction() {
return SchemaAction.RECREATE_DROP_UNUSED;
}
}
@Autowired AllPossibleTypesRepository allPossibleTypesRepository;
@Before
public void setUp() throws Exception {
allPossibleTypesRepository.deleteAll();
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnOptional() {
AllPossibleTypes entity = new AllPossibleTypes("123");
allPossibleTypesRepository.save(entity);
Optional<AllPossibleTypes> result = allPossibleTypesRepository.findOptionalById(entity.getId());
assertThat(result.isPresent(), is(true));
assertThat(result.get(), is(instanceOf(AllPossibleTypes.class)));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnList() {
AllPossibleTypes entity = new AllPossibleTypes("123");
allPossibleTypesRepository.save(entity);
List<AllPossibleTypes> result = allPossibleTypesRepository.findManyById(entity.getId());
assertThat(result.isEmpty(), is(false));
assertThat(result, hasItem(entity));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnInetAddress() throws UnknownHostException {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setInet(InetAddress.getByName("localhost"));
allPossibleTypesRepository.save(entity);
InetAddress result = allPossibleTypesRepository.findInetAddressById(entity.getId());
assertThat(result, is(equalTo(entity.getInet())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnOptionalInetAddress() throws UnknownHostException {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setInet(InetAddress.getByName("localhost"));
allPossibleTypesRepository.save(entity);
Optional<InetAddress> result = allPossibleTypesRepository.findOptionalInetById(entity.getId());
assertThat(result.isPresent(), is(true));
assertThat(result.get(), is(equalTo(entity.getInet())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBoxedByte() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBoxedByte(Byte.valueOf("1"));
allPossibleTypesRepository.save(entity);
Byte result = allPossibleTypesRepository.findBoxedByteById(entity.getId());
assertThat(result, is(equalTo(entity.getBoxedByte())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnPrimitiveByte() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setPrimitiveByte(Byte.MAX_VALUE);
allPossibleTypesRepository.save(entity);
byte result = allPossibleTypesRepository.findPrimitiveByteById(entity.getId());
assertThat(result, is(equalTo(entity.getPrimitiveByte())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBoxedShort() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBoxedShort(Short.MAX_VALUE);
allPossibleTypesRepository.save(entity);
Short result = allPossibleTypesRepository.findBoxedShortById(entity.getId());
assertThat(result, is(equalTo(entity.getBoxedShort())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBoxedLong() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBoxedLong(Long.MAX_VALUE);
allPossibleTypesRepository.save(entity);
Long result = allPossibleTypesRepository.findBoxedLongById(entity.getId());
assertThat(result, is(equalTo(entity.getBoxedLong())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBoxedInteger() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBoxedInteger(Integer.MAX_VALUE);
allPossibleTypesRepository.save(entity);
Integer result = allPossibleTypesRepository.findBoxedIntegerById(entity.getId());
assertThat(result, is(equalTo(entity.getBoxedInteger())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBoxedDouble() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBoxedDouble(Double.MAX_VALUE);
allPossibleTypesRepository.save(entity);
Double result = allPossibleTypesRepository.findBoxedDoubleById(entity.getId());
assertThat(result, is(equalTo(entity.getBoxedDouble())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBoxedDoubleFromInteger() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBoxedInteger(Integer.MAX_VALUE);
allPossibleTypesRepository.save(entity);
Double result = allPossibleTypesRepository.findDoubleFromIntegerById(entity.getId());
assertThat(result, is(closeTo(entity.getBoxedInteger(), 0.01d)));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBoxedBoolean() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBoxedBoolean(true);
allPossibleTypesRepository.save(entity);
Boolean result = allPossibleTypesRepository.findBoxedBooleanById(entity.getId());
assertThat(result, is(equalTo(entity.getBoxedBoolean())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnDate() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setDate(LocalDate.fromDaysSinceEpoch(1));
allPossibleTypesRepository.save(entity);
LocalDate result = allPossibleTypesRepository.findLocalDateById(entity.getId());
assertThat(result, is(equalTo(entity.getDate())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnTimestamp() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setTimestamp(new Date(1));
allPossibleTypesRepository.save(entity);
Date result = allPossibleTypesRepository.findTimestampById(entity.getId());
assertThat(result, is(equalTo(entity.getTimestamp())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBigDecimal() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBigDecimal(BigDecimal.ONE);
allPossibleTypesRepository.save(entity);
BigDecimal result = allPossibleTypesRepository.findBigDecimalById(entity.getId());
assertThat(result, is(equalTo(entity.getBigDecimal())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnBigInteger() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setBigInteger(BigInteger.ONE);
allPossibleTypesRepository.save(entity);
BigInteger result = allPossibleTypesRepository.findBigIntegerById(entity.getId());
assertThat(result, is(equalTo(entity.getBigInteger())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReturnEntityAsMap() {
AllPossibleTypes entity = new AllPossibleTypes("123");
entity.setPrimitiveInteger(123);
entity.setBigInteger(BigInteger.ONE);
allPossibleTypesRepository.save(entity);
Map<String, Object> result = allPossibleTypesRepository.findEntityAsMapById(entity.getId());
assertThat(result.size(), is(27));
assertThat(result.get("primitiveinteger"), is(equalTo((Object) Integer.valueOf(123))));
assertThat(result.get("biginteger"), is(equalTo((Object) BigInteger.ONE)));
}
public interface AllPossibleTypesRepository extends CrudRepository<AllPossibleTypes, String> {
// blob/byte-buffer result do not work yet.
// returning a map field does not work yet.
@Query("select * from allpossibletypes where id = ?0")
Optional<AllPossibleTypes> findOptionalById(String id);
@Query("select * from allpossibletypes where id = ?0")
List<AllPossibleTypes> findManyById(String id);
@Query("select inet from allpossibletypes where id = ?0")
InetAddress findInetAddressById(String id);
@Query("select inet from allpossibletypes where id = ?0")
Optional<InetAddress> findOptionalInetById(String id);
@Query("select boxedByte from allpossibletypes where id = ?0")
Byte findBoxedByteById(String id);
@Query("select primitiveByte from allpossibletypes where id = ?0")
byte findPrimitiveByteById(String id);
@Query("select boxedShort from allpossibletypes where id = ?0")
Short findBoxedShortById(String id);
@Query("select boxedLong from allpossibletypes where id = ?0")
Long findBoxedLongById(String id);
@Query("select boxedInteger from allpossibletypes where id = ?0")
Integer findBoxedIntegerById(String id);
@Query("select boxedInteger from allpossibletypes where id = ?0")
Double findDoubleFromIntegerById(String id);
@Query("select boxedDouble from allpossibletypes where id = ?0")
Double findBoxedDoubleById(String id);
@Query("select boxedBoolean from allpossibletypes where id = ?0")
Boolean findBoxedBooleanById(String id);
@Query("select date from allpossibletypes where id = ?0")
LocalDate findLocalDateById(String id);
@Query("select timestamp from allpossibletypes where id = ?0")
Date findTimestampById(String id);
@Query("select bigDecimal from allpossibletypes where id = ?0")
BigDecimal findBigDecimalById(String id);
@Query("select bigInteger from allpossibletypes where id = ?0")
BigInteger findBigIntegerById(String id);
@Query("select * from allpossibletypes where id = ?0")
Map<String, Object> findEntityAsMapById(String id);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors
* Copyright 2013-2016 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.
@@ -32,6 +32,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* Base class for Java config tests for {@link UserRepository}.
*
* @author Matthew T. Adams
* @author Mark Paluch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@@ -41,11 +42,6 @@ public class CommentRepositoryJavaConfigIntegrationTests extends AbstractSpringD
@EnableCassandraRepositories(basePackageClasses = CommentRepository.class)
public static class Config extends IntegrationTestConfig {
// @Override
// protected String getKeyspaceName() {
// return CommentRepositoryJavaConfigIntegrationTests.class.getSimpleName();
// }
@Override
public String[] getEntityBasePackages() {
return new String[] { Comment.class.getPackage().getName() };

View File

@@ -1,41 +0,0 @@
/*
* Copyright 2013-2016 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.config;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
/**
* @author Mark Paluch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class CassandraNamespaceIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
@Autowired ApplicationContext ctx;
@Test
public void test() {
Assert.notNull(ctx);
}
}

View File

@@ -10,7 +10,7 @@
* 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
* see the License for the specific language governing permissions and
* limitations under the License.
*/
@@ -28,31 +28,27 @@ import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.mapping.CassandraType;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.cassandra.domain.AllPossibleTypes;
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.datastax.driver.core.DataType.Name;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.LocalDate;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.exceptions.InvalidQueryException;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
/**
* Integration tests for type mapping using {@link CassandraOperations}.
@@ -69,7 +65,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
@Override
public String[] getEntityBasePackages() {
return new String[] { AllPossibleTypes.class.getPackage().getName() };
return new String[] { AllPossibleTypes.class.getPackage().getName(), CounterEntity.class.getPackage().getName() };
}
}
@@ -81,7 +77,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteInetAddress() throws Exception {
@@ -96,7 +92,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteUUID() {
@@ -111,10 +107,10 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBoxedLongShort() {
public void shouldReadAndWriteBoxedShort() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setBoxedShort(Short.MAX_VALUE);
@@ -126,7 +122,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWritePrimitiveShort() {
@@ -141,7 +137,37 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-271
*/
@Test
public void shouldReadAndWriteBoxedByte() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setBoxedByte(Byte.MAX_VALUE);
cassandraOperations.insert(entity);
AllPossibleTypes loaded = cassandraOperations.selectOneById(AllPossibleTypes.class, entity.getId());
assertThat(loaded.getBoxedByte(), is(equalTo(entity.getBoxedByte())));
}
/**
* @see DATACASS-271
*/
@Test
public void shouldReadAndWritePrimitiveByte() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setPrimitiveByte(Byte.MAX_VALUE);
cassandraOperations.insert(entity);
AllPossibleTypes loaded = cassandraOperations.selectOneById(AllPossibleTypes.class, entity.getId());
assertThat(loaded.getPrimitiveByte(), is(equalTo(entity.getPrimitiveByte())));
}
/**
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBoxedLong() {
@@ -156,7 +182,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWritePrimitiveLong() {
@@ -171,7 +197,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBoxedInteger() {
@@ -186,7 +212,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWritePrimitiveInteger() {
@@ -201,7 +227,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBoxedFloat() {
@@ -216,7 +242,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWritePrimitiveFloat() {
@@ -231,7 +257,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBoxedDouble() {
@@ -246,7 +272,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWritePrimitiveDouble() {
@@ -261,7 +287,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBoxedBoolean() {
@@ -276,7 +302,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWritePrimitiveBoolean() {
@@ -291,10 +317,11 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
* @see DATACASS-271
*/
@Test
public void shouldReadAndWriteDate() {
public void shouldReadAndWriteTimestamp() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setTimestamp(new Date(1));
@@ -306,7 +333,22 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-271
*/
@Test
public void shouldReadAndWriteDate() {
AllPossibleTypes entity = new AllPossibleTypes("1");
entity.setDate(LocalDate.fromDaysSinceEpoch(1));
cassandraOperations.insert(entity);
AllPossibleTypes loaded = cassandraOperations.selectOneById(AllPossibleTypes.class, entity.getId());
assertThat(loaded.getDate(), is(equalTo(entity.getDate())));
}
/**
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBigInteger() {
@@ -321,7 +363,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBigDecimal() {
@@ -336,7 +378,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteBlob() {
@@ -354,7 +396,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteSetOfString() {
@@ -369,7 +411,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteEmptySetOfString() {
@@ -384,7 +426,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteListOfString() {
@@ -399,7 +441,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteEmptyListOfString() {
@@ -414,7 +456,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteMapOfString() {
@@ -429,7 +471,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteEmptyMapOfString() {
@@ -444,7 +486,7 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
}
/**
* see DATACASS-280.
* @see DATACASS-280
*/
@Test
public void shouldReadAndWriteEnum() {
@@ -458,52 +500,59 @@ public class CassandraTypeMappingIntegrationTest extends AbstractSpringDataEmbed
assertThat(loaded.getAnEnum(), is(equalTo(entity.getAnEnum())));
}
@Table
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public static class AllPossibleTypes {
/**
* @see DATACASS-271
*/
@Test
public void shouldReadAndWriteTime() {
@PrimaryKey @NonNull private String id;
// writing of time is not supported with Insert/Update statements as they mix up types.
// The only way to insert a time right now seems a PreparedStatement
String id = "1";
long time = 21312214L;
private InetAddress inet;
PreparedStatement prepare = cassandraOperations.getSession()
.prepare("INSERT INTO timeentity (id, time) values(?,?)");
BoundStatement boundStatement = prepare.bind(id, time);
cassandraOperations.execute(boundStatement);
@CassandraType(type = Name.UUID) private UUID uuid;
@CassandraType(type = Name.INT) private Number justNumber;
@CassandraType(type = Name.INT) private Short boxedShort;
@CassandraType(type = Name.INT) private short primitiveShort;
@CassandraType(type = Name.BIGINT) private Long boxedLong;
@CassandraType(type = Name.BIGINT) private long primitiveLong;
private Integer boxedInteger;
private int primitiveInteger;
private Float boxedFloat;
private float primitiveFloat;
private Double boxedDouble;
private double primitiveDouble;
private Boolean boxedBoolean;
private boolean primitiveBoolean;
private Date timestamp;
private BigDecimal bigDecimal;
private BigInteger bigInteger;
private ByteBuffer blob;
private Set<String> setOfString;
private List<String> listOfString;
private Map<String, String> mapOfString;
private Condition anEnum;
TimeEntity loaded = cassandraOperations.selectOneById(TimeEntity.class, id);
assertThat(loaded.getTime(), is(equalTo(time)));
}
public static enum Condition {
MINT, USED;
/**
* @see DATACASS-271
*/
@Test(expected = InvalidQueryException.class)
public void insertFailsOnWriteTime() {
// writing of time is not supported with Insert/Update statements as they mix up types.
// The only way to insert a time right now seems a PreparedStatement
String id = "1";
long time = 21312214L;
Insert insert = QueryBuilder.insertInto("timeentity").value("id", id).value("time", time);
cassandraOperations.getSession().execute(insert);
}
/**
* @see DATACASS-285
*/
@Test
@Ignore("Counter columns are not supported with Spring Data Cassandra as the value of counter columns can only be incremented/decremented, not set")
public void shouldReadAndWriteCounter() {
CounterEntity entity = new CounterEntity("1");
entity.setCount(1);
cassandraOperations.update(entity);
CounterEntity loaded = cassandraOperations.selectOneById(CounterEntity.class, entity.getId());
assertThat(loaded.getCount(), is(equalTo(entity.getCount())));
}
public enum Condition {
MINT;
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.mapping.types;
import org.springframework.data.cassandra.mapping.CassandraType;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
import com.datastax.driver.core.DataType.Name;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* @author Mark Paluch
*/
@Table
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class CounterEntity {
@PrimaryKey @NonNull private String id;
@CassandraType(type = Name.COUNTER) private long count;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.mapping.types;
import org.springframework.data.cassandra.mapping.CassandraType;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
import com.datastax.driver.core.DataType.Name;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* @author Mark Paluch
*/
@Table
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class TimeEntity {
@PrimaryKey @NonNull private String id;
@CassandraType(type = Name.TIME) private long time;
}

View File

@@ -35,11 +35,6 @@ public class UserRepositoryJavaConfigIntegrationTests extends UserRepositoryInte
@EnableCassandraRepositories(basePackageClasses = UserRepository.class)
public static class Config extends IntegrationTestConfig {
// @Override
// protected String getKeyspaceName() {
// return UserRepositoryJavaConfigIntegrationTests.class.getSimpleName();
// }
@Override
public String[] getEntityBasePackages() {
return new String[] { User.class.getPackage().getName() };

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors
* Copyright 2013-2016 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.
@@ -24,15 +24,20 @@ import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification;
import org.springframework.cassandra.support.RandomKeySpaceName;
import org.springframework.cassandra.test.integration.support.CassandraConnectionProperties;
import org.springframework.cassandra.test.integration.support.FastShutdownNettyOptions;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.QueryOptions;
/**
* Setup any spring configuration for unit tests
*
* @author David Webb
* @author Matthew T. Adams
* @author Mark Paluch
*/
@Configuration
public class IntegrationTestConfig extends AbstractCassandraConfiguration {
@@ -57,6 +62,19 @@ public class IntegrationTestConfig extends AbstractCassandraConfiguration {
return keyspaceName;
}
@Override
protected NettyOptions getNettyOptions() {
return FastShutdownNettyOptions.INSTANCE;
}
@Override
protected QueryOptions getQueryOptions() {
QueryOptions queryOptions = new QueryOptions();
queryOptions.setRefreshSchemaIntervalMillis(0);
return queryOptions;
}
@Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
return Arrays.asList(createKeyspace().name(getKeyspaceName()).withSimpleReplication());

View File

@@ -1,4 +1,4 @@
# Cassandra storage config YAML
# Cassandra storage config YAML
# See http://wiki.apache.org/cassandra/StorageConfiguration for
# full explanations of configuration directives
@@ -18,7 +18,7 @@ cluster_name: 'Test Cluster'
#
# Specifying initial_token will override this setting.
#
# If you already have a cluster with 1 token per node, and wish to migrate to
# If you already have a cluster with 1 token per node, and wish to migrate to
# multiple tokens per node, see http://wiki.apache.org/cassandra/Operations
# num_tokens: 256
@@ -84,7 +84,7 @@ authorizer: org.apache.cassandra.auth.AllowAllAuthorizer
# own as long as it is on the classpath. Out of the box, Cassandra
# provides org.apache.cassandra.dht.{Murmur3Partitioner, RandomPartitioner
# ByteOrderedPartitioner, OrderPreservingPartitioner (deprecated)}.
#
#
# - RandomPartitioner distributes rows across the cluster evenly by md5.
# This is the default prior to 1.2 and is retained for compatibility.
# - Murmur3Partitioner is similar to RandomPartioner but uses Murmur3_128
@@ -108,6 +108,9 @@ partitioner: org.apache.cassandra.dht.Murmur3Partitioner
data_file_directories:
- target/embeddedCassandra/data
hints_directory:
- target/embeddedCassandra/hints
# commit log
commitlog_directory: target/embeddedCassandra/commitlog
@@ -173,7 +176,7 @@ row_cache_save_period: 0
# saved caches
saved_caches_directory: target/embeddedCassandra/saved_caches
# commitlog_sync may be either "periodic" or "batch."
# commitlog_sync may be either "periodic" or "batch."
# When in batch mode, Cassandra won't ack writes until the commit log
# has been fsynced to disk. It will wait up to
# commitlog_sync_batch_window_in_ms milliseconds for other writes, before
@@ -191,7 +194,7 @@ commitlog_sync_period_in_ms: 5000
# The size of the individual commitlog file segments. A commitlog
# segment may be archived, deleted, or recycled once all the data
# in it (potentially from each columnfamily in the system) has been
# flushed to sstables.
# flushed to sstables.
#
# The default size is 32, which is almost always fine, but if you are
# archiving commitlog segments (see commitlog_archiving.properties),
@@ -202,7 +205,7 @@ commitlog_segment_size_in_mb: 8
# any class that implements the SeedProvider interface and has a
# constructor that takes a Map<String, String> of parameters will do.
seed_provider:
# Addresses of hosts that are deemed contact points.
# Addresses of hosts that are deemed contact points.
# Cassandra nodes use this list of hosts to find each other and learn
# the topology of the ring. You must change this if you are running
# multiple nodes!
@@ -264,7 +267,7 @@ 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
# communicate!
#
#
# Leaving it blank leaves it up to InetAddress.getLocalHost(). This
# will always do the Right Thing _if_ the node is properly configured
# (hostname, name resolution, etc), and the Right Thing is to use the
@@ -299,7 +302,7 @@ start_rpc: false
# The address to bind the Thrift RPC service to -- clients connect
# here. Unlike ListenAddress above, you _can_ specify 0.0.0.0 here if
# you want Thrift to listen on all interfaces.
#
#
# Leaving this blank has the same effect it does for ListenAddress,
# (i.e. it will be based on the configured hostname of the node).
rpc_address: localhost
@@ -377,7 +380,7 @@ incremental_backups: false
snapshot_before_compaction: false
# Whether or not a snapshot is taken of the data before keyspace truncation
# or dropping of column families. The STRONGLY advised default of true
# or dropping of column families. The STRONGLY advised default of true
# should be used to provide data safety. If you set this flag to false, you will
# lose data on truncation or drop.
auto_snapshot: false
@@ -504,7 +507,7 @@ endpoint_snitch: SimpleSnitch
# controls how often to perform the more expensive part of host score
# calculation
dynamic_snitch_update_interval_in_ms: 100
dynamic_snitch_update_interval_in_ms: 100
# controls how often to reset all host scores, allowing a bad host to
# possibly recover
dynamic_snitch_reset_interval_in_ms: 600000
@@ -534,7 +537,7 @@ request_scheduler: org.apache.cassandra.scheduler.NoScheduler
# NoScheduler - Has no options
# RoundRobin
# - throttle_limit -- The throttle_limit is the number of in-flight
# requests per client. Requests beyond
# requests per client. Requests beyond
# that limit are queued up until
# running requests can complete.
# The value of 80 here is twice the number of

View File

@@ -9,13 +9,13 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:property-placeholder
location="classpath:/config/cassandra-connection.properties,classpath:/org/springframework/data/cassandra/test/integration/config/cassandra.properties" />
location="classpath:/config/cassandra-connection.properties,classpath:/org/springframework/data/cassandra/config/xml/cassandra.properties" />
<cass:cluster contact-points="${build.cassandra.host}"
port="${build.cassandra.native_transport_port}" compression="SNAPPY">
<cass:local-pooling-options
min-simultaneous-requests="25" max-simultaneous-requests="100"
core-connections="2" max-connections="8" />
min-simultaneous-requests="26" max-simultaneous-requests="101"
core-connections="3" max-connections="9" />
<cass:remote-pooling-options
min-simultaneous-requests="25" max-simultaneous-requests="100"
core-connections="1" max-connections="2" />