Skip to content
This repository was archived by the owner on Jul 6, 2023. It is now read-only.

Commit ee310a0

Browse files
authored
Merge pull request #156 from sherfert/1.2-bolt-errors
Stop unwrapping Bolt exceptions.
2 parents 51d0b81 + f63bd8d commit ee310a0

File tree

7 files changed

+149
-67
lines changed

7 files changed

+149
-67
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ ext {
7272
argparse4jVersion = '0.7.0'
7373
junitVersion = '4.12'
7474
evaluatorVersion = '3.5.4'
75-
neo4jJavaDriverVersion = '2.0.0-alpha02'
75+
neo4jJavaDriverVersion = '2.0.0-alpha03'
7676
findbugsVersion = '3.0.0'
7777
jansiVersion = '1.13'
7878
jlineVersion = '2.14.6'
Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,136 @@
11
package org.neo4j.shell;
22

3+
import org.junit.Ignore;
4+
import org.junit.Rule;
35
import org.junit.Test;
4-
import org.neo4j.shell.cli.CliArgs;
5-
import org.neo4j.shell.log.AnsiLogger;
6-
import org.neo4j.shell.log.Logger;
7-
import org.neo4j.shell.prettyprint.PrettyConfig;
6+
import org.junit.rules.ExpectedException;
87

98
import java.io.ByteArrayInputStream;
109
import java.io.ByteArrayOutputStream;
1110
import java.io.InputStream;
1211
import java.io.PrintStream;
1312

13+
import org.neo4j.driver.exceptions.ServiceUnavailableException;
14+
import org.neo4j.shell.cli.CliArgs;
15+
import org.neo4j.shell.log.AnsiLogger;
16+
import org.neo4j.shell.log.Logger;
17+
import org.neo4j.shell.prettyprint.PrettyConfig;
18+
1419
import static org.junit.Assert.assertEquals;
1520
import static org.junit.Assert.assertTrue;
1621

17-
public class MainIntegrationTest {
22+
public class MainIntegrationTest
23+
{
24+
25+
private static class ShellAndConnection
26+
{
27+
CypherShell shell;
28+
ConnectionConfig connectionConfig;
29+
30+
ShellAndConnection( CypherShell shell, ConnectionConfig connectionConfig )
31+
{
32+
this.shell = shell;
33+
this.connectionConfig = connectionConfig;
34+
}
35+
}
36+
37+
@Rule
38+
public final ExpectedException exception = ExpectedException.none();
1839

1940
@Test
20-
public void connectInteractivelyPromptOnWrongAuthentication() throws Exception {
41+
public void connectInteractivelyPromptOnWrongAuthentication() throws Exception
42+
{
2143
// given
22-
// what the user inputs when prompted
23-
String inputString = String.format( "neo4j%nneo%n" );
24-
InputStream inputStream = new ByteArrayInputStream(inputString.getBytes());
25-
2644
ByteArrayOutputStream baos = new ByteArrayOutputStream();
27-
PrintStream ps = new PrintStream(baos);
28-
29-
Main main = new Main(inputStream, ps);
45+
Main main = getMain( baos );
3046

3147
CliArgs cliArgs = new CliArgs();
32-
cliArgs.setUsername("", "");
48+
cliArgs.setUsername( "", "" );
3349
cliArgs.setPassword( "", "" );
3450

35-
Logger logger = new AnsiLogger(cliArgs.getDebugMode());
36-
PrettyConfig prettyConfig = new PrettyConfig(cliArgs);
37-
ConnectionConfig connectionConfig = new ConnectionConfig(
38-
cliArgs.getScheme(),
39-
cliArgs.getHost(),
40-
cliArgs.getPort(),
41-
cliArgs.getUsername(),
42-
cliArgs.getPassword(),
43-
cliArgs.getEncryption(),
44-
cliArgs.getDatabase());
45-
46-
CypherShell shell = new CypherShell(logger, prettyConfig, true);
51+
ShellAndConnection sac = getShell( cliArgs );
52+
CypherShell shell = sac.shell;
53+
ConnectionConfig connectionConfig = sac.connectionConfig;
4754

4855
// when
49-
assertEquals("", connectionConfig.username());
50-
assertEquals("", connectionConfig.password());
56+
assertEquals( "", connectionConfig.username() );
57+
assertEquals( "", connectionConfig.password() );
5158

52-
main.connectMaybeInteractively(shell, connectionConfig, true);
59+
main.connectMaybeInteractively( shell, connectionConfig, true );
5360

5461
// then
5562
// should be connected
56-
assertTrue(shell.isConnected());
63+
assertTrue( shell.isConnected() );
5764
// should have prompted and set the username and password
58-
assertEquals("neo4j", connectionConfig.username());
59-
assertEquals("neo", connectionConfig.password());
65+
assertEquals( "neo4j", connectionConfig.username() );
66+
assertEquals( "neo", connectionConfig.password() );
6067

6168
String out = baos.toString();
6269
assertEquals( String.format( "username: neo4j%npassword: ***%n" ), out );
6370
}
71+
72+
@Test
73+
public void wrongPortWithBolt() throws Exception
74+
{
75+
// given
76+
Main main = getMain( new ByteArrayOutputStream() );
77+
78+
CliArgs cliArgs = new CliArgs();
79+
cliArgs.setScheme( "bolt://", "" );
80+
cliArgs.setPort( 1234 );
81+
82+
ShellAndConnection sac = getShell( cliArgs );
83+
CypherShell shell = sac.shell;
84+
ConnectionConfig connectionConfig = sac.connectionConfig;
85+
86+
exception.expect( ServiceUnavailableException.class );
87+
exception.expectMessage( "Unable to connect to localhost:1234, ensure the database is running and that there is a working network connection to it" );
88+
main.connectMaybeInteractively( shell, connectionConfig, true );
89+
}
90+
91+
@Test
92+
public void wrongPortWithNeo4j() throws Exception
93+
{
94+
// given
95+
Main main = getMain( new ByteArrayOutputStream() );
96+
97+
CliArgs cliArgs = new CliArgs();
98+
cliArgs.setScheme( "neo4j://", "" );
99+
cliArgs.setPort( 1234 );
100+
101+
ShellAndConnection sac = getShell( cliArgs );
102+
CypherShell shell = sac.shell;
103+
ConnectionConfig connectionConfig = sac.connectionConfig;
104+
105+
exception.expect( ServiceUnavailableException.class );
106+
exception.expectMessage( "Unable to connect to database, ensure the database is running and that there is a working network connection to it" );
107+
main.connectMaybeInteractively( shell, connectionConfig, true );
108+
}
109+
110+
private Main getMain( ByteArrayOutputStream baos )
111+
{
112+
// what the user inputs when prompted
113+
String inputString = String.format( "neo4j%nneo%n" );
114+
InputStream inputStream = new ByteArrayInputStream( inputString.getBytes() );
115+
116+
PrintStream ps = new PrintStream( baos );
117+
118+
return new Main( inputStream, ps );
119+
}
120+
121+
private ShellAndConnection getShell( CliArgs cliArgs )
122+
{
123+
Logger logger = new AnsiLogger( cliArgs.getDebugMode() );
124+
PrettyConfig prettyConfig = new PrettyConfig( cliArgs );
125+
ConnectionConfig connectionConfig = new ConnectionConfig(
126+
cliArgs.getScheme(),
127+
cliArgs.getHost(),
128+
cliArgs.getPort(),
129+
cliArgs.getUsername(),
130+
cliArgs.getPassword(),
131+
cliArgs.getEncryption(),
132+
cliArgs.getDatabase() );
133+
134+
return new ShellAndConnection( new CypherShell( logger, prettyConfig, true ), connectionConfig );
135+
}
64136
}

cypher-shell/src/main/java/org/neo4j/shell/cli/CliArgs.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class CliArgs {
3232
/**
3333
* Set the scheme to the primary value, or if null, the fallback value.
3434
*/
35-
void setScheme(@Nullable String primary, @Nonnull String fallback) {
35+
public void setScheme(@Nullable String primary, @Nonnull String fallback) {
3636
scheme = primary == null ? fallback : primary;
3737
}
3838

@@ -46,7 +46,7 @@ void setHost(@Nullable String primary, @Nonnull String fallback) {
4646
/**
4747
* Set the port to the value.
4848
*/
49-
void setPort(int port) {
49+
public void setPort(int port) {
5050
this.port = port;
5151
}
5252

cypher-shell/src/main/java/org/neo4j/shell/log/AnsiLogger.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public void printOut(@Nonnull final String msg) {
110110
}
111111

112112
/**
113-
* Interpret the cause of a Bolt exception and translate it into a sensible error message.
113+
* Formatting for Bolt exceptions.
114114
*/
115115
@Nonnull
116116
String getFormattedMessage(@Nonnull final Throwable e) {
@@ -122,23 +122,20 @@ String getFormattedMessage(@Nonnull final Throwable e) {
122122
e.printStackTrace(ps);
123123
msg.append(new String(baos.toByteArray(), StandardCharsets.UTF_8));
124124
} else {
125-
//noinspection ThrowableResultOfMethodCallIgnored
126-
final Throwable cause = getRootCause(e);
127-
128-
if (cause instanceof AnsiFormattedException) {
129-
msg = msg.append(((AnsiFormattedException) cause).getFormattedMessage());
130-
} else if (cause instanceof ClientException &&
131-
cause.getMessage() != null && cause.getMessage().contains("Missing username")) {
125+
if (e instanceof AnsiFormattedException) {
126+
msg = msg.append(((AnsiFormattedException) e).getFormattedMessage());
127+
} else if (e instanceof ClientException &&
128+
e.getMessage() != null && e.getMessage().contains("Missing username")) {
132129
// Username and password was not specified
133-
msg = msg.append(cause.getMessage())
130+
msg = msg.append(e.getMessage())
134131
.append("\nPlease specify --username, and optionally --password, as argument(s)")
135132
.append("\nor as environment variable(s), NEO4J_USERNAME, and NEO4J_PASSWORD respectively.")
136133
.append("\nSee --help for more info.");
137134
} else {
138-
if (cause.getMessage() != null) {
139-
msg = msg.append(cause.getMessage());
135+
if (e.getMessage() != null) {
136+
msg = msg.append(e.getMessage());
140137
} else {
141-
msg = msg.append(cause.getClass().getSimpleName());
138+
msg = msg.append(e.getClass().getSimpleName());
142139
}
143140
}
144141
}

cypher-shell/src/main/java/org/neo4j/shell/state/BoltStateHandler.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import java.util.Map;
66
import java.util.Optional;
77
import java.util.function.BiFunction;
8-
import java.util.function.Consumer;
98
import java.util.stream.Collectors;
109
import javax.annotation.Nonnull;
1110
import javax.annotation.Nullable;
@@ -17,12 +16,12 @@
1716
import org.neo4j.driver.Driver;
1817
import org.neo4j.driver.GraphDatabase;
1918
import org.neo4j.driver.Session;
20-
import org.neo4j.driver.SessionParametersTemplate;
2119
import org.neo4j.driver.Statement;
2220
import org.neo4j.driver.StatementResult;
2321
import org.neo4j.driver.Transaction;
2422
import org.neo4j.driver.exceptions.ClientException;
2523
import org.neo4j.driver.exceptions.SessionExpiredException;
24+
import org.neo4j.driver.internal.SessionConfig;
2625
import org.neo4j.driver.summary.DatabaseInfo;
2726
import org.neo4j.shell.ConnectionConfig;
2827
import org.neo4j.shell.Connector;
@@ -173,20 +172,24 @@ private void reconnect() {
173172
}
174173

175174
private void reconnect(boolean keepBookmark) {
176-
Consumer<SessionParametersTemplate> sessionOptionalArgs = t -> {};
177-
if (session != null && keepBookmark) {
175+
// This will already throw an exception if there is no connectivity
176+
driver.verifyConnectivity();
177+
178+
SessionConfig.Builder builder = SessionConfig.builder();
179+
builder.withDefaultAccessMode( AccessMode.WRITE );
180+
if ( !ABSENT_DB_NAME.equals( activeDatabaseNameAsSetByUser ) )
181+
{
182+
builder.withDatabase( activeDatabaseNameAsSetByUser );
183+
}
184+
if ( session != null && keepBookmark )
185+
{
178186
// Save the last bookmark and close the session
179187
final String bookmark = session.lastBookmark();
180188
session.close();
181-
sessionOptionalArgs = t -> t.withBookmarks(bookmark);
189+
builder.withBookmarks( bookmark );
182190
}
183-
Consumer<SessionParametersTemplate> sessionArgs = t -> {
184-
t.withDefaultAccessMode(AccessMode.WRITE);
185-
if (!ABSENT_DB_NAME.equals(activeDatabaseNameAsSetByUser)) {
186-
t.withDatabase(activeDatabaseNameAsSetByUser);
187-
}
188-
};
189-
session = driver.session(sessionArgs.andThen(sessionOptionalArgs));
191+
192+
session = driver.session( builder.build() );
190193

191194
String query = activeDatabaseNameAsSetByUser.compareToIgnoreCase(SYSTEM_DB_NAME) == 0 ? "SHOW DATABASES" : "RETURN 1";
192195

cypher-shell/src/test/java/org/neo4j/shell/log/AnsiLoggerTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,13 @@ public void testSimple() {
135135

136136
@Test
137137
public void testNested() {
138-
assertEquals("@|RED nested|@", logger.getFormattedMessage(new ClientException("outer",
138+
assertEquals("@|RED outer|@", logger.getFormattedMessage(new ClientException("outer",
139139
new CommandException("nested"))));
140140
}
141141

142142
@Test
143143
public void testNestedDeep() {
144-
assertEquals("@|RED nested deep|@", logger.getFormattedMessage(
144+
assertEquals("@|RED outer|@", logger.getFormattedMessage(
145145
new ClientException("outer",
146146
new ClientException("nested",
147147
new ClientException("nested deep")))));
@@ -150,7 +150,7 @@ public void testNestedDeep() {
150150
@Test
151151
public void testNullMessage() {
152152
assertEquals("@|RED ClientException|@", logger.getFormattedMessage(new ClientException(null)));
153-
assertEquals("@|RED NullPointerException|@",
153+
assertEquals("@|RED outer|@",
154154
logger.getFormattedMessage(new ClientException("outer", new NullPointerException(null))));
155155
}
156156

cypher-shell/src/test/java/org/neo4j/shell/test/bolt/FakeDriver.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33
import org.neo4j.driver.Driver;
44
import org.neo4j.driver.Metrics;
55
import org.neo4j.driver.Session;
6-
import org.neo4j.driver.SessionParametersTemplate;
76
import org.neo4j.driver.async.AsyncSession;
87
import org.neo4j.driver.exceptions.Neo4jException;
8+
import org.neo4j.driver.internal.SessionConfig;
99
import org.neo4j.driver.reactive.RxSession;
1010
import org.neo4j.driver.types.TypeSystem;
1111

1212
import java.util.concurrent.CompletionStage;
13-
import java.util.function.Consumer;
1413

1514
public class FakeDriver implements Driver {
1615
@Override
@@ -24,7 +23,7 @@ public Session session() {
2423
}
2524

2625
@Override
27-
public Session session(Consumer<SessionParametersTemplate> templateConsumer) {
26+
public Session session( SessionConfig sessionConfig) {
2827
return new FakeSession();
2928
}
3029

@@ -50,7 +49,7 @@ public RxSession rxSession()
5049
}
5150

5251
@Override
53-
public RxSession rxSession(Consumer<SessionParametersTemplate> templateConsumer)
52+
public RxSession rxSession( SessionConfig sessionConfig )
5453
{
5554
return null;
5655
}
@@ -62,7 +61,7 @@ public AsyncSession asyncSession()
6261
}
6362

6463
@Override
65-
public AsyncSession asyncSession(Consumer<SessionParametersTemplate> templateConsumer)
64+
public AsyncSession asyncSession( SessionConfig sessionConfig )
6665
{
6766
return null;
6867
}
@@ -72,4 +71,15 @@ public TypeSystem defaultTypeSystem()
7271
{
7372
return null;
7473
}
74+
75+
@Override
76+
public void verifyConnectivity()
77+
{
78+
}
79+
80+
@Override
81+
public CompletionStage<Void> verifyConnectivityAsync()
82+
{
83+
return null;
84+
}
7585
}

0 commit comments

Comments
 (0)