Skip to content

Commit 3f0c9a1

Browse files
GH-2367 - Remove AutoCloseableQueryRunner proxy.
Closes #2367, delegating is the nicer choice for all driver versions.
1 parent 7888333 commit 3f0c9a1

File tree

2 files changed

+61
-39
lines changed

2 files changed

+61
-39
lines changed

src/main/java/org/springframework/data/neo4j/core/DefaultNeo4jClient.java

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@
1515
*/
1616
package org.springframework.data.neo4j.core;
1717

18-
import java.lang.reflect.InvocationHandler;
19-
import java.lang.reflect.InvocationTargetException;
20-
import java.lang.reflect.Method;
21-
import java.lang.reflect.Proxy;
2218
import java.util.Collection;
2319
import java.util.Map;
2420
import java.util.Optional;
@@ -28,10 +24,12 @@
2824
import java.util.stream.Collectors;
2925

3026
import org.neo4j.driver.Driver;
27+
import org.neo4j.driver.Query;
3128
import org.neo4j.driver.QueryRunner;
3229
import org.neo4j.driver.Record;
3330
import org.neo4j.driver.Result;
3431
import org.neo4j.driver.Session;
32+
import org.neo4j.driver.Value;
3533
import org.neo4j.driver.summary.ResultSummary;
3634
import org.neo4j.driver.types.TypeSystem;
3735
import org.springframework.core.convert.ConversionService;
@@ -71,50 +69,57 @@ class DefaultNeo4jClient implements Neo4jClient {
7169
new Neo4jConversions().registerConvertersIn((ConverterRegistry) conversionService);
7270
}
7371

