001/* 002 * Copyright 2012-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.autoconfigure.data.cassandra; 018 019import java.util.Collections; 020import java.util.List; 021 022import com.datastax.driver.core.Cluster; 023import com.datastax.driver.core.Session; 024 025import org.springframework.beans.factory.BeanFactory; 026import org.springframework.boot.autoconfigure.AutoConfigurationPackages; 027import org.springframework.boot.autoconfigure.AutoConfigureAfter; 028import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 029import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; 030import org.springframework.boot.autoconfigure.cassandra.CassandraProperties; 031import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 032import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 033import org.springframework.boot.autoconfigure.domain.EntityScanPackages; 034import org.springframework.boot.context.properties.EnableConfigurationProperties; 035import org.springframework.boot.context.properties.PropertyMapper; 036import org.springframework.boot.context.properties.bind.Binder; 037import org.springframework.context.annotation.Bean; 038import org.springframework.context.annotation.Configuration; 039import org.springframework.core.env.Environment; 040import org.springframework.data.cassandra.config.CassandraEntityClassScanner; 041import org.springframework.data.cassandra.config.CassandraSessionFactoryBean; 042import org.springframework.data.cassandra.config.SchemaAction; 043import org.springframework.data.cassandra.core.CassandraAdminOperations; 044import org.springframework.data.cassandra.core.CassandraTemplate; 045import org.springframework.data.cassandra.core.convert.CassandraConverter; 046import org.springframework.data.cassandra.core.convert.CassandraCustomConversions; 047import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; 048import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; 049import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver; 050 051/** 052 * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Cassandra support. 053 * 054 * @author Julien Dubois 055 * @author EddĂș MelĂ©ndez 056 * @author Mark Paluch 057 * @author Madhura Bhave 058 * @since 1.3.0 059 */ 060@Configuration 061@ConditionalOnClass({ Cluster.class, CassandraAdminOperations.class }) 062@EnableConfigurationProperties(CassandraProperties.class) 063@AutoConfigureAfter(CassandraAutoConfiguration.class) 064public class CassandraDataAutoConfiguration { 065 066 private final BeanFactory beanFactory; 067 068 private final CassandraProperties properties; 069 070 private final Cluster cluster; 071 072 private final Environment environment; 073 074 public CassandraDataAutoConfiguration(BeanFactory beanFactory, 075 CassandraProperties properties, Cluster cluster, Environment environment) { 076 this.beanFactory = beanFactory; 077 this.properties = properties; 078 this.cluster = cluster; 079 this.environment = environment; 080 } 081 082 @Bean 083 @ConditionalOnMissingBean 084 public CassandraMappingContext cassandraMapping( 085 CassandraCustomConversions conversions) throws ClassNotFoundException { 086 CassandraMappingContext context = new CassandraMappingContext(); 087 List<String> packages = EntityScanPackages.get(this.beanFactory) 088 .getPackageNames(); 089 if (packages.isEmpty() && AutoConfigurationPackages.has(this.beanFactory)) { 090 packages = AutoConfigurationPackages.get(this.beanFactory); 091 } 092 if (!packages.isEmpty()) { 093 context.setInitialEntitySet(CassandraEntityClassScanner.scan(packages)); 094 } 095 PropertyMapper.get().from(this.properties::getKeyspaceName).whenHasText() 096 .as(this::createSimpleUserTypeResolver).to(context::setUserTypeResolver); 097 context.setCustomConversions(conversions); 098 return context; 099 } 100 101 private SimpleUserTypeResolver createSimpleUserTypeResolver(String keyspaceName) { 102 return new SimpleUserTypeResolver(this.cluster, keyspaceName); 103 } 104 105 @Bean 106 @ConditionalOnMissingBean 107 public CassandraConverter cassandraConverter(CassandraMappingContext mapping, 108 CassandraCustomConversions conversions) { 109 MappingCassandraConverter converter = new MappingCassandraConverter(mapping); 110 converter.setCustomConversions(conversions); 111 return converter; 112 } 113 114 @Bean 115 @ConditionalOnMissingBean(Session.class) 116 public CassandraSessionFactoryBean cassandraSession(CassandraConverter converter) 117 throws Exception { 118 CassandraSessionFactoryBean session = new CassandraSessionFactoryBean(); 119 session.setCluster(this.cluster); 120 session.setConverter(converter); 121 session.setKeyspaceName(this.properties.getKeyspaceName()); 122 Binder binder = Binder.get(this.environment); 123 binder.bind("spring.data.cassandra.schema-action", SchemaAction.class) 124 .ifBound(session::setSchemaAction); 125 return session; 126 } 127 128 @Bean 129 @ConditionalOnMissingBean 130 public CassandraTemplate cassandraTemplate(Session session, 131 CassandraConverter converter) throws Exception { 132 return new CassandraTemplate(session, converter); 133 } 134 135 @Bean 136 @ConditionalOnMissingBean 137 public CassandraCustomConversions cassandraCustomConversions() { 138 return new CassandraCustomConversions(Collections.emptyList()); 139 } 140 141}