From ac321512bb0f32ad227f679f38eeaceb47611ce0 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 10 May 2016 17:23:58 +0200 Subject: [PATCH] DATACASS-226 - Polishing. Add tests for CassandraCqlClusterFactoryBean and AbstractClusterConfiguration. Update license headers. Extend JavaDoc. Rearrange fields in CassandraCqlClusterFactoryBean to reflect grouping similar to the client. Original pull request: #31. --- .../CassandraCqlClusterFactoryBean.java | 103 ++++-- .../java/AbstractClusterConfiguration.java | 229 ++++++++---- ...ssandraCqlClusterFactoryBeanUnitTests.java | 301 ++++++++++++++++ ...AbstractClusterConfigurationUnitTests.java | 335 ++++++++++++++++++ 4 files changed, 867 insertions(+), 101 deletions(-) create mode 100644 spring-cql/src/test/java/org/springframework/cassandra/config/CassandraCqlClusterFactoryBeanUnitTests.java create mode 100644 spring-cql/src/test/java/org/springframework/cassandra/config/java/AbstractClusterConfigurationUnitTests.java diff --git a/spring-cql/src/main/java/org/springframework/cassandra/config/CassandraCqlClusterFactoryBean.java b/spring-cql/src/main/java/org/springframework/cassandra/config/CassandraCqlClusterFactoryBean.java index 1b26f8258..a784bcd1d 100644 --- a/spring-cql/src/main/java/org/springframework/cassandra/config/CassandraCqlClusterFactoryBean.java +++ b/spring-cql/src/main/java/org/springframework/cassandra/config/CassandraCqlClusterFactoryBean.java @@ -15,25 +15,12 @@ */ package org.springframework.cassandra.config; -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.PoolingOptions; -import com.datastax.driver.core.ProtocolOptions.Compression; -import com.datastax.driver.core.ProtocolVersion; -import com.datastax.driver.core.QueryOptions; -import com.datastax.driver.core.SSLOptions; -import com.datastax.driver.core.Session; -import com.datastax.driver.core.SocketOptions; -import com.datastax.driver.core.policies.LoadBalancingPolicy; -import com.datastax.driver.core.policies.ReconnectionPolicy; -import com.datastax.driver.core.policies.RetryPolicy; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; @@ -50,14 +37,33 @@ import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.util.StringUtils; +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.PoolingOptions; +import com.datastax.driver.core.ProtocolOptions.Compression; +import com.datastax.driver.core.ProtocolVersion; +import com.datastax.driver.core.QueryOptions; +import com.datastax.driver.core.SSLOptions; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SocketOptions; +import com.datastax.driver.core.policies.LoadBalancingPolicy; +import com.datastax.driver.core.policies.ReconnectionPolicy; +import com.datastax.driver.core.policies.RetryPolicy; + /** - * Convenient factory for configuring a Cassandra Cluster. + * Convenient {@link org.springframework.beans.factory.FactoryBean} for configuring a Cassandra {@link Cluster}. * * @author Alex Shvid * @author Matthew T. Adams * @author David Webb * @author Kirk Clemens * @author Jorge Davison + * @see org.springframework.beans.factory.InitializingBean + * @see org.springframework.beans.factory.DisposableBean + * @see org.springframework.beans.factory.FactoryBean + * @see com.datastax.driver.core.Cluster */ public class CassandraCqlClusterFactoryBean implements FactoryBean, InitializingBean, DisposableBean, PersistenceExceptionTranslator { @@ -77,23 +83,32 @@ public class CassandraCqlClusterFactoryBean */ private String contactPoints = DEFAULT_CONTACT_POINTS; private int port = CassandraCqlClusterFactoryBean.DEFAULT_PORT; + + // Protocol options private CompressionType compressionType; - private PoolingOptions poolingOptions; - private SocketOptions socketOptions; - private QueryOptions queryOptions; + private SSLOptions sslOptions; + private boolean sslEnabled = DEFAULT_SSL_ENABLED; private AuthProvider authProvider; private String username; private String password; + private ProtocolVersion protocolVersion; + + // Policies private LoadBalancingPolicy loadBalancingPolicy; private ReconnectionPolicy reconnectionPolicy; private RetryPolicy retryPolicy; - private ProtocolVersion protocolVersion; + + private PoolingOptions poolingOptions; + private QueryOptions queryOptions; + private SocketOptions socketOptions; + private boolean metricsEnabled = DEFAULT_METRICS_ENABLED; private boolean jmxReportingEnabled = DEFAULT_JMX_REPORTING_ENABLED; - private boolean sslEnabled = DEFAULT_SSL_ENABLED; - private SSLOptions sslOptions; + private Host.StateListener hostStateListener; private LatencyTracker latencyTracker; + + // Startup and shutdown actions private Set> keyspaceSpecifications = new HashSet>(); private List keyspaceCreations = new ArrayList(); private List keyspaceDrops = new ArrayList(); @@ -102,26 +117,41 @@ public class CassandraCqlClusterFactoryBean private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator(); + /* (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#getObject() + */ @Override - public Cluster getObject() throws Exception { + public Cluster getObject() { return cluster; } + /* (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#getObjectType() + */ @Override public Class getObjectType() { return Cluster.class; } + /* (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#isSingleton() + */ @Override public boolean isSingleton() { return true; } + /* (non-Javadoc) + * @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException) + */ @Override public DataAccessException translateExceptionIfPossible(RuntimeException ex) { return exceptionTranslator.translateExceptionIfPossible(ex); } + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ @Override public void afterPropertiesSet() throws Exception { @@ -204,6 +234,16 @@ public class CassandraCqlClusterFactoryBean executeSpecsAndScripts(keyspaceCreations, startupScripts); } + /* (non-Javadoc) + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ + @Override + public void destroy() throws Exception { + + executeSpecsAndScripts(keyspaceDrops, shutdownScripts); + cluster.close(); + } + /** * Examines the contents of all the KeyspaceSpecificationFactoryBeans and generates the proper KeyspaceSpecification * from them. @@ -218,9 +258,7 @@ public class CassandraCqlClusterFactoryBean if (spec instanceof DropKeyspaceSpecification) { keyspaceDrops.add((DropKeyspaceSpecification) spec); } - } - } protected void executeSpecsAndScripts(@SuppressWarnings("rawtypes") List specs, List scripts) { @@ -271,13 +309,6 @@ public class CassandraCqlClusterFactoryBean } } - @Override - public void destroy() throws Exception { - - executeSpecsAndScripts(keyspaceDrops, shutdownScripts); - cluster.close(); - } - /** * Set a comma-delimited string of the contact points (hosts) to connect to. Default is {@code localhost}, see * {@link #DEFAULT_CONTACT_POINTS}. @@ -440,6 +471,10 @@ public class CassandraCqlClusterFactoryBean this.startupScripts = scripts; } + public List getStartupScripts() { + return startupScripts; + } + /** * Set a {@link List} of raw {@link String CQL statements} that are executed when this factory is {@link #destroy() * destroyed}. {@link DropKeyspaceSpecification Drop keyspace specifications} are executed on a system session with no @@ -451,6 +486,10 @@ public class CassandraCqlClusterFactoryBean this.shutdownScripts = scripts; } + public List getShutdownScripts() { + return shutdownScripts; + } + /** * @return Returns the keyspaceSpecifications. */ @@ -459,8 +498,6 @@ public class CassandraCqlClusterFactoryBean } /** - * If accumlating is true, we append to the list, otherwise we replace the list. - * * @param keyspaceSpecifications The keyspaceSpecifications to set. */ public void setKeyspaceSpecifications(Set> keyspaceSpecifications) { diff --git a/spring-cql/src/main/java/org/springframework/cassandra/config/java/AbstractClusterConfiguration.java b/spring-cql/src/main/java/org/springframework/cassandra/config/java/AbstractClusterConfiguration.java index 5bc4bf839..b5c5c7663 100644 --- a/spring-cql/src/main/java/org/springframework/cassandra/config/java/AbstractClusterConfiguration.java +++ b/spring-cql/src/main/java/org/springframework/cassandra/config/java/AbstractClusterConfiguration.java @@ -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,18 +28,19 @@ import org.springframework.context.annotation.Configuration; import com.datastax.driver.core.AuthProvider; import com.datastax.driver.core.PoolingOptions; import com.datastax.driver.core.ProtocolVersion; -import com.datastax.driver.core.SocketOptions; import com.datastax.driver.core.QueryOptions; +import com.datastax.driver.core.SocketOptions; import com.datastax.driver.core.policies.LoadBalancingPolicy; import com.datastax.driver.core.policies.ReconnectionPolicy; import com.datastax.driver.core.policies.RetryPolicy; /** * Base class for Spring Cassandra configuration that can handle creating namespaces, execute arbitrary CQL on startup & - * shutdown, and optionally drop namespaces. - * + * shutdown, and optionally drop keyspaces. + * * @author Matthew T. Adams * @author Jorge Davison + * @author Mark Paluch */ @Configuration public abstract class AbstractClusterConfiguration { @@ -48,87 +49,179 @@ public abstract class AbstractClusterConfiguration { public CassandraCqlClusterFactoryBean cluster() { CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + + bean.setContactPoints(getContactPoints()); + bean.setPort(getPort()); + bean.setAuthProvider(getAuthProvider()); bean.setCompressionType(getCompressionType()); - bean.setContactPoints(getContactPoints()); + bean.setProtocolVersion(getProtocolVersion()); + + bean.setLoadBalancingPolicy(getLoadBalancingPolicy()); + bean.setReconnectionPolicy(getReconnectionPolicy()); + bean.setRetryPolicy(getRetryPolicy()); + bean.setMetricsEnabled(getMetricsEnabled()); + + bean.setPoolingOptions(getPoolingOptions()); + bean.setQueryOptions(getQueryOptions()); + bean.setSocketOptions(getSocketOptions()); + bean.setKeyspaceCreations(getKeyspaceCreations()); bean.setKeyspaceDrops(getKeyspaceDrops()); - bean.setLoadBalancingPolicy(getLoadBalancingPolicy()); - bean.setMetricsEnabled(getMetricsEnabled()); - bean.setPort(getPort()); - bean.setReconnectionPolicy(getReconnectionPolicy()); - bean.setPoolingOptions(getPoolingOptions()); - bean.setRetryPolicy(getRetryPolicy()); - bean.setShutdownScripts(getShutdownScripts()); - bean.setSocketOptions(getSocketOptions()); - bean.setQueryOptions(getQueryOptions()); bean.setStartupScripts(getStartupScripts()); - bean.setProtocolVersion(getProtocolVersion()); + bean.setShutdownScripts(getShutdownScripts()); return bean; } - protected List getStartupScripts() { - return Collections.emptyList(); - } - - protected SocketOptions getSocketOptions() { - return null; - } - - protected QueryOptions getQueryOptions() { - return null; - } - - protected List getShutdownScripts() { - return Collections.emptyList(); - } - - protected ReconnectionPolicy getReconnectionPolicy() { - return null; - } - - protected RetryPolicy getRetryPolicy() { - return null; - } - - protected PoolingOptions getPoolingOptions() { - return null; - } - + /** + * Returns the Cassandra port. Defaults to {@code 9042} + * + * @return the Cassandra port + * @see CassandraCqlClusterFactoryBean#DEFAULT_PORT + */ protected int getPort() { return CassandraCqlClusterFactoryBean.DEFAULT_PORT; } - protected boolean getMetricsEnabled() { - return CassandraCqlClusterFactoryBean.DEFAULT_METRICS_ENABLED; - } - - protected LoadBalancingPolicy getLoadBalancingPolicy() { - return null; - } - - protected List getKeyspaceDrops() { - return Collections.emptyList(); - } - - protected List getKeyspaceCreations() { - return Collections.emptyList(); - } - + /** + * Returns the Cassandra contact points. Defaults to {@code localhost} + * + * @return the Cassandra contact points + * @see CassandraCqlClusterFactoryBean#DEFAULT_CONTACT_POINTS + */ protected String getContactPoints() { return CassandraCqlClusterFactoryBean.DEFAULT_CONTACT_POINTS; } - protected CompressionType getCompressionType() { - return null; - } - + /** + * Returns the {@link AuthProvider}. + * + * @return the {@link AuthProvider}, may be {@literal null}. + */ protected AuthProvider getAuthProvider() { return null; } - protected ProtocolVersion getProtocolVersion(){ + /** + * Returns the {@link CompressionType}. + * + * @return the {@link CompressionType}, may be {@literal null}. + */ + protected CompressionType getCompressionType() { return null; - } + } + + /** + * Returns the {@link ProtocolVersion}. + * + * @return the {@link ProtocolVersion}, may be {@literal null}. + */ + protected ProtocolVersion getProtocolVersion() { + return null; + } + + /** + * Returns the {@link LoadBalancingPolicy}. + * + * @return the {@link LoadBalancingPolicy}, may be {@literal null}. + */ + protected LoadBalancingPolicy getLoadBalancingPolicy() { + return null; + } + + /** + * Returns the {@link ReconnectionPolicy}. + * + * @return the {@link ReconnectionPolicy}, may be {@literal null}. + */ + protected ReconnectionPolicy getReconnectionPolicy() { + return null; + } + + /** + * Returns the {@link RetryPolicy}. + * + * @return the {@link RetryPolicy}, may be {@literal null}. + */ + protected RetryPolicy getRetryPolicy() { + return null; + } + + /** + * Returns the whether to enable metrics. Defaults to {@literal true} + * + * @return {@literal true} to enable metrics. + * @see CassandraCqlClusterFactoryBean#DEFAULT_METRICS_ENABLED + */ + protected boolean getMetricsEnabled() { + return CassandraCqlClusterFactoryBean.DEFAULT_METRICS_ENABLED; + } + + /** + * Returns the {@link PoolingOptions}. + * + * @return the {@link PoolingOptions}, may be {@literal null}. + */ + protected PoolingOptions getPoolingOptions() { + return null; + } + + /** + * Returns the {@link QueryOptions}. + * + * @return the {@link QueryOptions}, may be {@literal null}. + * @since 1.5 + */ + protected QueryOptions getQueryOptions() { + return null; + } + + /** + * Returns the {@link SocketOptions}. + * + * @return the {@link SocketOptions}, may be {@literal null}. + */ + protected SocketOptions getSocketOptions() { + return null; + } + + /** + * Returns the list of keyspace creations to be run right after {@link com.datastax.driver.core.Cluster} + * initialization. + * + * @return the list of keyspace creations, may be empty but never {@link null} + */ + protected List getKeyspaceCreations() { + return Collections.emptyList(); + } + + /** + * Returns the list of keyspace drops to be run before {@link com.datastax.driver.core.Cluster} shutdown. + * + * @return the list of keyspace drops, may be empty but never {@link null} + */ + protected List getKeyspaceDrops() { + return Collections.emptyList(); + } + + /** + * Returns the list of startup scripts to be run after {@link #getKeyspaceCreations() keyspace creations} and after + * {@link com.datastax.driver.core.Cluster} initialization. + * + * @return the list of startup scripts, may be empty but never {@link null} + */ + protected List getStartupScripts() { + return Collections.emptyList(); + } + + /** + * Returns the list of shutdown scripts to be run after {@link #getKeyspaceDrops() keyspace drops} and right before + * {@link com.datastax.driver.core.Cluster} shutdown. + * + * @return the list of shutdown scripts, may be empty but never {@link null} + */ + protected List getShutdownScripts() { + return Collections.emptyList(); + } } diff --git a/spring-cql/src/test/java/org/springframework/cassandra/config/CassandraCqlClusterFactoryBeanUnitTests.java b/spring-cql/src/test/java/org/springframework/cassandra/config/CassandraCqlClusterFactoryBeanUnitTests.java new file mode 100644 index 000000000..0679c7865 --- /dev/null +++ b/spring-cql/src/test/java/org/springframework/cassandra/config/CassandraCqlClusterFactoryBeanUnitTests.java @@ -0,0 +1,301 @@ +/* + * 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; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +import com.datastax.driver.core.AuthProvider; +import com.datastax.driver.core.Configuration; +import com.datastax.driver.core.PlainTextAuthProvider; +import com.datastax.driver.core.PoolingOptions; +import com.datastax.driver.core.ProtocolOptions.Compression; +import com.datastax.driver.core.ProtocolVersion; +import com.datastax.driver.core.QueryOptions; +import com.datastax.driver.core.SSLOptions; +import com.datastax.driver.core.SocketOptions; +import com.datastax.driver.core.policies.ExponentialReconnectionPolicy; +import com.datastax.driver.core.policies.LoadBalancingPolicy; +import com.datastax.driver.core.policies.ReconnectionPolicy; +import com.datastax.driver.core.policies.RoundRobinPolicy; + +/** + * Unit tests for {@link CassandraCqlClusterFactoryBean}. + * + * @see DATACASS-226 + * @author Mark Paluch + */ +public class CassandraCqlClusterFactoryBeanUnitTests { + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldInitializeWithoutAnyOptions() throws Exception { + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.afterPropertiesSet(); + + assertThat(bean.getObject(), is(not(nullValue()))); + assertThat(bean.getObject().isClosed(), is(false)); + assertThat(getConfiguration(bean).getMetricsOptions(), is(not(nullValue()))); + assertThat(getConfiguration(bean).getMetricsOptions().isJMXReportingEnabled(), is(true)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldShutdownClusterInstance() throws Exception { + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.afterPropertiesSet(); + bean.destroy(); + + assertThat(bean.getObject().isClosed(), is(true)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetCompressionType() throws Exception { + + CompressionType compressionType = CompressionType.SNAPPY; + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setCompressionType(compressionType); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getProtocolOptions().getCompression(), is(Compression.SNAPPY)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetPoolingOptions() throws Exception { + + PoolingOptions poolingOptions = new PoolingOptions(); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setPoolingOptions(poolingOptions); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getPoolingOptions(), is(poolingOptions)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetSocketOptions() throws Exception { + + SocketOptions socketOptions = new SocketOptions(); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setSocketOptions(socketOptions); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getSocketOptions(), is(socketOptions)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetQueryOptions() throws Exception { + + QueryOptions queryOptions = new QueryOptions(); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setQueryOptions(queryOptions); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getQueryOptions(), is(queryOptions)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void defaultQueryOptionsShouldHaveOwnObjectIdentity() throws Exception { + + QueryOptions queryOptions = new QueryOptions(); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getQueryOptions(), is(not(nullValue()))); + assertThat(getConfiguration(bean).getQueryOptions(), is(not(queryOptions))); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetAuthProvider() throws Exception { + + AuthProvider authProvider = new PlainTextAuthProvider("x", "y"); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setAuthProvider(authProvider); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getProtocolOptions().getAuthProvider(), is(authProvider)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void doesNotSetPlainTextAuthenticationUnlessAuthProviderIsSet() throws Exception { + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setUsername("user"); + bean.setPassword("password"); + bean.afterPropertiesSet(); + + AuthProvider result = getConfiguration(bean).getProtocolOptions().getAuthProvider(); + assertThat(result, is(AuthProvider.NONE)); + } + + @Test + public void shouldSetAuthentication() throws Exception { + + PlainTextAuthProvider authProvider = new PlainTextAuthProvider("x", "y"); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setAuthProvider(authProvider); + bean.setUsername("user"); + bean.setPassword("password"); + bean.afterPropertiesSet(); + + AuthProvider result = getConfiguration(bean).getProtocolOptions().getAuthProvider(); + assertThat(result, is(not(nullValue()))); + assertThat(ReflectionTestUtils.getField(result, "username"), is(equalTo((Object) "user"))); + assertThat(ReflectionTestUtils.getField(result, "password"), is(equalTo((Object) "password"))); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetLoadBalancingPolicy() throws Exception { + + LoadBalancingPolicy loadBalancingPolicy = new RoundRobinPolicy(); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setLoadBalancingPolicy(loadBalancingPolicy); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getPolicies().getLoadBalancingPolicy(), is(loadBalancingPolicy)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetReconnectionPolicy() throws Exception { + + ReconnectionPolicy reconnectionPolicy = new ExponentialReconnectionPolicy(1, 2); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setReconnectionPolicy(reconnectionPolicy); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getPolicies().getReconnectionPolicy(), is(reconnectionPolicy)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetProtocolVersion() throws Exception { + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setProtocolVersion(ProtocolVersion.V2); + bean.afterPropertiesSet(); + + assertThat(ReflectionTestUtils.getField(getConfiguration(bean).getProtocolOptions(), "initialProtocolVersion"), + is((Object) ProtocolVersion.V2)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetSslOptions() throws Exception { + + SSLOptions sslOptions = new SSLOptions(); + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setSslEnabled(true); + bean.setSslOptions(sslOptions); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getProtocolOptions().getSSLOptions(), is(sslOptions)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldDisableMetrics() throws Exception { + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setMetricsEnabled(false); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getMetricsOptions(), is(nullValue())); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldDisableJmxReporting() throws Exception { + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.setJmxReportingEnabled(false); + bean.afterPropertiesSet(); + + assertThat(getConfiguration(bean).getMetricsOptions().isJMXReportingEnabled(), is(false)); + } + + private Configuration getConfiguration(CassandraCqlClusterFactoryBean bean) throws Exception { + return bean.getObject().getConfiguration(); + } +} diff --git a/spring-cql/src/test/java/org/springframework/cassandra/config/java/AbstractClusterConfigurationUnitTests.java b/spring-cql/src/test/java/org/springframework/cassandra/config/java/AbstractClusterConfigurationUnitTests.java new file mode 100644 index 000000000..8f26da188 --- /dev/null +++ b/spring-cql/src/test/java/org/springframework/cassandra/config/java/AbstractClusterConfigurationUnitTests.java @@ -0,0 +1,335 @@ +/* + * 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 static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.springframework.cassandra.config.CassandraCqlClusterFactoryBean; +import org.springframework.cassandra.config.CompressionType; +import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification; +import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification; +import org.springframework.test.util.ReflectionTestUtils; + +import com.datastax.driver.core.AuthProvider; +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Configuration; +import com.datastax.driver.core.PlainTextAuthProvider; +import com.datastax.driver.core.PoolingOptions; +import com.datastax.driver.core.ProtocolOptions.Compression; +import com.datastax.driver.core.ProtocolVersion; +import com.datastax.driver.core.QueryOptions; +import com.datastax.driver.core.SocketOptions; +import com.datastax.driver.core.policies.ExponentialReconnectionPolicy; +import com.datastax.driver.core.policies.LoadBalancingPolicy; +import com.datastax.driver.core.policies.ReconnectionPolicy; +import com.datastax.driver.core.policies.RoundRobinPolicy; + +/** + * Unit tests for {@link AbstractClusterConfiguration}. + * + * @author Mark Paluch + * @soundtrack Max Graham Feat Neev Kennedy - So Caught Up (Dns Project Remix) + * @see DATACASS-226 + */ +public class AbstractClusterConfigurationUnitTests { + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldInitializeWithoutAnyOptions() throws Exception { + + CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean(); + bean.afterPropertiesSet(); + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() {}; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(cluster, is(not(nullValue()))); + assertThat(cluster.isClosed(), is(false)); + assertThat(getConfiguration(cluster).getMetricsOptions(), is(not(nullValue()))); + assertThat(getConfiguration(cluster).getMetricsOptions().isJMXReportingEnabled(), is(true)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetCompressionType() throws Exception { + + final CompressionType compressionType = CompressionType.SNAPPY; + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected CompressionType getCompressionType() { + return compressionType; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(getConfiguration(cluster).getProtocolOptions().getCompression(), is(Compression.SNAPPY)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetPoolingOptions() throws Exception { + + final PoolingOptions poolingOptions = new PoolingOptions(); + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected PoolingOptions getPoolingOptions() { + return poolingOptions; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(getConfiguration(cluster).getPoolingOptions(), is(poolingOptions)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetSocketOptions() throws Exception { + + final SocketOptions socketOptions = new SocketOptions(); + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected SocketOptions getSocketOptions() { + return socketOptions; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(getConfiguration(cluster).getSocketOptions(), is(socketOptions)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetQueryOptions() throws Exception { + + final QueryOptions queryOptions = new QueryOptions(); + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected QueryOptions getQueryOptions() { + return queryOptions; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(getConfiguration(cluster).getQueryOptions(), is(queryOptions)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetAuthProvider() throws Exception { + + final AuthProvider authProvider = new PlainTextAuthProvider("x", "y"); + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected AuthProvider getAuthProvider() { + return authProvider; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(getConfiguration(cluster).getProtocolOptions().getAuthProvider(), is(authProvider)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetLoadBalancingPolicy() throws Exception { + + final LoadBalancingPolicy loadBalancingPolicy = new RoundRobinPolicy(); + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected LoadBalancingPolicy getLoadBalancingPolicy() { + return loadBalancingPolicy; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(getConfiguration(cluster).getPolicies().getLoadBalancingPolicy(), is(loadBalancingPolicy)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetReconnectionPolicy() throws Exception { + + final ReconnectionPolicy reconnectionPolicy = new ExponentialReconnectionPolicy(1, 2); + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected ReconnectionPolicy getReconnectionPolicy() { + return reconnectionPolicy; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(getConfiguration(cluster).getPolicies().getReconnectionPolicy(), is(reconnectionPolicy)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetProtocolVersion() throws Exception { + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected ProtocolVersion getProtocolVersion() { + return ProtocolVersion.V2; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(ReflectionTestUtils.getField(getConfiguration(cluster).getProtocolOptions(), "initialProtocolVersion"), + is((Object) ProtocolVersion.V2)); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldDisableMetrics() throws Exception { + + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected boolean getMetricsEnabled() { + return false; + } + }; + + Cluster cluster = getCluster(clusterConfiguration); + assertThat(getConfiguration(cluster).getMetricsOptions(), is(nullValue())); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetKeyspaceCreations() throws Exception { + + final List specification = Collections + .singletonList(CreateKeyspaceSpecification.createKeyspace()); + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected List getKeyspaceCreations() { + return specification; + } + }; + + assertThat(clusterConfiguration.cluster().getKeyspaceCreations(), is(equalTo(specification))); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetKeyspaceDrops() throws Exception { + + final List specification = Collections + .singletonList(DropKeyspaceSpecification.dropKeyspace()); + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected List getKeyspaceDrops() { + return specification; + } + }; + + assertThat(clusterConfiguration.cluster().getKeyspaceDrops(), is(equalTo(specification))); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetStartupScripts() throws Exception { + + final List scripts = Collections.singletonList("USE BLUE_METH; CREATE TABLE..."); + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected List getStartupScripts() { + return scripts; + } + }; + + assertThat(clusterConfiguration.cluster().getStartupScripts(), is(equalTo(scripts))); + } + + /** + * @see DATACASS-226 + * @throws Exception + */ + @Test + public void shouldSetShutdownScripts() throws Exception { + + final List scripts = Collections.singletonList("USE BLUE_METH; DROP TABLE..."); + AbstractClusterConfiguration clusterConfiguration = new AbstractClusterConfiguration() { + @Override + protected List getShutdownScripts() { + return scripts; + } + }; + + assertThat(clusterConfiguration.cluster().getShutdownScripts(), is(equalTo(scripts))); + } + + private Configuration getConfiguration(Cluster cluster) throws Exception { + return cluster.getConfiguration(); + } + + private Cluster getCluster(AbstractClusterConfiguration clusterConfiguration) throws Exception { + + CassandraCqlClusterFactoryBean cluster = clusterConfiguration.cluster(); + cluster.afterPropertiesSet(); + return cluster.getObject(); + } +}