Zack
Zack

Reputation: 13972

How do I grab variables from the Context/scope while inside an onNext call? (java/grpc)

I am working with contexts within grpc/java.

I am ultimately trying to

1) grab metadata attached as a header from each incoming request (cred metadata)

2) attach this to the grpc scope/context, so that I have access to it when the request comes in, server side.

It's kind of a work around for not being able to change the API as much as I would like to. Nonetheless, I have defined an Interceptor that will strip each incoming request of the metadata.

public class OnBehalfOfInterceptor implements ServerInterceptor {

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
       final ServerCall<ReqT, RespT> call,
       final Metadata headers,
       final ServerCallHandler<ReqT, RespT> next
    ) {

        Context ctx = Context.current();

        String mayDelegate = headers.get(
            Metadata.Key.of("may-delegate", Metadata.ASCII_STRING_MARSHALLER)
        );
        String onBehalfOf;

        if (mayDelegate != null && str2bool(mayDelegate)) {
            onBehalfOf = headers.get(
                Metadata.Key.of("on-behalf-of", Metadata.ASCII_STRING_MARSHALLER)
            );
            ctx = ctx.withValue(
                    Context.key("on-behalf-of"),
                    onBehalfOf
            );
        }

        return Contexts.interceptCall(ctx, call, headers, next);
    }

}

This code attempts to find a string "on-behalf-of" and if it finds it, attaches it to the current context.

Now, when I go to debug the current Context, I am able to see the following output

Context.current().keyValueEntries.root.values[1]

result
    key "on-behalf-of"
    value "my id"

This was the debug output inside a .onNext() call, I was able to see the context variables as I figured I should be able to. However, I am not able to grab "keyValueEntries" while I am not in the debug run time environment. I'm guessing that it is something that the debugger provides, not necessarily a member of the Context class.

So... How do I properly get access to the variables that I had attached to the current context? I've tried a few different examples and debugged my way through them.

Context.current().get(Context.key("on-behalf-of"))

// this ^ returns null

Am I just thinking about this wrong? Is there an easier way to grab metadata off of the incoming request?

Upvotes: 3

Views: 1577

Answers (1)

Eric Anderson
Eric Anderson

Reputation: 26414

Context.Key uses reference equality. You should use the same Key instance in both locations. The String passed is just a debug string. As written in the documentation:

Create a Context.Key with the given debug name. Multiple different keys may have the same name; the name is intended for debugging purposes and does not impact behavior.

Using reference equality means you can use Java visibility restrictions to limit what code has access to the context state, in the same way that's possible with ThreadLocal.

Upvotes: 4

Related Questions