googleapis / googleapis/google-cloud-java

[java-spanner] NullPointerException occurring in HttpJsonSpannerStub.batchWriteCallable() when handling an error status response.

Đang mở
#12,247 5 bình luận 0 reaction 1 người được giao Được @rahul2393 nhận Xem trên GitHub
api: spanner
Ngôn ngữ chính
Java
Star
2.1k
Fork
1.2k
Merge trung bình
1 ngày 23 giờ
Pull request đã merge (30 ngày)
154

Mô tả

I'd like to report a `NullPointerException` in `HttpJsonSpannerStub` generated by gapic-generator. I understand the code is not intended for end-user use, but I'm reporting it in case others encounter similar issues

#### Environment details

* OS type and version: macOS 15.3
* Java version: 11
* version(s): google-cloud-spanner 6.86.6

#### Steps to reproduce

1. Create a Spanner table with `CREATE TABLE table1 (k STRING(100), v INT64) PRIMARY KEY (k)`.
2. Add a row with the key `k` as "k1".
3. Run the following code which writes a row with `k` as "k1". This will result in an error status response from Cloud Spanner.

An exception with an appropriate error message, such as "Row [k1] in table table1 already exists," is expected. However, a NullPointerException is thrown instead.

#### Code example

```java
import com.google.api.gax.rpc.ServerStream;
import com.google.api.gax.rpc.ServerStreamingCallable;
import com.google.cloud.spanner.v1.stub.SpannerStub;
import com.google.cloud.spanner.v1.stub.SpannerStubSettings;
import com.google.protobuf.ListValue;
import com.google.protobuf.Value;
import com.google.spanner.v1.*;

import java.io.IOException;

public class SpannerHttpJsonStubMain {
public static void main(String[] args) throws IOException {
SpannerStubSettings stubSettings = SpannerStubSettings.newHttpJsonBuilder().build();
try (SpannerStub stub = stubSettings.createStub()) {
Session session = stub.createSessionCallable()
.call(CreateSessionRequest.newBuilder()
.setDatabase("projects//instances/spanner-1/databases/db-1")
.build());
BatchWriteRequest request = BatchWriteRequest.newBuilder()
.setSession(session.getName())
.addMutationGroups(BatchWriteRequest.MutationGroup.newBuilder()
.addMutations(Mutation.newBuilder()
.setInsert(Mutation.Write.newBuilder()
// SCHEMA: CREATE TABLE table1 (k STRING(100), v INT64) PRIMARY KEY (k)
.setTable("table1")
.addColumns("k")
.addColumns("v")
// The key "k1" already exists in the table. Therefore, this request will result in an error
// response.
.addValues(ListValue.newBuilder()
.addValues(Value.newBuilder().setStringValue("k1"))
.addValues(Value.newBuilder().setStringValue("1"))))))
.build();

ServerStreamingCallable callable = stub.batchWriteCallable();

ServerStream responseStream = callable.call(request);
for (BatchWriteResponse response : responseStream) {
System.out.println("response = " + response);
}
}
}
}
```

#### Stack trace

