Skip to content

Commit 21306c2

Browse files
author
Zhen Li
authored
Merge pull request #236 from zhenlineo/1.0-coredge
Better error message when running statements against incompatible server
2 parents 30391d3 + ac61e9d commit 21306c2

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

driver/src/main/java/org/neo4j/driver/internal/pool/PooledConnection.java

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@
2525
import org.neo4j.driver.internal.util.Clock;
2626
import org.neo4j.driver.internal.util.Consumer;
2727
import org.neo4j.driver.v1.Value;
28+
import org.neo4j.driver.v1.exceptions.ClientException;
2829
import org.neo4j.driver.v1.exceptions.Neo4jException;
30+
31+
import static java.lang.String.format;
32+
2933
/**
3034
* The state of a pooledConnection from a pool point of view could be one of the following:
3135
* Created,
@@ -91,7 +95,7 @@ public void run( String statement, Map<String,Value> parameters,
9195
{
9296
delegate.run( statement, parameters, collector );
9397
}
94-
catch(RuntimeException e)
98+
catch( RuntimeException e )
9599
{
96100
onDelegateException( e );
97101
}
@@ -104,7 +108,7 @@ public void discardAll()
104108
{
105109
delegate.discardAll();
106110
}
107-
catch(RuntimeException e)
111+
catch( RuntimeException e )
108112
{
109113
onDelegateException( e );
110114
}
@@ -117,7 +121,7 @@ public void pullAll( StreamCollector collector )
117121
{
118122
delegate.pullAll( collector );
119123
}
120-
catch(RuntimeException e)
124+
catch( RuntimeException e )
121125
{
122126
onDelegateException( e );
123127
}
@@ -224,9 +228,18 @@ public void dispose()
224228
*/
225229
private void onDelegateException( RuntimeException e )
226230
{
227-
if ( !isClientOrTransientError( e ) || isProtocolViolationError( e ) )
231+
if ( isUnrecoverableErrorsOccurred( e ) )
228232
{
229233
unrecoverableErrorsOccurred = true;
234+
if( isClusterError( e ) )
235+
{
236+
e = new ClientException( format(
237+
"Failed to run a statement on a 3.1+ Neo4j core-edge cluster server. %n" +
238+
"Please retry the statement if you have defined your own routing strategy to route driver messages to the cluster. " +
239+
"Note: 1.0 java driver does not support routing statements to a 3.1+ Neo4j core edge cluster. " +
240+
"Please upgrade to 1.1 driver and use `bolt+routing` scheme to route and run statements " +
241+
"directly to a 3.1+ core edge cluster." ), e );
242+
}
230243
}
231244
else
232245
{
@@ -245,18 +258,27 @@ public void onError( Runnable runnable )
245258
this.onError = runnable;
246259
}
247260

248-
private boolean isProtocolViolationError(RuntimeException e )
261+
private boolean isUnrecoverableErrorsOccurred( RuntimeException e )
249262
{
250-
return e instanceof Neo4jException
251-
&& ((Neo4jException) e).neo4jErrorCode().startsWith( "Neo.ClientError.Request" );
263+
return !isClientOrTransientError( e ) || isProtocolViolationError( e ) || isClusterError( e );
264+
}
265+
266+
private boolean isProtocolViolationError( RuntimeException e )
267+
{
268+
return ( e instanceof Neo4jException ) &&
269+
( ( Neo4jException ) e ).neo4jErrorCode().startsWith( "Neo.ClientError.Request" );
252270
}
253271

254272
private boolean isClientOrTransientError( RuntimeException e )
255273
{
256274
// Eg: DatabaseErrors and unknown (no status code or not neo4j exception) cause session to be discarded
257-
return e instanceof Neo4jException
258-
&& (((Neo4jException) e).neo4jErrorCode().contains( "ClientError" )
259-
|| ((Neo4jException) e).neo4jErrorCode().contains( "TransientError" ));
275+
return ( e instanceof Neo4jException ) && ( ( Neo4jException ) e ).neo4jErrorCode().contains( "ClientError" )
276+
|| ( e instanceof Neo4jException ) && ( ( Neo4jException ) e ).neo4jErrorCode().contains( "TransientError" );
277+
}
278+
279+
private boolean isClusterError( RuntimeException e )
280+
{
281+
return ( e instanceof Neo4jException ) && ( ( Neo4jException ) e ).neo4jErrorCode().contains( "Cluster" );
260282
}
261283

262284
public long idleTime()

driver/src/test/java/org/neo4j/driver/internal/pool/ConnectionInvalidationTest.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.neo4j.driver.v1.exceptions.Neo4jException;
3737
import org.neo4j.driver.v1.exceptions.TransientException;
3838

39+
import static java.lang.String.format;
3940
import static junit.framework.TestCase.assertFalse;
4041
import static org.hamcrest.CoreMatchers.equalTo;
4142
import static org.hamcrest.MatcherAssert.assertThat;
@@ -124,6 +125,29 @@ public void shouldInvalidateOnUnrecoverableProblems() throws Throwable
124125
assertUnrecoverable( new ClientException( "Hello, world!" ) );
125126
}
126127

128+
@Test
129+
public void shouldInvalidateOnUnrecoverableClusterErrors() throws Throwable
130+
{
131+
// Given
132+
String clientErrorMessage = format( "Failed to run a statement on a 3.1+ Neo4j core-edge cluster server. %n" +
133+
"Please retry the statement if you have defined your own routing strategy to route driver messages to the cluster. " +
134+
"Note: 1.0 java driver does not support routing statements to a 3.1+ Neo4j core edge cluster. " +
135+
"Please upgrade to 1.1 driver and use `bolt+routing` scheme to route and run statements " +
136+
"directly to a 3.1+ core edge cluster." );
137+
ClientException serverException = new ClientException( "Neo.ClientError.Cluster.NotALeader", "Hello, world!" );
138+
ClientException clientException = new ClientException( clientErrorMessage, serverException );
139+
140+
// When/Then
141+
assertUnrecoverable( serverException, clientException );
142+
143+
// Given
144+
serverException = new ClientException( "Neo.TransientError.Cluster.NoLeaderAvailable", "Hello, world" );
145+
clientException = new ClientException( clientErrorMessage, serverException );
146+
147+
// When/Then
148+
assertUnrecoverable( serverException, clientException );
149+
}
150+
127151
@Test
128152
public void shouldNotInvalidateOnKnownRecoverableExceptions() throws Throwable
129153
{
@@ -138,8 +162,13 @@ public void shouldInvalidateOnProtocolViolationExceptions() throws Throwable
138162
assertUnrecoverable( new ClientException( "Neo.ClientError.Request.Invalid", "Hello, world!" ) );
139163
}
140164

141-
@SuppressWarnings( "unchecked" )
142165
private void assertUnrecoverable( Neo4jException exception )
166+
{
167+
assertUnrecoverable( exception, exception );
168+
}
169+
170+
@SuppressWarnings( "unchecked" )
171+
private void assertUnrecoverable( Neo4jException exception, Neo4jException expectingException )
143172
{
144173
doThrow( exception ).when( delegate )
145174
.run( eq("assert unrecoverable"), anyMap(), any( StreamCollector.class ) );
@@ -152,7 +181,8 @@ private void assertUnrecoverable( Neo4jException exception )
152181
}
153182
catch ( Neo4jException e )
154183
{
155-
assertThat( e, equalTo( exception ) );
184+
assertThat( e.getMessage(), equalTo( expectingException.getMessage() ) );
185+
assertThat( e.getCause(), equalTo( expectingException.getCause() ) );
156186
}
157187

158188
// Then

0 commit comments

Comments
 (0)