diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraSessionFactoryBean.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraSessionFactoryBean.java index 263099953..cb868ffed 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraSessionFactoryBean.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraSessionFactoryBean.java @@ -47,6 +47,51 @@ public class CassandraSessionFactoryBean extends CassandraCqlSessionFactoryBean private SchemaAction schemaAction = SchemaAction.NONE; + /* + * (non-Javadoc) + * @see org.springframework.cassandra.config.CassandraCqlSessionFactoryBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + + Assert.state(converter != null, "Converter was not properly initialized"); + + super.afterPropertiesSet(); + + admin = new CassandraAdminTemplate(getObject(), converter); + + performSchemaAction(); + } + + /** + * Perform the configure {@link SchemaAction} using {@link CassandraMappingContext} metadata. + */ + protected void performSchemaAction() { + + boolean create = false; + boolean drop = DEFAULT_DROP_TABLES; + boolean dropUnused = DEFAULT_DROP_UNUSED_TABLES; + boolean ifNotExists = DEFAULT_CREATE_IF_NOT_EXISTS; + + switch (schemaAction) { + case RECREATE_DROP_UNUSED: + dropUnused = true; + case RECREATE: + drop = true; + case CREATE_IF_NOT_EXISTS: + ifNotExists = SchemaAction.CREATE_IF_NOT_EXISTS.equals(schemaAction); + case CREATE: + create = true; + case NONE: + default: + // do nothing + } + + if (create) { + createTables(drop, dropUnused, ifNotExists); + } + } + /** * Set the {@link CassandraConverter} to use. Schema actions will derive table and user type information from the * {@link CassandraMappingContext} inside {@code converter}. @@ -92,50 +137,6 @@ public class CassandraSessionFactoryBean extends CassandraCqlSessionFactoryBean return schemaAction; } - /* (non-Javadoc) - * @see org.springframework.cassandra.config.CassandraCqlSessionFactoryBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - - Assert.state(converter != null, "Converter was not properly initialized"); - - super.afterPropertiesSet(); - - admin = new CassandraAdminTemplate(getObject(), converter); - - performSchemaAction(); - } - - /** - * Perform the configure {@link SchemaAction} using {@link CassandraMappingContext} metadata. - */ - protected void performSchemaAction() { - - boolean create = false; - boolean drop = DEFAULT_DROP_TABLES; - boolean dropUnused = DEFAULT_DROP_UNUSED_TABLES; - boolean ifNotExists = DEFAULT_CREATE_IF_NOT_EXISTS; - - switch (schemaAction) { - case RECREATE_DROP_UNUSED: - dropUnused = true; - case RECREATE: - drop = true; - case CREATE_IF_NOT_EXISTS: - ifNotExists = SchemaAction.CREATE_IF_NOT_EXISTS.equals(schemaAction); - case CREATE: - create = true; - case NONE: - default: - // do nothing - } - - if (create) { - createTables(drop, dropUnused, ifNotExists); - } - } - /** * Perform schema actions. * diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cql/config/CassandraCqlClusterFactoryBean.java b/spring-data-cassandra/src/main/java/org/springframework/data/cql/config/CassandraCqlClusterFactoryBean.java index c8257939b..2b2ffbe24 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cql/config/CassandraCqlClusterFactoryBean.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cql/config/CassandraCqlClusterFactoryBean.java @@ -18,10 +18,9 @@ package org.springframework.data.cql.config; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; @@ -39,9 +38,23 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import com.datastax.driver.core.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.datastax.driver.core.AuthProvider; +import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Cluster.Builder; +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; +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.TimestampGenerator; import com.datastax.driver.core.policies.AddressTranslator; import com.datastax.driver.core.policies.LoadBalancingPolicy; import com.datastax.driver.core.policies.ReconnectionPolicy; @@ -129,89 +142,55 @@ public class CassandraCqlClusterFactoryBean @Override public void afterPropertiesSet() throws Exception { - Assert.isTrue(StringUtils.hasText(contactPoints), "At least one server is required"); + Assert.hasText(contactPoints, "At least one server is required"); Cluster.Builder clusterBuilder = newClusterBuilder(); clusterBuilder.addContactPoints(StringUtils.commaDelimitedListToStringArray(contactPoints)).withPort(port); + clusterBuilder.withMaxSchemaAgreementWaitSeconds(maxSchemaAgreementWaitSeconds); - if (compressionType != null) { - clusterBuilder.withCompression(convertCompressionType(compressionType)); - } + Optional.ofNullable(compressionType).map(CassandraCqlClusterFactoryBean::convertCompressionType) + .ifPresent(clusterBuilder::withCompression); - if (poolingOptions != null) { - clusterBuilder.withPoolingOptions(poolingOptions); - } - - if (socketOptions != null) { - clusterBuilder.withSocketOptions(socketOptions); - } - - if (queryOptions != null) { - clusterBuilder.withQueryOptions(queryOptions); - } + Optional.ofNullable(addressTranslator).ifPresent(clusterBuilder::withAddressTranslator); + Optional.ofNullable(loadBalancingPolicy).ifPresent(clusterBuilder::withLoadBalancingPolicy); + Optional.ofNullable(nettyOptions).ifPresent(clusterBuilder::withNettyOptions); + Optional.ofNullable(poolingOptions).ifPresent(clusterBuilder::withPoolingOptions); + Optional.ofNullable(protocolVersion).ifPresent(clusterBuilder::withProtocolVersion); + Optional.ofNullable(queryOptions).ifPresent(clusterBuilder::withQueryOptions); + Optional.ofNullable(reconnectionPolicy).ifPresent(clusterBuilder::withReconnectionPolicy); + Optional.ofNullable(retryPolicy).ifPresent(clusterBuilder::withRetryPolicy); + Optional.ofNullable(socketOptions).ifPresent(clusterBuilder::withSocketOptions); + Optional.ofNullable(speculativeExecutionPolicy).ifPresent(clusterBuilder::withSpeculativeExecutionPolicy); + Optional.ofNullable(timestampGenerator).ifPresent(clusterBuilder::withTimestampGenerator); if (authProvider != null) { clusterBuilder.withAuthProvider(authProvider); - } else if (username != null) { + } + else if (username != null) { clusterBuilder.withCredentials(username, password); } - if (nettyOptions != null) { - clusterBuilder.withNettyOptions(nettyOptions); - } - - if (loadBalancingPolicy != null) { - clusterBuilder.withLoadBalancingPolicy(loadBalancingPolicy); - } - - if (reconnectionPolicy != null) { - clusterBuilder.withReconnectionPolicy(reconnectionPolicy); - } - - if (retryPolicy != null) { - clusterBuilder.withRetryPolicy(retryPolicy); - } - - if (!metricsEnabled) { - clusterBuilder.withoutMetrics(); - } - if (!jmxReportingEnabled) { clusterBuilder.withoutJMXReporting(); } + if (!metricsEnabled) { + clusterBuilder.withoutMetrics(); + } + if (sslEnabled) { - if (sslOptions == null) { - clusterBuilder.withSSL(); - } else { + if (sslOptions != null) { clusterBuilder.withSSL(sslOptions); } + else { + clusterBuilder.withSSL(); + } } - if (protocolVersion != null) { - clusterBuilder.withProtocolVersion(protocolVersion); - } + Optional.ofNullable(resolveClusterName()).filter(StringUtils::hasText) + .ifPresent(clusterBuilder::withClusterName); - if (addressTranslator != null) { - clusterBuilder.withAddressTranslator(addressTranslator); - } - - String clusterName = resolveClusterName(); - - if (StringUtils.hasText(clusterName)) { - clusterBuilder.withClusterName(clusterName); - } - - clusterBuilder.withMaxSchemaAgreementWaitSeconds(maxSchemaAgreementWaitSeconds); - - if (speculativeExecutionPolicy != null) { - clusterBuilder.withSpeculativeExecutionPolicy(speculativeExecutionPolicy); - } - - if (timestampGenerator != null) { - clusterBuilder.withTimestampGenerator(timestampGenerator); - } if (clusterBuilderConfigurer != null) { clusterBuilderConfigurer.configure(clusterBuilder); @@ -219,16 +198,10 @@ public class CassandraCqlClusterFactoryBean cluster = clusterBuilder.build(); - if (hostStateListener != null) { - cluster.register(hostStateListener); - } - - if (latencyTracker != null) { - cluster.register(latencyTracker); - } + Optional.ofNullable(hostStateListener).ifPresent(cluster::register); + Optional.ofNullable(latencyTracker).ifPresent(cluster::register); generateSpecificationsFromFactoryBeans(); - executeSpecsAndScripts(keyspaceCreations, startupScripts); } @@ -240,6 +213,7 @@ public class CassandraCqlClusterFactoryBean return Cluster.builder(); } + /* (non-Javadoc) */ private String resolveClusterName() { return (StringUtils.hasText(clusterName) ? clusterName : beanName); } @@ -297,6 +271,7 @@ public class CassandraCqlClusterFactoryBean private void generateSpecificationsFromFactoryBeans() { keyspaceSpecifications.forEach(keyspaceActionSpecification -> { + if (keyspaceActionSpecification instanceof CreateKeyspaceSpecification) { keyspaceCreations.add((CreateKeyspaceSpecification) keyspaceActionSpecification); } @@ -321,7 +296,8 @@ public class CassandraCqlClusterFactoryBean .forEach(keyspaceActionSpecification -> template.execute(toCql(keyspaceActionSpecification))); scripts.forEach(template::execute); - } finally { + } + finally { if (session != null) { session.close(); } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cql/config/CassandraCqlSessionFactoryBean.java b/spring-data-cassandra/src/main/java/org/springframework/data/cql/config/CassandraCqlSessionFactoryBean.java index e3011df8e..ceb61e1cd 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cql/config/CassandraCqlSessionFactoryBean.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cql/config/CassandraCqlSessionFactoryBean.java @@ -20,8 +20,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; @@ -34,6 +32,9 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Session; @@ -69,7 +70,25 @@ public class CassandraCqlSessionFactoryBean private String keyspaceName; - /* (non-Javadoc) + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + + this.session = connect(getKeyspaceName()); + + executeScripts(getStartupScripts()); + } + + /* (non-Javadoc) */ + Session connect(String keyspaceName) { + return (StringUtils.hasText(keyspaceName) ? getCluster().connect(keyspaceName) : getCluster().connect()); + } + + /* + * (non-Javadoc) * @see org.springframework.beans.factory.FactoryBean#getObject() */ @Override @@ -77,7 +96,8 @@ public class CassandraCqlSessionFactoryBean return this.session; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.beans.factory.FactoryBean#getObjectType() */ @Override @@ -85,7 +105,8 @@ public class CassandraCqlSessionFactoryBean return (this.session != null ? this.session.getClass() : Session.class); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.beans.factory.FactoryBean#isSingleton() */ @Override @@ -93,27 +114,11 @@ public class CassandraCqlSessionFactoryBean return true; } - /* (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - - this.session = connect(getKeyspaceName()); - executeScripts(getStartupScripts()); - } - - Session connect(String keyspaceName) { - - return (StringUtils.hasText(keyspaceName) ? getCluster().connect(keyspaceName) : getCluster().connect()); - } - /* (non-Javadoc) * @see org.springframework.beans.factory.DisposableBean#destroy() */ @Override public void destroy() throws Exception { - executeScripts(getShutdownScripts()); getSession().close(); } @@ -160,6 +165,7 @@ public class CassandraCqlSessionFactoryBean public boolean isConnected() { Session session = getObject(); + return !(session == null || session.isClosed()); } @@ -172,7 +178,6 @@ public class CassandraCqlSessionFactoryBean * @see #getCluster() */ public void setCluster(Cluster cluster) { - Assert.notNull(cluster, "Cluster must not be null"); this.cluster = cluster; } @@ -186,7 +191,6 @@ public class CassandraCqlSessionFactoryBean * @see #setCluster(Cluster) */ protected Cluster getCluster() { - Assert.state(this.cluster != null, "Cluster was not properly initialized"); return this.cluster; } @@ -222,7 +226,9 @@ public class CassandraCqlSessionFactoryBean protected Session getSession() { Session session = getObject(); + Assert.state(session != null, "Session was not properly initialized"); + return session; } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cql/config/CassandraCqlClusterFactoryBeanUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cql/config/CassandraCqlClusterFactoryBeanUnitTests.java index cad2d272d..acf359d23 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cql/config/CassandraCqlClusterFactoryBeanUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cql/config/CassandraCqlClusterFactoryBeanUnitTests.java @@ -271,42 +271,42 @@ public class CassandraCqlClusterFactoryBeanUnitTests { @Test // DATACASS-317 public void shouldSetClusterNameWithBeanNameProperty() throws Exception { - final Cluster.Builder mockClusterBuilder = mock(Cluster.Builder.class); + Cluster.Builder mockClusterBuilder = mock(Cluster.Builder.class); + Cluster mockCluster = mock(Cluster.class); when(mockClusterBuilder.addContactPoints(anyString())).thenReturn(mockClusterBuilder); + when(mockClusterBuilder.build()).thenReturn(mockCluster); - CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean() { - @Override - Cluster.Builder newClusterBuilder() { - return mockClusterBuilder; - } - }; + CassandraCqlClusterFactoryBean bean = spy(new CassandraCqlClusterFactoryBean()); + + when(bean.newClusterBuilder()).thenReturn(mockClusterBuilder); bean.setBeanName("ABC"); bean.setClusterName(" "); bean.afterPropertiesSet(); + verify(bean, times(1)).newClusterBuilder(); verify(mockClusterBuilder, times(1)).withClusterName(eq("ABC")); } @Test // DATACASS-317 public void shouldSetClusterNameWithClusterNameProperty() throws Exception { - final Cluster.Builder mockClusterBuilder = mock(Cluster.Builder.class); + Cluster.Builder mockClusterBuilder = mock(Cluster.Builder.class); + Cluster mockCluster = mock(Cluster.class); when(mockClusterBuilder.addContactPoints(anyString())).thenReturn(mockClusterBuilder); + when(mockClusterBuilder.build()).thenReturn(mockCluster); - CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean() { - @Override - Cluster.Builder newClusterBuilder() { - return mockClusterBuilder; - } - }; + CassandraCqlClusterFactoryBean bean = spy(new CassandraCqlClusterFactoryBean()); + + when(bean.newClusterBuilder()).thenReturn(mockClusterBuilder); bean.setBeanName("ABC"); bean.setClusterName("XYZ"); bean.afterPropertiesSet(); + verify(bean,times(1)).newClusterBuilder(); verify(mockClusterBuilder, times(1)).withClusterName(eq("XYZ")); }