23
23
import java .util .LinkedHashMap ;
24
24
import java .util .List ;
25
25
import java .util .Map ;
26
- import java .util .function .Supplier ;
27
26
28
27
import javax .net .ssl .SSLContext ;
29
28
64
63
* @author Stephane Nicoll
65
64
* @author Steffen F. Qvistgaard
66
65
* @author Ittay Stern
66
+ * @author Moritz Halbritter
67
+ * @author Andy Wilkinson
68
+ * @author Phillip Webb
67
69
* @since 1.3.0
68
70
*/
69
71
@ AutoConfiguration
70
- @ ConditionalOnClass ({ CqlSession .class } )
72
+ @ ConditionalOnClass (CqlSession .class )
71
73
@ EnableConfigurationProperties (CassandraProperties .class )
72
74
public class CassandraAutoConfiguration {
73
75
@@ -80,6 +82,17 @@ public class CassandraAutoConfiguration {
80
82
SPRING_BOOT_DEFAULTS = options .build ();
81
83
}
82
84
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
+
83
96
@ Bean
84
97
@ ConditionalOnMissingBean
85
98
@ Lazy
@@ -90,24 +103,25 @@ public CqlSession cassandraSession(CqlSessionBuilder cqlSessionBuilder) {
90
103
@ Bean
91
104
@ ConditionalOnMissingBean
92
105
@ Scope ("prototype" )
93
- public CqlSessionBuilder cassandraSessionBuilder (CassandraProperties properties ,
94
- DriverConfigLoader driverConfigLoader , ObjectProvider <CqlSessionBuilderCustomizer > builderCustomizers ) {
106
+ public CqlSessionBuilder cassandraSessionBuilder (DriverConfigLoader driverConfigLoader ,
107
+ ObjectProvider <CqlSessionBuilderCustomizer > builderCustomizers ) {
95
108
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 ());
99
112
builderCustomizers .orderedStream ().forEach ((customizer ) -> customizer .customize (builder ));
100
113
return builder ;
101
114
}
102
115
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 ());
106
120
}
107
121
}
108
122
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 ()) {
111
125
try {
112
126
builder .withSslContext (SSLContext .getDefault ());
113
127
}
@@ -119,20 +133,20 @@ private void configureSsl(CassandraProperties properties, CqlSessionBuilder buil
119
133
120
134
@ Bean (destroyMethod = "" )
121
135
@ ConditionalOnMissingBean
122
- public DriverConfigLoader cassandraDriverConfigLoader (CassandraProperties properties ,
136
+ public DriverConfigLoader cassandraDriverConfigLoader (
123
137
ObjectProvider <DriverConfigLoaderBuilderCustomizer > builderCustomizers ) {
124
138
ProgrammaticDriverConfigLoaderBuilder builder = new DefaultProgrammaticDriverConfigLoaderBuilder (
125
- () -> cassandraConfiguration (properties ), DefaultDriverConfigLoader .DEFAULT_ROOT_PATH );
139
+ () -> cassandraConfiguration (), DefaultDriverConfigLoader .DEFAULT_ROOT_PATH );
126
140
builderCustomizers .orderedStream ().forEach ((customizer ) -> customizer .customize (builder ));
127
141
return builder .build ();
128
142
}
129
143
130
- private Config cassandraConfiguration (CassandraProperties properties ) {
144
+ private Config cassandraConfiguration () {
131
145
ConfigFactory .invalidateCaches ();
132
146
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 ()));
136
150
}
137
151
config = config .withFallback (SPRING_BOOT_DEFAULTS );
138
152
config = config .withFallback (ConfigFactory .defaultReference ());
@@ -148,32 +162,32 @@ private Config loadConfig(Resource resource) {
148
162
}
149
163
}
150
164
151
- private Config mapConfig (CassandraProperties properties ) {
165
+ private Config mapConfig () {
152
166
CassandraDriverOptions options = new CassandraDriverOptions ();
153
167
PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
154
- map .from (properties .getSessionName ())
168
+ map .from (this . properties .getSessionName ())
155
169
.whenHasText ()
156
170
.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 )
161
175
.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 ())
167
181
.to ((contactPoints ) -> options .add (DefaultDriverOption .CONTACT_POINTS , contactPoints ));
168
- map .from (properties .getLocalDatacenter ())
182
+ map .from (this . connectionDetails .getLocalDatacenter ())
169
183
.whenHasText ()
170
184
.to ((localDatacenter ) -> options .add (DefaultDriverOption .LOAD_BALANCING_LOCAL_DATACENTER , localDatacenter ));
171
185
return options .build ();
172
186
}
173
187
174
- private void mapConnectionOptions (CassandraProperties properties , CassandraDriverOptions options ) {
188
+ private void mapConnectionOptions (CassandraDriverOptions options ) {
175
189
PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
176
- Connection connectionProperties = properties .getConnection ();
190
+ Connection connectionProperties = this . properties .getConnection ();
177
191
map .from (connectionProperties ::getConnectTimeout )
178
192
.asInt (Duration ::toMillis )
179
193
.to ((connectTimeout ) -> options .add (DefaultDriverOption .CONNECTION_CONNECT_TIMEOUT , connectTimeout ));
@@ -182,9 +196,9 @@ private void mapConnectionOptions(CassandraProperties properties, CassandraDrive
182
196
.to ((initQueryTimeout ) -> options .add (DefaultDriverOption .CONNECTION_INIT_QUERY_TIMEOUT , initQueryTimeout ));
183
197
}
184
198
185
- private void mapPoolingOptions (CassandraProperties properties , CassandraDriverOptions options ) {
199
+ private void mapPoolingOptions (CassandraDriverOptions options ) {
186
200
PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
187
- CassandraProperties .Pool poolProperties = properties .getPool ();
201
+ CassandraProperties .Pool poolProperties = this . properties .getPool ();
188
202
map .from (poolProperties ::getIdleTimeout )
189
203
.asInt (Duration ::toMillis )
190
204
.to ((idleTimeout ) -> options .add (DefaultDriverOption .HEARTBEAT_TIMEOUT , idleTimeout ));
@@ -193,9 +207,9 @@ private void mapPoolingOptions(CassandraProperties properties, CassandraDriverOp
193
207
.to ((heartBeatInterval ) -> options .add (DefaultDriverOption .HEARTBEAT_INTERVAL , heartBeatInterval ));
194
208
}
195
209
196
- private void mapRequestOptions (CassandraProperties properties , CassandraDriverOptions options ) {
210
+ private void mapRequestOptions (CassandraDriverOptions options ) {
197
211
PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
198
- Request requestProperties = properties .getRequest ();
212
+ Request requestProperties = this . properties .getRequest ();
199
213
map .from (requestProperties ::getTimeout )
200
214
.asInt (Duration ::toMillis )
201
215
.to (((timeout ) -> options .add (DefaultDriverOption .REQUEST_TIMEOUT , timeout )));
@@ -222,40 +236,19 @@ private void mapRequestOptions(CassandraProperties properties, CassandraDriverOp
222
236
.to ((drainInterval ) -> options .add (DefaultDriverOption .REQUEST_THROTTLER_DRAIN_INTERVAL , drainInterval ));
223
237
}
224
238
225
- private void mapControlConnectionOptions (CassandraProperties properties , CassandraDriverOptions options ) {
239
+ private void mapControlConnectionOptions (CassandraDriverOptions options ) {
226
240
PropertyMapper map = PropertyMapper .get ().alwaysApplyingWhenNonNull ();
227
- Controlconnection controlProperties = properties .getControlconnection ();
241
+ Controlconnection controlProperties = this . properties .getControlconnection ();
228
242
map .from (controlProperties ::getTimeout )
229
243
.asInt (Duration ::toMillis )
230
244
.to ((timeout ) -> options .add (DefaultDriverOption .CONTROL_CONNECTION_TIMEOUT , timeout ));
231
245
}
232
246
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 ();
259
252
}
260
253
261
254
private static class CassandraDriverOptions {
@@ -293,4 +286,61 @@ private static String createKeyFor(DriverOption option) {
293
286
294
287
}
295
288
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
+
296
346
}
0 commit comments