45
45
import org .neo4j .driver .SessionConfig ;
46
46
import org .neo4j .driver .internal .util .ServerVersion ;
47
47
import org .springframework .core .log .LogMessage ;
48
+ import org .springframework .lang .Nullable ;
48
49
import org .testcontainers .containers .Neo4jContainer ;
49
50
import org .testcontainers .utility .TestcontainersConfiguration ;
50
51
@@ -118,7 +119,7 @@ public void beforeAll(ExtensionContext context) throws Exception {
118
119
}
119
120
120
121
@ Override
121
- public void beforeEach (ExtensionContext context ) throws Exception {
122
+ public void beforeEach (ExtensionContext context ) {
122
123
ExtensionContext .Store contextStore = context .getStore (NAMESPACE );
123
124
Neo4jConnectionSupport neo4jConnectionSupport = contextStore .get (KEY_DRIVER_INSTANCE , Neo4jConnectionSupport .class );
124
125
checkRequiredFeatures (neo4jConnectionSupport , context .getTags ());
@@ -173,16 +174,19 @@ public Neo4jConnectionSupport(String url, AuthToken authToken) {
173
174
}
174
175
175
176
/**
176
- * @return A possible shared driver instance, connected to either a database running inside test containers or
177
- * running locally.
177
+ * This method asserts that the current driver instance is usable before handing it out. If it isn't usable, it
178
+ * creates a new one.
179
+ *
180
+ * @return A shared driver instance, connected to either a database running inside test containers or
181
+ * running locally.
178
182
*/
179
183
public Driver getDriver () {
180
184
181
185
Driver driver = this .driverInstance ;
182
- if (driver == null ) {
186
+ if (! isUsable ( driver ) ) {
183
187
synchronized (this ) {
184
188
driver = this .driverInstance ;
185
- if (driver == null ) {
189
+ if (! isUsable ( driver ) ) {
186
190
this .driverInstance = GraphDatabase .driver (url , authToken , config );
187
191
driver = this .driverInstance ;
188
192
}
@@ -191,6 +195,30 @@ public Driver getDriver() {
191
195
return driver ;
192
196
}
193
197
198
+ /**
199
+ * A driver is usable if it's not null and can verify its connectivity. This method force closes
200
+ * the bean if the connectivity cannot be verified to avoid having a netty pool dangling around.
201
+ *
202
+ * @param driver The driver that should be checked for usability
203
+ * @return true if the driver is currently usable.
204
+ */
205
+ private static boolean isUsable (@ Nullable Driver driver ) {
206
+
207
+ if (driver == null ) {
208
+ return false ;
209
+ }
210
+ try {
211
+ driver .verifyConnectivity ();
212
+ return true ;
213
+ } catch (Exception ex ) {
214
+ try {
215
+ driver .close ();
216
+ } catch (Exception nested ) {
217
+ }
218
+ return false ;
219
+ }
220
+ }
221
+
194
222
ServerVersion getServerVersion () {
195
223
196
224
ServerVersion serverVersion = this .cachedServerVersion ;
@@ -238,7 +266,8 @@ public void close() {
238
266
try {
239
267
log .debug ("Closing Neo4j connection support." );
240
268
driverInstance .close ();
241
- } catch (Exception e ) {}
269
+ } catch (Exception e ) {
270
+ }
242
271
}
243
272
}
244
273
0 commit comments