diff --git a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Spanner.java b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Spanner.java index 75c062f96811..0c6bec4ea830 100644 --- a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Spanner.java +++ b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Spanner.java @@ -105,4 +105,7 @@ public interface Spanner extends Service, AutoCloseable { */ @Override void close(); + + /** @return true if this {@link Spanner} object is closed. */ + boolean isClosed(); } diff --git a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java index 5e60686c7e5b..9ee941584c11 100644 --- a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java +++ b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java @@ -291,6 +291,11 @@ public void close() { } } + @Override + public boolean isClosed() { + return spannerIsClosed; + } + /** * Checks that the current context is still valid, throwing a CANCELLED or DEADLINE_EXCEEDED error * if not. diff --git a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java index b5457f814d26..0ddee6b5d9a1 100644 --- a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java +++ b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java @@ -298,6 +298,36 @@ protected SpannerRpc getSpannerRpcV1() { return (SpannerRpc) getRpc(); } + /** + * Returns a {@link Spanner} service object. Note that only the first call to this method will + * create a new instance, and all subsequent calls to this method will return the same instance. + * Calling this method after the {@link Spanner} instance has been closed will cause an exception. + */ + @Override + public Spanner getService() { + Spanner spanner = super.getService(); + if (spanner.isClosed()) { + throw new IllegalStateException( + "The Spanner service of this SpannerOptions has been closed. Create a new SpannerOptions instance and call getService() on the new instance instead."); + } + return spanner; + } + + /** + * Returns a {@link SpannerRpc} object. Note that only the first call to this method will create a + * new instance, and all subsequent calls to this method will return the same instance. Calling + * this method after the instance has been closed will cause an exception. + */ + @Override + public ServiceRpc getRpc() { + SpannerRpc rpc = (SpannerRpc) super.getRpc(); + if (rpc.isClosed()) { + throw new IllegalStateException( + "The Spanner service of this SpannerOptions has been closed. Create a new SpannerOptions instance and call getRpc() on the new instance instead."); + } + return rpc; + } + @SuppressWarnings("unchecked") @Override public Builder toBuilder() { diff --git a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java index 4aaf8e1e6298..8b57dd7c2851 100644 --- a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java +++ b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java @@ -168,6 +168,7 @@ private synchronized void shutdown() { private static final int DEFAULT_PERIOD_SECONDS = 10; private final ManagedInstantiatingExecutorProvider executorProvider; + private boolean rpcIsClosed; private final SpannerStub spannerStub; private final InstanceAdminStub instanceAdminStub; private final DatabaseAdminStub databaseAdminStub; @@ -631,6 +632,7 @@ private GrpcCallContext newCallContext(@Nullable Map options, String @Override public void shutdown() { + this.rpcIsClosed = true; this.spannerStub.close(); this.instanceAdminStub.close(); this.databaseAdminStub.close(); @@ -638,6 +640,11 @@ public void shutdown() { this.executorProvider.shutdown(); } + @Override + public boolean isClosed() { + return rpcIsClosed; + } + /** * A {@code ResponseObserver} that exposes the {@code StreamController} and delegates callbacks to * the {@link ResultStreamConsumer}. diff --git a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java index 500f369f67a8..593ba3c5ec06 100644 --- a/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java +++ b/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/SpannerRpc.java @@ -233,4 +233,6 @@ PartitionResponse partitionRead(PartitionReadRequest request, @Nullable Map