74-
AutoCloseableQueryRunner getQueryRunner(@Nullable final String targetDatabase) {
72+
QueryRunner getQueryRunner(@Nullable final String targetDatabase) {
7573

7674
QueryRunner queryRunner = Neo4jTransactionManager.retrieveTransaction(driver, targetDatabase);
7775
if (queryRunner == null) {
7876
queryRunner = driver.session(Neo4jTransactionUtils.defaultSessionConfig(targetDatabase));
7977
}
8078

81-
return (AutoCloseableQueryRunner) Proxy.newProxyInstance(this.getClass().getClassLoader(),
82-
new Class<?>[] { AutoCloseableQueryRunner.class }, new AutoCloseableQueryRunnerHandler(queryRunner));
79+
return new DelegatingQueryRunner(queryRunner);
8380
}
8481

85-
/**
86-
* Makes a query runner automatically closeable and aware whether it's session or a transaction
87-
*/
88-
interface AutoCloseableQueryRunner extends QueryRunner, AutoCloseable {
82+
private static class DelegatingQueryRunner implements QueryRunner {
83+
84+
private final QueryRunner delegate;
85+
86+
private DelegatingQueryRunner(QueryRunner delegate) {
87+
this.delegate = delegate;
88+
}
8989

9090
@Override
91-
void close();
92-
}
91+
public void close() throws Exception {
9392

94-
static class AutoCloseableQueryRunnerHandler implements InvocationHandler {
93+
// We're only going to close sessions we have acquired inside the client, not something that
94+
// has been retrieved from the tx manager.
95+
if (this.delegate instanceof Session) {
96+
this.delegate.close();
97+
}
98+
}
9599

96-
private final QueryRunner target;
100+
@Override
101+
public Result run(String s, Value value) {
102+
return delegate.run(s, value);
103+
}
97104

98-
AutoCloseableQueryRunnerHandler(QueryRunner target) {
99-
this.target = target;
105+
@Override
106+
public Result run(String s, Map<String, Object> map) {
107+
return delegate.run(s, map);
100108
}
101109

102-
@Nullable
103110
@Override
104-
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
111+
public Result run(String s, Record record) {
112+
return delegate.run(s, record);
113+
}
105114

106-
if ("close".equals(method.getName())) {
107-
if (this.target instanceof Session) {
108-
((Session) this.target).close();
109-
}
110-
return null;
111-
} else {
112-
try {
113-
return method.invoke(target, args);
114-
} catch (InvocationTargetException ite) {
115-
throw ite.getCause();
116-
}
117-
}
115+
@Override
116+
public Result run(String s) {
117+
return delegate.run(s);
118+
}
119+
120+
@Override
121+
public Result run(Query query) {
122+
return delegate.run(query);
118123
}
119124
}
120125

@@ -159,7 +164,7 @@ static class RunnableStatement {
159164

160165
private final NamedParameters parameters;
161166

162-
protected final Result runWith(AutoCloseableQueryRunner statementRunner) {
167+
protected final Result runWith(QueryRunner statementRunner) {
163168
String statementTemplate = cypherSupplier.get();
164169

165170
if (cypherLog.isDebugEnabled()) {
@@ -257,11 +262,13 @@ public RecordFetchSpec<Map<String, Object>> fetch() {
257262
@Override
258263
public ResultSummary run() {
259264

260-
try (AutoCloseableQueryRunner statementRunner = getQueryRunner(this.targetDatabase)) {
265+
try (QueryRunner statementRunner = getQueryRunner(this.targetDatabase)) {
261266
Result result = runnableStatement.runWith(statementRunner);
262267
return ResultSummaries.process(result.consume());
263268
} catch (RuntimeException e) {
264269
throw potentiallyConvertRuntimeException(e, persistenceExceptionTranslator);
270+
} catch (Exception e) {
271+
throw new RuntimeException(e);
265272
}
266273
}
267274

@@ -306,7 +313,7 @@ public RecordFetchSpec<T> mappedBy(
306313
@Override
307314
public Optional<T> one() {
308315

309-
try (AutoCloseableQueryRunner statementRunner = getQueryRunner(this.targetDatabase)) {
316+
try (QueryRunner statementRunner = getQueryRunner(this.targetDatabase)) {
310317
Result result = runnableStatement.runWith(statementRunner);
311318
Optional<T> optionalValue = result.hasNext() ?
312319
Optional.ofNullable(mappingFunction.apply(typeSystem, result.single())) :
@@ -315,32 +322,38 @@ public Optional<T> one() {
315322
return optionalValue;
316323
} catch (RuntimeException e) {
317324
throw potentiallyConvertRuntimeException(e, persistenceExceptionTranslator);
325+
} catch (Exception e) {
326+
throw new RuntimeException(e);
318327
}
319328
}
320329

321330
@Override
322331
public Optional<T> first() {
323332

324-
try (AutoCloseableQueryRunner statementRunner = getQueryRunner(this.targetDatabase)) {
333+
try (QueryRunner statementRunner = getQueryRunner(this.targetDatabase)) {
325334
Result result = runnableStatement.runWith(statementRunner);
326335
Optional<T> optionalValue = result.stream().map(partialMappingFunction(typeSystem)).findFirst();
327336
ResultSummaries.process(result.consume());
328337
return optionalValue;
329338
} catch (RuntimeException e) {
330339
throw potentiallyConvertRuntimeException(e, persistenceExceptionTranslator);
340+
} catch (Exception e) {
341+
throw new RuntimeException(e);
331342
}
332343
}
333344

334345
@Override
335346
public Collection<T> all() {
336347

337-
try (AutoCloseableQueryRunner statementRunner = getQueryRunner(this.targetDatabase)) {
348+
try (QueryRunner statementRunner = getQueryRunner(this.targetDatabase)) {
338349
Result result = runnableStatement.runWith(statementRunner);
339350
Collection<T> values = result.stream().map(partialMappingFunction(typeSystem)).collect(Collectors.toList());
340351
ResultSummaries.process(result.consume());
341352
return values;
342353
} catch (RuntimeException e) {
343354
throw potentiallyConvertRuntimeException(e, persistenceExceptionTranslator);
355+
} catch (Exception e) {
356+
throw new RuntimeException(e);
344357
}
345358
}
346359

@@ -377,8 +390,12 @@ public RunnableDelegation<T> in(@Nullable @SuppressWarnings("HiddenField") Strin
377390

378391
@Override
379392
public Optional<T> run() {
380-
try (AutoCloseableQueryRunner queryRunner = getQueryRunner(targetDatabase)) {
393+
try (QueryRunner queryRunner = getQueryRunner(targetDatabase)) {
381394
return callback.apply(queryRunner);
395+
} catch (RuntimeException e) {
396+
throw potentiallyConvertRuntimeException(e, persistenceExceptionTranslator);
397+
} catch (Exception e) {
398+
throw new RuntimeException(e);
382399
}
383400
}
384401
}

src/test/java/org/springframework/data/neo4j/core/TransactionHandlingTest.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.mockito.Mock;
4040
import org.mockito.junit.jupiter.MockitoExtension;
4141
import org.neo4j.driver.Driver;
42+
import org.neo4j.driver.QueryRunner;
4243
import org.neo4j.driver.Session;
4344
import org.neo4j.driver.SessionConfig;
4445
import org.neo4j.driver.Transaction;
@@ -92,8 +93,10 @@ void shouldCallCloseOnSession() {
9293

9394
// Make template acquire session
9495
DefaultNeo4jClient neo4jClient = new DefaultNeo4jClient(driver, null);
95-
try (DefaultNeo4jClient.AutoCloseableQueryRunner s = neo4jClient.getQueryRunner("aDatabase")) {
96+
try (QueryRunner s = neo4jClient.getQueryRunner("aDatabase")) {
9697
s.run("MATCH (n) RETURN n");
98+
} catch (Exception e) {
99+
throw new RuntimeException(e);
97100
}
98101

99102
verify(driver).session(configArgumentCaptor.capture());
@@ -126,8 +129,10 @@ void shouldNotInvokeCloseOnTransaction() {
126129

127130
DefaultNeo4jClient neo4jClient = new DefaultNeo4jClient(driver, null);
128131
txTemplate.execute(tx -> {
129-
try (DefaultNeo4jClient.AutoCloseableQueryRunner s = neo4jClient.getQueryRunner(null)) {
132+
try (QueryRunner s = neo4jClient.getQueryRunner(null)) {
130133
s.run("MATCH (n) RETURN n");
134+
} catch (Exception e) {
135+
throw new RuntimeException(e);
131136
}
132137
return null;
133138
});

0 commit comments

Comments
 (0)