The code was run with the JVM option `-Djava.util.logging.config.file=logging.properties` to enable HTTP transport debug logging. The logging.properties file is [here](https://github.com/baeminbo/dataflow-pipelines/blob/master/spanner-study/logging.properties). The output shows that parsing `DebugInfo` failed because `TypedRegistry` was `null` in some location

```
... skipped ...

Feb 11, 2025 11:21:51 PM com.google.api.client.http.HttpResponse
CONFIG: -------------- RESPONSE --------------
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Server: ESF
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Server-Timing: gfet4t7; dur=148
Content-Encoding: gzip
Vary: Origin
Vary: X-Origin
Vary: Referer
X-XSS-Protection: 0
Date: Wed, 12 Feb 2025 07:21:51 GMT
Content-Type: application/json; charset=UTF-8

Feb 11, 2025 11:21:51 PM com.google.api.client.util.LoggingByteArrayOutputStream close
CONFIG: Total: 254 bytes
Feb 11, 2025 11:21:51 PM com.google.api.client.util.LoggingByteArrayOutputStream close
CONFIG: [{
"indexes": [
0
],
"status": {
"code": 6,
"message": "Row [k1] in table table1 already exists",
"details": [
{
"@type": "type.googleapis.com/google.rpc.DebugInfo",
"detail": "table1(k1)"
}
]
}
}
]
Exception in thread "main" com.google.api.gax.rpc.CancelledException: Exception in message delivery
at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:48)
at com.google.api.gax.httpjson.HttpJsonApiExceptionFactory.createApiException(HttpJsonApiExceptionFactory.java:76)
at com.google.api.gax.httpjson.HttpJsonApiExceptionFactory.create(HttpJsonApiExceptionFactory.java:58)
at com.google.api.gax.httpjson.HttpJsonExceptionResponseObserver.onErrorImpl(HttpJsonExceptionResponseObserver.java:82)
at com.google.api.gax.rpc.StateCheckingResponseObserver.onError(StateCheckingResponseObserver.java:84)
at com.google.api.gax.httpjson.HttpJsonDirectStreamController$ResponseObserverAdapter.onClose(HttpJsonDirectStreamController.java:125)
at com.google.api.gax.httpjson.HttpJsonClientCallImpl$OnCloseNotificationTask.call(HttpJsonClientCallImpl.java:551)
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.notifyListeners(HttpJsonClientCallImpl.java:390)
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.deliver(HttpJsonClientCallImpl.java:317)
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.setResult(HttpJsonClientCallImpl.java:163)
at com.google.api.gax.httpjson.HttpRequestRunnable.run(HttpRequestRunnable.java:148)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1570)
Suppressed: java.lang.RuntimeException: Asynchronous task failed
at com.google.api.gax.rpc.ServerStreamIterator.hasNext(ServerStreamIterator.java:105)
at SpannerHttpJsonStubMain.main(SpannerHttpJsonStubMain.java:38)
Caused by: com.google.api.gax.httpjson.HttpJsonStatusRuntimeException: Exception in message delivery
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.deliver(HttpJsonClientCallImpl.java:367)
... 8 more
Caused by: com.google.api.gax.httpjson.RestSerializationException: Failed to parse response message
at com.google.api.gax.httpjson.ProtoRestSerializer.fromJson(ProtoRestSerializer.java:107)
at com.google.api.gax.httpjson.ProtoMessageResponseParser.parse(ProtoMessageResponseParser.java:76)
at com.google.api.gax.httpjson.ProtoMessageResponseParser.parse(ProtoMessageResponseParser.java:41)
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.consumeMessageFromStream(HttpJsonClientCallImpl.java:430)
at com.google.api.gax.httpjson.HttpJsonClientCallImpl.deliver(HttpJsonClientCallImpl.java:362)
... 8 more
Caused by: com.google.protobuf.InvalidProtocolBufferException: Cannot invoke "com.google.protobuf.TypeRegistry.getDescriptorForTypeUrl(String)" because "this.registry" is null
at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1309)
at com.google.protobuf.util.JsonFormat$Parser.merge(JsonFormat.java:463)
at com.google.api.gax.httpjson.ProtoRestSerializer.fromJson(ProtoRestSerializer.java:104)
... 12 more
Caused by: java.lang.NullPointerException: Cannot invoke "com.google.protobuf.TypeRegistry.getDescriptorForTypeUrl(String)" because "this.registry" is null
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeAny(JsonFormat.java:1507)
at com.google.protobuf.util.JsonFormat$ParserImpl.access$2000(JsonFormat.java:1276)
at com.google.protobuf.util.JsonFormat$ParserImpl$1.merge(JsonFormat.java:1343)
at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1432)
at com.google.protobuf.util.JsonFormat$ParserImpl.parseFieldValue(JsonFormat.java:1995)
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeRepeatedField(JsonFormat.java:1710)
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeField(JsonFormat.java:1642)
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeMessage(JsonFormat.java:1477)
at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1435)
at com.google.protobuf.util.JsonFormat$ParserImpl.parseFieldValue(JsonFormat.java:1995)
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeField(JsonFormat.java:1646)
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeMessage(JsonFormat.java:1477)
at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1435)
at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1299)
... 14 more
```

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.