2323import java .util .LinkedHashMap ;
2424import java .util .List ;
2525import java .util .Map ;
26- import java .util .function .Supplier ;
2726
2827import javax .net .ssl .SSLContext ;
2928
6463 * @author Stephane Nicoll
6564 * @author Steffen F. Qvistgaard
6665 * @author Ittay Stern
66+ * @author Moritz Halbritter
67+ * @author Andy Wilkinson
68+ * @author Phillip Webb
6769 * @since 1.3.0
6870 */
6971@ AutoConfiguration
70- @ ConditionalOnClass ({ CqlSession .class } )
72+ @ ConditionalOnClass (CqlSession .class )
7173@ EnableConfigurationProperties (CassandraProperties .class )
7274public class CassandraAutoConfiguration {
7375
@@ -80,6 +82,17 @@ public class CassandraAutoConfiguration {
8082 SPRING_BOOT_DEFAULTS = options .build ();
8183 }
8284
85+ private final CassandraProperties properties ;
86+
87+ private final CassandraConnectionDetails connectionDetails ;
88+
89+ CassandraAutoConfiguration (CassandraProperties properties ,
90+ ObjectProvider <CassandraConnectionDetails > connectionDetails ) {
91+ this .properties = properties ;
92+ this .connectionDetails = connectionDetails
93+ .getIfAvailable (() -> new PropertiesCassandraConnectionDetails (properties ));
94+ }
95+
8396 @ Bean
8497 @ ConditionalOnMissingBean
8598 @ Lazy
@@ -90,24 +103,25 @@ public CqlSession cassandraSession(CqlSessionBuilder cqlSessionBuilder) {
90103 @ Bean
91104 @ ConditionalOnMissingBean
92105 @ Scope ("prototype" )
93- public CqlSessionBuilder cassandraSessionBuilder (CassandraProperties properties ,
94- DriverConfigLoader driverConfigLoader , ObjectProvider <CqlSessionBuilderCustomizer > builderCustomizers ) {
106+ public CqlSessionBuilder cassandraSessionBuilder (DriverConfigLoader driverConfigLoader ,
107+ ObjectProvider <CqlSessionBuilderCustomizer > builderCustomizers ) {
95108 CqlSessionBuilder builder = CqlSession .builder ().withConfigLoader (driverConfigLoader );
96- configureAuthentication (properties , builder );
97- configureSsl (properties , builder );
98- builder .withKeyspace (properties .getKeyspaceName ());
109+ configureAuthentication (builder );
110+ configureSsl (builder );
111+ builder .withKeyspace (this . properties .getKeyspaceName ());
99112 builderCustomizers .orderedStream ().forEach ((customizer ) -> customizer .customize (builder ));
100113 return builder ;
101114 }
102115
103- private void configureAuthentication (CassandraProperties properties , CqlSessionBuilder builder ) {
104- if (properties .getUsername () != null ) {
105- builder .withAuthCredentials (properties .getUsername (), properties .getPassword ());
116+ private void configureAuthentication (CqlSessionBuilder builder ) {
117+ String username = this .connectionDetails .getUsername ();
118+ if (username != null ) {
119+ builder .withAuthCredentials (username , this .connectionDetails .getPassword ());
106120 }
107121 }
108122
109- private void configureSsl (CassandraProperties properties , CqlSessionBuilder builder ) {
110- if (properties .isSsl ()) {
123+ private void configureSsl (CqlSessionBuilder builder ) {
124+ if (this . connectionDetails instanceof PropertiesCassandraConnectionDetails && this . properties .isSsl ()) {
111125 try {
112126 builder .withSslContext (SSLContext .getDefault ());
113127 }
@@ -119,20 +133,20 @@ private void configureSsl(CassandraProperties properties, CqlSessionBuilder buil
119133
120134 @ Bean (destroyMethod = "" )
121135 @ ConditionalOnMissingBean
122- public DriverConfigLoader cassandraDriverConfigLoader (CassandraProperties properties ,
136+ public DriverConfigLoader cassandraDriverConfigLoader (
123137 ObjectProvider <DriverConfigLoaderBuilderCustomizer > builderCustomizers ) {
124138 ProgrammaticDriverConfigLoaderBuilder builder = new DefaultProgrammaticDriverConfigLoaderBuilder (
125- () -> cassandraConfiguration (properties ), DefaultDriverConfigLoader .DEFAULT_ROOT_PATH );
139+ () -> cassandraConfiguration (), DefaultDriverConfigLoader .DEFAULT_ROOT_PATH );
126140 builderCustomizers .orderedStream ().forEach ((customizer ) -> customizer .customize (builder ));
127141 return builder .build ();
128142 }
129143
130- private Config cassandraConfiguration (CassandraProperties properties ) {
144+ private Config cassandraConfiguration () {
131145 ConfigFactory .invalidateCaches ();
132146 Config config = ConfigFactory .defaultOverrides ();
133- config = config .withFallback (mapConfig (properties ));
134- if (properties .getConfig () != null ) {
135- config = config .withFallback (loadConfig (properties .getConfig ()));
147+ config = config .withFallback (mapConfig ());
148+ if (this . properties .getConfig () != null ) {
149+ config = config .withFallback (loadConfig (this . properties .getConfig ()));
136150 }
137151 config = config .withFallback (SPRING_BOOT_DEFAULTS );
138152 config = config .withFallback (ConfigFactory .defaultReference ());
@@ -148,32 +162,32 @@ private Config loadConfig(Resource resource) {
148162 }
149163 }
150164
151- private Config mapConfig (CassandraProperties properties ) {
165+ private Config mapConfig () {
152166 CassandraDriverOptions options = new CassandraDriverOptions ();
153167 PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
154- map .from (properties .getSessionName ())
168+ map .from (this . properties .getSessionName ())
155169 .whenHasText ()
156170 .to ((sessionName ) -> options .add (DefaultDriverOption .SESSION_NAME , sessionName ));
157- map .from (properties :: getUsername )
158- .to ((username ) -> options .add (DefaultDriverOption .AUTH_PROVIDER_USER_NAME , username )
159- .add (DefaultDriverOption .AUTH_PROVIDER_PASSWORD , properties .getPassword ()));
160- map .from (properties ::getCompression )
171+ map .from (this . connectionDetails . getUsername () )
172+ .to ((value ) -> options .add (DefaultDriverOption .AUTH_PROVIDER_USER_NAME , value )
173+ .add (DefaultDriverOption .AUTH_PROVIDER_PASSWORD , this . connectionDetails .getPassword ()));
174+ map .from (this . properties ::getCompression )
161175 .to ((compression ) -> options .add (DefaultDriverOption .PROTOCOL_COMPRESSION , compression ));
162- mapConnectionOptions (properties , options );
163- mapPoolingOptions (properties , options );
164- mapRequestOptions (properties , options );
165- mapControlConnectionOptions (properties , options );
166- map .from (mapContactPoints (properties ))
176+ mapConnectionOptions (options );
177+ mapPoolingOptions (options );
178+ mapRequestOptions (options );
179+ mapControlConnectionOptions (options );
180+ map .from (mapContactPoints ())
167181 .to ((contactPoints ) -> options .add (DefaultDriverOption .CONTACT_POINTS , contactPoints ));
168- map .from (properties .getLocalDatacenter ())
182+ map .from (this . connectionDetails .getLocalDatacenter ())
169183 .whenHasText ()
170184 .to ((localDatacenter ) -> options .add (DefaultDriverOption .LOAD_BALANCING_LOCAL_DATACENTER , localDatacenter ));
171185 return options .build ();
172186 }
173187
174- private void mapConnectionOptions (CassandraProperties properties , CassandraDriverOptions options ) {
188+ private void mapConnectionOptions (CassandraDriverOptions options ) {
175189 PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
176- Connection connectionProperties = properties .getConnection ();
190+ Connection connectionProperties = this . properties .getConnection ();
177191 map .from (connectionProperties ::getConnectTimeout )
178192 .asInt (Duration ::toMillis )
179193 .to ((connectTimeout ) -> options .add (DefaultDriverOption .CONNECTION_CONNECT_TIMEOUT , connectTimeout ));
@@ -182,9 +196,9 @@ private void mapConnectionOptions(CassandraProperties properties, CassandraDrive
182196 .to ((initQueryTimeout ) -> options .add (DefaultDriverOption .CONNECTION_INIT_QUERY_TIMEOUT , initQueryTimeout ));
183197 }
184198
185- private void mapPoolingOptions (CassandraProperties properties , CassandraDriverOptions options ) {
199+ private void mapPoolingOptions (CassandraDriverOptions options ) {
186200 PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
187- CassandraProperties .Pool poolProperties = properties .getPool ();
201+ CassandraProperties .Pool poolProperties = this . properties .getPool ();
188202 map .from (poolProperties ::getIdleTimeout )
189203 .asInt (Duration ::toMillis )
190204 .to ((idleTimeout ) -> options .add (DefaultDriverOption .HEARTBEAT_TIMEOUT , idleTimeout ));
@@ -193,9 +207,9 @@ private void mapPoolingOptions(CassandraProperties properties, CassandraDriverOp
193207 .to ((heartBeatInterval ) -> options .add (DefaultDriverOption .HEARTBEAT_INTERVAL , heartBeatInterval ));
194208 }
195209
196- private void mapRequestOptions (CassandraProperties properties , CassandraDriverOptions options ) {
210+ private void mapRequestOptions (CassandraDriverOptions options ) {
197211 PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
198- Request requestProperties = properties .getRequest ();
212+ Request requestProperties = this . properties .getRequest ();
199213 map .from (requestProperties ::getTimeout )
200214 .asInt (Duration ::toMillis )
201215 .to (((timeout ) -> options .add (DefaultDriverOption .REQUEST_TIMEOUT , timeout )));
@@ -222,40 +236,19 @@ private void mapRequestOptions(CassandraProperties properties, CassandraDriverOp
222236 .to ((drainInterval ) -> options .add (DefaultDriverOption .REQUEST_THROTTLER_DRAIN_INTERVAL , drainInterval ));
223237 }
224238
225- private void mapControlConnectionOptions (CassandraProperties properties , CassandraDriverOptions options ) {
239+ private void mapControlConnectionOptions (CassandraDriverOptions options ) {
226240 PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
227- Controlconnection controlProperties = properties .getControlconnection ();
241+ Controlconnection controlProperties = this . properties .getControlconnection ();
228242 map .from (controlProperties ::getTimeout )
229243 .asInt (Duration ::toMillis )
230244 .to ((timeout ) -> options .add (DefaultDriverOption .CONTROL_CONNECTION_TIMEOUT , timeout ));
231245 }
232246
233- private List <String > mapContactPoints (CassandraProperties properties ) {
234- if (properties .getContactPoints () != null ) {
235- return properties .getContactPoints ()
236- .stream ()
237- .map ((candidate ) -> formatContactPoint (candidate , properties .getPort ()))
238- .toList ();
239- }
240- return null ;
241- }
242-
243- private String formatContactPoint (String candidate , int port ) {
244- int i = candidate .lastIndexOf (':' );
245- if (i == -1 || !isPort (() -> candidate .substring (i + 1 ))) {
246- return String .format ("%s:%s" , candidate , port );
247- }
248- return candidate ;
249- }
250-
251- private boolean isPort (Supplier <String > value ) {
252- try {
253- int i = Integer .parseInt (value .get ());
254- return i > 0 && i < 65535 ;
255- }
256- catch (Exception ex ) {
257- return false ;
258- }
247+ private List <String > mapContactPoints () {
248+ return this .connectionDetails .getContactPoints ()
249+ .stream ()
250+ .map ((node ) -> node .host () + ":" + node .port ())
251+ .toList ();
259252 }
260253
261254 private static class CassandraDriverOptions {
@@ -293,4 +286,61 @@ private static String createKeyFor(DriverOption option) {
293286
294287 }
295288
289+ /**
290+ * Adapts {@link CassandraProperties} to {@link CassandraConnectionDetails}.
291+ */
292+ private static final class PropertiesCassandraConnectionDetails implements CassandraConnectionDetails {
293+
294+ private final CassandraProperties properties ;
295+
296+ private PropertiesCassandraConnectionDetails (CassandraProperties properties ) {
297+ this .properties = properties ;
298+ }
299+
300+ @ Override
301+ public List <Node > getContactPoints () {
302+ List <String > contactPoints = this .properties .getContactPoints ();
303+ return (contactPoints != null ) ? contactPoints .stream ().map (this ::asNode ).toList ()
304+ : Collections .emptyList ();
305+ }
306+
307+ @ Override
308+ public String getUsername () {
309+ return this .properties .getUsername ();
310+ }
311+
312+ @ Override
313+ public String getPassword () {
314+ return this .properties .getPassword ();
315+ }
316+
317+ @ Override
318+ public String getLocalDatacenter () {
319+ return this .properties .getLocalDatacenter ();
320+ }
321+
322+ private Node asNode (String contactPoint ) {
323+ int i = contactPoint .lastIndexOf (':' );
324+ if (i >= 0 ) {
325+ String portCandidate = contactPoint .substring (i + 1 );
326+ Integer port = asPort (portCandidate );
327+ if (port != null ) {
328+ return new Node (contactPoint .substring (0 , i ), port );
329+ }
330+ }
331+ return new Node (contactPoint , this .properties .getPort ());
332+ }
333+
334+ private Integer asPort (String value ) {
335+ try {
336+ int i = Integer .parseInt (value );
337+ return (i > 0 && i < 65535 ) ? i : null ;
338+ }
339+ catch (Exception ex ) {
340+ return null ;
341+ }
342+ }
343+
344+ }
345+
296346}
0 commit comments