I'm having an issue with the java client
# spicedb
t
I'm having an issue with the java client > 0.9.0 and matching grpc version where when I call
SchemaServiceGrpc.newBlockingStub(channel).withCallCredentials(BearerToken(presharedKey))
specifically the withCallCredentials part, I get the error
apply() or fail() already called
. Any ideas why? I know it happens during the
applier.apply(headers);
step in BearerToken.
v
I was able to call read schema with the following snippet, using the authzed-java SDK 1.1.0, and grpc-protobuf `1.68.1`:
Copy code
ManagedChannel channel = ManagedChannelBuilder
                .forTarget("localhost:50051")
                .usePlaintext()
                .build();

        BearerToken bearerToken = new BearerToken("foobar");

        SchemaServiceGrpc.SchemaServiceBlockingStub schemaService = SchemaServiceGrpc.
                newBlockingStub(channel).
                withCallCredentials(bearerToken);
t
Copy code
mavenBom("io.grpc:grpc-bom:1.68.1")
...
    implementation ("com.authzed.api:authzed:v1.1.0")
    implementation ("io.grpc:grpc-protobuf")
    implementation ("io.grpc:grpc-stub")
Copy code
val channelBuilder = ManagedChannelBuilder
            .forTarget(spicedbUrl)
        if (secure)
            channelBuilder.useTransportSecurity()
        if (!secure)
            channelBuilder.usePlaintext()
        val channel = channelBuilder.build()

        val schema = resourceLoader.getResource("classpath:spicedb/schema.zed").inputStream.bufferedReader().use { it.readText() }
        val schemaService = SchemaServiceGrpc.newBlockingStub(channel).withCallCredentials(BearerToken(presharedKey))
Copy code
Exception in thread "grpc-default-executor-0" java.lang.IllegalStateException: apply() or fail() already called
    at com.google.common.base.Preconditions.checkState(Preconditions.java:513)
    at io.grpc.internal.MetadataApplierImpl.fail(MetadataApplierImpl.java:84)
    at com.authzed.grpcutil.BearerToken.lambda$applyRequestMetadata$0(BearerToken.java:31)
    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:1583)
y
@ThatDiveGuy it looks like it's the same issue as https://github.com/authzed/authzed-java/issues/117
what call are you attempting to make, and what's the target of the call?
t
What I put above is the entirety of the relevant code to cause the error
Also, thank you for pointing that out, it's exactly the issue
y
so it's just constructing the client that's causing the issue?
t
yep, can't get past that
y
is that the entire code snippet? i.e. are you doing any other work with the zed client in code invoked along that codepath?
t
not before that
y
are you able to bring one of the examples in the examples directory into your project and execute it successfully?
err rather the example
t
I made a copy of the bearer token object and added some logging
Copy code
10:51:07.253 [grpc-default-executor-0] INFO  n.e.central.security.BearerToken - BearerToken error:
java.lang.NoSuchMethodError: 'boolean com.google.protobuf.GeneratedMessage.isStringEmpty(java.lang.Object)'
    at com.authzed.api.v1.WriteSchemaRequest.getSerializedSize(WriteSchemaRequest.java:126)
    at io.grpc.protobuf.lite.ProtoInputStream.available(ProtoInputStream.java:108)
    at io.grpc.internal.MessageFramer.getKnownLength(MessageFramer.java:204)
    at io.grpc.internal.MessageFramer.writePayload(MessageFramer.java:139)
    at io.grpc.internal.AbstractStream.writeMessage(AbstractStream.java:66)
    at io.grpc.internal.DelayedStream$6.run(DelayedStream.java:282)
    at io.grpc.internal.DelayedStream.drainPendingCalls(DelayedStream.java:182)
    at io.grpc.internal.DelayedStream.access$100(DelayedStream.java:44)
    at io.grpc.internal.DelayedStream$4.run(DelayedStream.java:148)
    at io.grpc.internal.MetadataApplierImpl.finalizeWith(MetadataApplierImpl.java:111)
    at io.grpc.internal.MetadataApplierImpl.apply(MetadataApplierImpl.java:78)
It happens during
Copy code
headers.put(META_DATA_KEY, header)
y
do you know what's in the preshared key value? are you sure it's a string?
t
yes
This code works just fine with 0.9.0. The only thing I change to break it is the versions
y
🤔
t
y
sanity check: does the problem still exist if you bump your grpc libs to 1.69.0?
t
yes
so the problem is in the generated authzed client. it's trying to use
Copy code
if (!com.google.protobuf.GeneratedMessage.isStringEmpty(schema_)) {
in WriteSchemaRequest.java but it should be referencing
Copy code
if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(schema_)) {
y
yeah iirc that was a change that they made in 4.27
t
ok, I see why, the authzed client is correct. It's dependency hell
com.google.firebase:firebase-admin depends on protobufs 3.x still for some reason
weirdly, so does grpc-api 1.69.0...
y
oh that's gross 😦
but yeah that's something that we've seen folks run into fairly regularly
the protoc build systems and runtimes make an assumption that rather than using multiple libraries that each have their own runtime, you're instead starting with the protobuf for all of the various services you want to talk to and then running a single build against a single version of protobuf for your system
which isn't borne out in practice 🙃
well, problem solved and I updated issue 117 with the details of my solution
y
thank you!
9 Views