Skip to content

Commit 6069e6e

Browse files
committed
Throw ServiceUnavailableException when socket write fails
Previously `ClientException` was thrown which was incorrect and resulted in connections not being properly disposed.
1 parent 9d5e46d commit 6069e6e

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

driver/src/main/java/org/neo4j/driver/internal/net/SocketConnection.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.neo4j.driver.v1.Value;
3939
import org.neo4j.driver.v1.exceptions.ClientException;
4040
import org.neo4j.driver.v1.exceptions.Neo4jException;
41+
import org.neo4j.driver.v1.exceptions.ServiceUnavailableException;
4142
import org.neo4j.driver.v1.summary.ServerInfo;
4243

4344
import static java.lang.String.format;
@@ -165,8 +166,7 @@ public synchronized void flush()
165166
}
166167
catch ( IOException e )
167168
{
168-
String message = e.getMessage();
169-
throw new ClientException( "Unable to send messages to server: " + message, e );
169+
throw new ServiceUnavailableException( "Unable to send messages to server: " + e.getMessage(), e );
170170
}
171171
}
172172

driver/src/test/java/org/neo4j/driver/internal/net/SocketConnectionTest.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@
2222
import org.mockito.invocation.InvocationOnMock;
2323
import org.mockito.stubbing.Answer;
2424

25+
import java.io.IOException;
2526
import java.net.URI;
2627
import java.util.ArrayList;
2728
import java.util.Iterator;
29+
import java.util.Queue;
2830

2931
import org.neo4j.driver.internal.messaging.Message;
3032
import org.neo4j.driver.internal.messaging.SuccessMessage;
3133
import org.neo4j.driver.internal.summary.InternalServerInfo;
32-
import org.neo4j.driver.v1.Logger;
3334
import org.neo4j.driver.v1.Values;
35+
import org.neo4j.driver.v1.exceptions.ServiceUnavailableException;
3436
import org.neo4j.driver.v1.summary.ServerInfo;
3537

3638
import static org.hamcrest.CoreMatchers.equalTo;
3739
import static org.hamcrest.CoreMatchers.instanceOf;
40+
import static org.junit.Assert.assertSame;
3841
import static org.junit.Assert.assertThat;
3942
import static org.junit.Assert.fail;
4043
import static org.mockito.Matchers.any;
@@ -45,16 +48,20 @@
4548
import static org.mockito.Mockito.times;
4649
import static org.mockito.Mockito.verify;
4750
import static org.mockito.Mockito.when;
51+
import static org.neo4j.driver.internal.logging.DevNullLogger.DEV_NULL_LOGGER;
52+
import static org.neo4j.driver.internal.net.BoltServerAddress.LOCAL_DEFAULT;
4853
import static org.neo4j.driver.v1.Values.parameters;
4954

5055
public class SocketConnectionTest
5156
{
57+
private static final InternalServerInfo SERVER_INFO = new InternalServerInfo( LOCAL_DEFAULT, "test" );
58+
5259
@Test
5360
public void shouldReceiveServerInfoAfterInit() throws Throwable
5461
{
5562
// Given
5663
SocketClient socket = mock( SocketClient.class );
57-
SocketConnection conn = new SocketConnection( socket, mock( InternalServerInfo.class ), mock( Logger.class ) );
64+
SocketConnection conn = new SocketConnection( socket, SERVER_INFO, DEV_NULL_LOGGER );
5865

5966
when( socket.address() ).thenReturn( BoltServerAddress.from( URI.create( "http://neo4j.com:9000" ) ) );
6067

@@ -98,7 +105,7 @@ public void shouldCloseConnectionIfFailedToCreate() throws Throwable
98105
// Then
99106
try
100107
{
101-
SocketConnection conn = new SocketConnection( socket, mock( InternalServerInfo.class ), mock( Logger.class ) );
108+
new SocketConnection( socket, SERVER_INFO, DEV_NULL_LOGGER );
102109
fail( "should have failed with the provided exception" );
103110
}
104111
catch( Throwable e )
@@ -108,4 +115,26 @@ public void shouldCloseConnectionIfFailedToCreate() throws Throwable
108115
}
109116
verify( socket, times( 1 ) ).stop();
110117
}
118+
119+
@Test
120+
@SuppressWarnings( "unchecked" )
121+
public void flushThrowsWhenSocketIsBroken() throws Exception
122+
{
123+
SocketClient socket = mock( SocketClient.class );
124+
IOException sendError = new IOException( "Unable to send" );
125+
doThrow( sendError ).when( socket ).send( any( Queue.class ) );
126+
127+
SocketConnection connection = new SocketConnection( socket, SERVER_INFO, DEV_NULL_LOGGER );
128+
129+
try
130+
{
131+
connection.flush();
132+
fail( "Exception expected" );
133+
}
134+
catch ( Exception e )
135+
{
136+
assertThat( e, instanceOf( ServiceUnavailableException.class ) );
137+
assertSame( sendError, e.getCause() );
138+
}
139+
}
111140
}

driver/src/test/java/org/neo4j/driver/v1/integration/CausalClusteringIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,8 @@ public void shouldHandleGracefulLeaderSwitch() throws Exception
312312
parameters( "name", "Webber", "title", "Mr" ) );
313313
tx1.success();
314314

315-
closeAndExpectException( tx1, ClientException.class );
316-
closeAndExpectException( session1, ClientException.class );
315+
closeAndExpectException( tx1, SessionExpiredException.class );
316+
session1.close();
317317

318318
String bookmark = inExpirableSession( driver, createSession(), new Function<Session,String>()
319319
{

0 commit comments

Comments
 (0)