diff --git a/src/main/java/org/hyperledger/fabric/gateway/Gateway.java b/src/main/java/org/hyperledger/fabric/gateway/Gateway.java index 43b6af0e..d5a6a49c 100644 --- a/src/main/java/org/hyperledger/fabric/gateway/Gateway.java +++ b/src/main/java/org/hyperledger/fabric/gateway/Gateway.java @@ -183,6 +183,14 @@ interface Builder { */ Builder discovery(boolean enabled); + /** + * Optional - Enable or disable force immediate shutdown of the network connection. + * forceClose is enabled by default. + * @param enabled - true to enable force immediate shutdown. + * @return The builder instance, allowing multiple configuration options to be chained. + */ + Builder forceClose(boolean enabled); + /** * Connects to the gateway using the specified options. * @return The connected {@link Gateway} object. diff --git a/src/main/java/org/hyperledger/fabric/gateway/impl/GatewayImpl.java b/src/main/java/org/hyperledger/fabric/gateway/impl/GatewayImpl.java index 79b5924e..e78dd273 100644 --- a/src/main/java/org/hyperledger/fabric/gateway/impl/GatewayImpl.java +++ b/src/main/java/org/hyperledger/fabric/gateway/impl/GatewayImpl.java @@ -62,6 +62,7 @@ public final class GatewayImpl implements Gateway { private final TimePeriod commitTimeout; private final QueryHandlerFactory queryHandlerFactory; private final boolean discovery; + private final boolean forceClose; public static final class Builder implements Gateway.Builder { private CommitHandlerFactory commitHandlerFactory = DefaultCommitHandlers.PREFER_MSPID_SCOPE_ALLFORTX; @@ -71,6 +72,7 @@ public static final class Builder implements Gateway.Builder { private Identity identity = null; private HFClient client; private boolean discovery = false; + private boolean forceClose = true; private static final class ExposedByteArrayOutputStream extends ByteArrayOutputStream { public byte[] getInternalBuffer() { @@ -152,6 +154,12 @@ public Builder discovery(final boolean enabled) { return this; } + @Override + public Builder forceClose(final boolean enabled) { + this.forceClose = enabled; + return this; + } + public Builder client(final HFClient client) { this.client = client; return this; @@ -168,6 +176,7 @@ private GatewayImpl(final Builder builder) { this.commitTimeout = builder.commitTimeout; this.queryHandlerFactory = builder.queryHandlerFactory; this.discovery = builder.discovery; + this.forceClose = builder.forceClose; if (builder.client != null) { // Only for testing! @@ -201,6 +210,7 @@ private GatewayImpl(final GatewayImpl that) { this.commitTimeout = that.commitTimeout; this.queryHandlerFactory = that.queryHandlerFactory; this.discovery = that.discovery; + this.forceClose = that.forceClose; this.networkConfig = that.networkConfig; this.identity = that.identity; @@ -281,6 +291,10 @@ public boolean isDiscoveryEnabled() { return discovery; } + public boolean isForceClose() { + return forceClose; + } + public GatewayImpl newInstance() { return new GatewayImpl(this); } diff --git a/src/main/java/org/hyperledger/fabric/gateway/impl/NetworkImpl.java b/src/main/java/org/hyperledger/fabric/gateway/impl/NetworkImpl.java index 8c48e1c7..0b0b6095 100644 --- a/src/main/java/org/hyperledger/fabric/gateway/impl/NetworkImpl.java +++ b/src/main/java/org/hyperledger/fabric/gateway/impl/NetworkImpl.java @@ -179,7 +179,7 @@ public void close() { orderedBlockSource.close(); channelBlockSource.close(); - channel.shutdown(false); + channel.shutdown(gateway.isForceClose()); } @Override diff --git a/src/test/java/org/hyperledger/fabric/gateway/impl/GatewayTest.java b/src/test/java/org/hyperledger/fabric/gateway/impl/GatewayTest.java index 1eeff95f..1f944e47 100644 --- a/src/test/java/org/hyperledger/fabric/gateway/impl/GatewayTest.java +++ b/src/test/java/org/hyperledger/fabric/gateway/impl/GatewayTest.java @@ -82,6 +82,37 @@ public void testCloseGatewayClosesNetworks() { assertThat(channel.isShutdown()).isTrue(); } + @Test + public void testCloseGatewayForceClosesNetworks() { + HFClient mockClient = testUtils.newMockClient(); + Channel mockChannel = testUtils.newMockChannel("CHANNEL"); + Mockito.when(mockClient.getChannel("CHANNEL")).thenReturn(mockChannel); + + builder.client(mockClient); + + try (Gateway gateway = builder.connect()) { + gateway.getNetwork("CHANNEL"); + } + + Mockito.verify(mockChannel).shutdown(true); + } + + @Test + public void testCloseGatewayWithForceCloseDisabledClosesNetworks() { + HFClient mockClient = testUtils.newMockClient(); + Channel mockChannel = testUtils.newMockChannel("CHANNEL"); + Mockito.when(mockClient.getChannel("CHANNEL")).thenReturn(mockChannel); + + builder.client(mockClient); + builder.forceClose(false); + + try (Gateway gateway = builder.connect()) { + gateway.getNetwork("CHANNEL"); + } + + Mockito.verify(mockChannel).shutdown(false); + } + @Test public void testNewInstanceHasSameCryptoSuite() { final HFClient clientSpy;