Skip to content

Commit c21d58b

Browse files
committed
Update internal Bolt exception structure
The main goal if this update is to refactor internal Bolt exception handling and to separate it from the user facing exceptions.
1 parent c84ca38 commit c21d58b

File tree

102 files changed

+2442
-914
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+2442
-914
lines changed

driver/src/main/java/org/neo4j/driver/exceptions/Neo4jException.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ public Optional<Neo4jException> gqlCause() {
238238
return findFirstGqlCause(this, Neo4jException.class);
239239
}
240240

241+
@SuppressWarnings("DuplicatedCode")
241242
private static <T extends Throwable> Optional<T> findFirstGqlCause(Throwable throwable, Class<T> targetCls) {
242243
var cause = throwable.getCause();
243244
if (cause == null) {

driver/src/main/java/org/neo4j/driver/exceptions/SecurityRetryableException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* Indicates that the contained {@link SecurityException} is a {@link RetryableException}, which is determined by the
2626
* {@link org.neo4j.driver.AuthTokenManager#handleSecurityException(AuthToken, SecurityException)} method.
2727
* <p>
28-
* The original {@link java.lang.SecurityException} is always available as a {@link Throwable#getCause()}. The
28+
* The original {@link SecurityException} is always available as a {@link Throwable#getCause()}. The
2929
* {@link SecurityRetryableException#code()} and {@link SecurityRetryableException#getMessage()} supply the values from
3030
* the original exception.
3131
*

driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
import org.neo4j.driver.Driver;
4040
import org.neo4j.driver.Logging;
4141
import org.neo4j.driver.MetricsAdapter;
42+
import org.neo4j.driver.internal.adaptedbolt.AdaptingDriverBoltConnectionProvider;
43+
import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider;
44+
import org.neo4j.driver.internal.adaptedbolt.ErrorMapper;
4245
import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider;
4346
import org.neo4j.driver.internal.bolt.api.BoltServerAddress;
4447
import org.neo4j.driver.internal.bolt.api.DefaultDomainNameResolver;
@@ -158,7 +161,7 @@ private InternalDriver createDriver(
158161
AuthTokenManager authTokenManager,
159162
boolean ownsEventLoopGroup,
160163
Supplier<Rediscovery> rediscoverySupplier) {
161-
BoltConnectionProvider boltConnectionProvider = null;
164+
DriverBoltConnectionProvider boltConnectionProvider = null;
162165
try {
163166
boltConnectionProvider =
164167
createBoltConnectionProvider(uri, config, eventLoopGroup, routingSettings, rediscoverySupplier);
@@ -204,28 +207,33 @@ private Function<BoltServerAddress, Set<BoltServerAddress>> createBoltServerAddr
204207
.collect(Collectors.toCollection(LinkedHashSet::new));
205208
}
206209

207-
private BoltConnectionProvider createBoltConnectionProvider(
210+
private DriverBoltConnectionProvider createBoltConnectionProvider(
208211
URI uri,
209212
Config config,
210213
EventLoopGroup eventLoopGroup,
211214
RoutingSettings routingSettings,
212215
Supplier<Rediscovery> rediscoverySupplier) {
213-
BoltConnectionProvider boltConnectionProvider;
216+
DriverBoltConnectionProvider boltConnectionProvider;
214217
var clock = createClock();
215218
var loggingProvider = new BoltLoggingProvider(config.logging());
216219
Supplier<BoltConnectionProvider> pooledBoltConnectionProviderSupplier =
217220
() -> createPooledBoltConnectionProvider(config, eventLoopGroup, clock, loggingProvider);
221+
var errorMapper = ErrorMapper.getInstance();
218222
if (uri.getScheme().startsWith("bolt")) {
219223
assertNoRoutingContext(uri, routingSettings);
220-
boltConnectionProvider = pooledBoltConnectionProviderSupplier.get();
224+
boltConnectionProvider = new AdaptingDriverBoltConnectionProvider(
225+
pooledBoltConnectionProviderSupplier.get(), errorMapper, false);
221226
} else {
222-
boltConnectionProvider = createRoutedBoltConnectionProvider(
223-
config,
224-
pooledBoltConnectionProviderSupplier,
225-
routingSettings,
226-
rediscoverySupplier,
227-
clock,
228-
loggingProvider);
227+
boltConnectionProvider = new AdaptingDriverBoltConnectionProvider(
228+
createRoutedBoltConnectionProvider(
229+
config,
230+
pooledBoltConnectionProviderSupplier,
231+
routingSettings,
232+
rediscoverySupplier,
233+
clock,
234+
loggingProvider),
235+
errorMapper,
236+
true);
229237
}
230238
return boltConnectionProvider;
231239
}
@@ -308,7 +316,7 @@ protected Clock createClock() {
308316
*/
309317
protected SessionFactory createSessionFactory(
310318
BoltSecurityPlanManager securityPlanManager,
311-
BoltConnectionProvider connectionProvider,
319+
DriverBoltConnectionProvider connectionProvider,
312320
RetryLogic retryLogic,
313321
Config config,
314322
AuthTokenManager authTokenManager) {

driver/src/main/java/org/neo4j/driver/internal/InternalResult.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@
2828
import org.neo4j.driver.async.ResultCursor;
2929
import org.neo4j.driver.exceptions.ClientException;
3030
import org.neo4j.driver.exceptions.NoSuchRecordException;
31-
import org.neo4j.driver.internal.bolt.api.BoltConnection;
31+
import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection;
3232
import org.neo4j.driver.internal.bolt.api.GqlStatusError;
3333
import org.neo4j.driver.internal.util.Futures;
3434
import org.neo4j.driver.summary.ResultSummary;
3535

3636
public class InternalResult implements Result {
37-
private final BoltConnection connection;
37+
private final DriverBoltConnection connection;
3838
private final ResultCursor cursor;
3939

40-
public InternalResult(BoltConnection connection, ResultCursor cursor) {
40+
public InternalResult(DriverBoltConnection connection, ResultCursor cursor) {
4141
this.connection = connection;
4242
this.cursor = cursor;
4343
}

driver/src/main/java/org/neo4j/driver/internal/InternalSession.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
import org.neo4j.driver.TransactionConfig;
3131
import org.neo4j.driver.TransactionWork;
3232
import org.neo4j.driver.exceptions.ClientException;
33+
import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection;
3334
import org.neo4j.driver.internal.async.NetworkSession;
34-
import org.neo4j.driver.internal.bolt.api.BoltConnection;
3535
import org.neo4j.driver.internal.bolt.api.GqlStatusError;
3636
import org.neo4j.driver.internal.bolt.api.TelemetryApi;
3737
import org.neo4j.driver.internal.telemetry.ApiTelemetryWork;
@@ -208,7 +208,7 @@ private Transaction beginTransaction(
208208

209209
private void terminateConnectionOnThreadInterrupt(String reason) {
210210
// try to get current connection if it has been acquired
211-
BoltConnection connection = null;
211+
DriverBoltConnection connection = null;
212212
try {
213213
connection = Futures.getNow(session.connectionAsync());
214214
} catch (Throwable ignore) {

driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@
3333
import org.neo4j.driver.NotificationConfig;
3434
import org.neo4j.driver.SessionConfig;
3535
import org.neo4j.driver.Value;
36+
import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider;
3637
import org.neo4j.driver.internal.async.LeakLoggingNetworkSession;
3738
import org.neo4j.driver.internal.async.NetworkSession;
38-
import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider;
3939
import org.neo4j.driver.internal.bolt.api.DatabaseName;
4040
import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil;
4141
import org.neo4j.driver.internal.bolt.api.SecurityPlan;
@@ -45,7 +45,7 @@
4545

4646
public class SessionFactoryImpl implements SessionFactory {
4747
private final BoltSecurityPlanManager securityPlanManager;
48-
private final BoltConnectionProvider connectionProvider;
48+
private final DriverBoltConnectionProvider connectionProvider;
4949
private final RetryLogic retryLogic;
5050
private final Logging logging;
5151
private final boolean leakedSessionsLoggingEnabled;
@@ -54,7 +54,7 @@ public class SessionFactoryImpl implements SessionFactory {
5454

5555
SessionFactoryImpl(
5656
BoltSecurityPlanManager securityPlanManager,
57-
BoltConnectionProvider connectionProvider,
57+
DriverBoltConnectionProvider connectionProvider,
5858
RetryLogic retryLogic,
5959
Config config,
6060
AuthTokenManager authTokenManager) {
@@ -163,7 +163,7 @@ public CompletionStage<Boolean> supportsSessionAuth() {
163163

164164
private NetworkSession createSession(
165165
BoltSecurityPlanManager securityPlanManager,
166-
BoltConnectionProvider connectionProvider,
166+
DriverBoltConnectionProvider connectionProvider,
167167
RetryLogic retryLogic,
168168
DatabaseName databaseName,
169169
AccessMode mode,
@@ -214,7 +214,7 @@ private NetworkSession createSession(
214214
authTokenManager);
215215
}
216216

217-
public BoltConnectionProvider getConnectionProvider() {
217+
public DriverBoltConnectionProvider getConnectionProvider() {
218218
return connectionProvider;
219219
}
220220

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [https://neo4j.com]
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.neo4j.driver.internal.adaptedbolt;
18+
19+
import java.time.Duration;
20+
import java.util.Map;
21+
import java.util.Objects;
22+
import java.util.Set;
23+
import java.util.concurrent.CompletionStage;
24+
import org.neo4j.driver.Value;
25+
import org.neo4j.driver.internal.bolt.api.AccessMode;
26+
import org.neo4j.driver.internal.bolt.api.AuthData;
27+
import org.neo4j.driver.internal.bolt.api.BoltConnection;
28+
import org.neo4j.driver.internal.bolt.api.BoltConnectionState;
29+
import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion;
30+
import org.neo4j.driver.internal.bolt.api.BoltServerAddress;
31+
import org.neo4j.driver.internal.bolt.api.DatabaseName;
32+
import org.neo4j.driver.internal.bolt.api.NotificationConfig;
33+
import org.neo4j.driver.internal.bolt.api.TelemetryApi;
34+
import org.neo4j.driver.internal.bolt.api.TransactionType;
35+
36+
final class AdaptingDriverBoltConnection implements DriverBoltConnection {
37+
private final BoltConnection connection;
38+
private final ErrorMapper errorMapper;
39+
40+
AdaptingDriverBoltConnection(BoltConnection connection, ErrorMapper errorMapper) {
41+
this.connection = Objects.requireNonNull(connection);
42+
this.errorMapper = Objects.requireNonNull(errorMapper);
43+
}
44+
45+
@Override
46+
public CompletionStage<DriverBoltConnection> onLoop() {
47+
return connection.onLoop().exceptionally(errorMapper::mapAndTrow).thenApply(ignored -> this);
48+
}
49+
50+
@Override
51+
public CompletionStage<DriverBoltConnection> route(
52+
DatabaseName databaseName, String impersonatedUser, Set<String> bookmarks) {
53+
return connection
54+
.route(databaseName, impersonatedUser, bookmarks)
55+
.exceptionally(errorMapper::mapAndTrow)
56+
.thenApply(ignored -> this);
57+
}
58+
59+
@Override
60+
public CompletionStage<DriverBoltConnection> beginTransaction(
61+
DatabaseName databaseName,
62+
AccessMode accessMode,
63+
String impersonatedUser,
64+
Set<String> bookmarks,
65+
TransactionType transactionType,
66+
Duration txTimeout,
67+
Map<String, Value> txMetadata,
68+
String txType,
69+
NotificationConfig notificationConfig) {
70+
return connection
71+
.beginTransaction(
72+
databaseName,
73+
accessMode,
74+
impersonatedUser,
75+
bookmarks,
76+
transactionType,
77+
txTimeout,
78+
txMetadata,
79+
txType,
80+
notificationConfig)
81+
.exceptionally(errorMapper::mapAndTrow)
82+
.thenApply(ignored -> this);
83+
}
84+
85+
@Override
86+
public CompletionStage<DriverBoltConnection> runInAutoCommitTransaction(
87+
DatabaseName databaseName,
88+
AccessMode accessMode,
89+
String impersonatedUser,
90+
Set<String> bookmarks,
91+
String query,
92+
Map<String, Value> parameters,
93+
Duration txTimeout,
94+
Map<String, Value> txMetadata,
95+
NotificationConfig notificationConfig) {
96+
return connection
97+
.runInAutoCommitTransaction(
98+
databaseName,
99+
accessMode,
100+
impersonatedUser,
101+
bookmarks,
102+
query,
103+
parameters,
104+
txTimeout,
105+
txMetadata,
106+
notificationConfig)
107+
.exceptionally(errorMapper::mapAndTrow)
108+
.thenApply(ignored -> this);
109+
}
110+
111+
@Override
112+
public CompletionStage<DriverBoltConnection> run(String query, Map<String, Value> parameters) {
113+
return connection
114+
.run(query, parameters)
115+
.exceptionally(errorMapper::mapAndTrow)
116+
.thenApply(ignored -> this);
117+
}
118+
119+
@Override
120+
public CompletionStage<DriverBoltConnection> pull(long qid, long request) {
121+
return connection
122+
.pull(qid, request)
123+
.exceptionally(errorMapper::mapAndTrow)
124+
.thenApply(ignored -> this);
125+
}
126+
127+
@Override
128+
public CompletionStage<DriverBoltConnection> discard(long qid, long number) {
129+
return connection
130+
.discard(qid, number)
131+
.exceptionally(errorMapper::mapAndTrow)
132+
.thenApply(ignored -> this);
133+
}
134+
135+
@Override
136+
public CompletionStage<DriverBoltConnection> commit() {
137+
return connection.commit().exceptionally(errorMapper::mapAndTrow).thenApply(ignored -> this);
138+
}
139+
140+
@Override
141+
public CompletionStage<DriverBoltConnection> rollback() {
142+
return connection.rollback().exceptionally(errorMapper::mapAndTrow).thenApply(ignored -> this);
143+
}
144+
145+
@Override
146+
public CompletionStage<DriverBoltConnection> reset() {
147+
return connection.reset().exceptionally(errorMapper::mapAndTrow).thenApply(ignored -> this);
148+
}
149+
150+
@Override
151+
public CompletionStage<DriverBoltConnection> logoff() {
152+
return connection.logoff().exceptionally(errorMapper::mapAndTrow).thenApply(ignored -> this);
153+
}
154+
155+
@Override
156+
public CompletionStage<DriverBoltConnection> logon(Map<String, Value> authMap) {
157+
return connection.logon(authMap).exceptionally(errorMapper::mapAndTrow).thenApply(ignored -> this);
158+
}
159+
160+
@Override
161+
public CompletionStage<DriverBoltConnection> telemetry(TelemetryApi telemetryApi) {
162+
return connection
163+
.telemetry(telemetryApi)
164+
.exceptionally(errorMapper::mapAndTrow)
165+
.thenApply(ignored -> this);
166+
}
167+
168+
@Override
169+
public CompletionStage<DriverBoltConnection> clear() {
170+
return connection.clear().exceptionally(errorMapper::mapAndTrow).thenApply(ignored -> this);
171+
}
172+
173+
@Override
174+
public CompletionStage<Void> flush(DriverResponseHandler handler) {
175+
return connection
176+
.flush(new AdaptingDriverResponseHandler(handler, errorMapper))
177+
.exceptionally(errorMapper::mapAndTrow);
178+
}
179+
180+
@Override
181+
public CompletionStage<Void> forceClose(String reason) {
182+
return connection.forceClose(reason).exceptionally(errorMapper::mapAndTrow);
183+
}
184+
185+
@Override
186+
public CompletionStage<Void> close() {
187+
return connection.close().exceptionally(errorMapper::mapAndTrow);
188+
}
189+
190+
@Override
191+
public BoltConnectionState state() {
192+
return connection.state();
193+
}
194+
195+
@Override
196+
public CompletionStage<AuthData> authData() {
197+
return connection.authData().exceptionally(errorMapper::mapAndTrow);
198+
}
199+
200+
@Override
201+
public String serverAgent() {
202+
return connection.serverAgent();
203+
}
204+
205+
@Override
206+
public BoltServerAddress serverAddress() {
207+
return connection.serverAddress();
208+
}
209+
210+
@Override
211+
public BoltProtocolVersion protocolVersion() {
212+
return connection.protocolVersion();
213+
}
214+
215+
@Override
216+
public boolean telemetrySupported() {
217+
return connection.telemetrySupported();
218+
}
219+
}

0 commit comments

Comments
 (0)