Configuration

<- Back to Index

This section describes how you can configure your grpc-spring-boot-starter clients.

Table of Contents

Additional Topics

Configuration via Properties

grpc-spring-boot-starter can be configured via spring’s @ConfigurationProperties mechanism.

You can find all build-in configuration properties here:

If you prefer to read the sources instead, you can do so here.

The properties for the channels are all prefixed with grpc.client.__name__. and grpc.client.__name__.security. respectively. The channel name is taken from the @GrpcClient("__name__") annotation. If you wish to configure some options such as trusted certificates for all servers at once, you can do so using GLOBAL as name. Properties that are defined for a specific/named channel take precedence over GLOBAL ones.

Choosing the Target

You can change the target server using the following property:

grpc.client.__name__.address=static://localhost:9090

There are a number of supported schemes, that you can use to determine the target server (Priorities 0 (low) - 10 (high)):

If you don’t define an address it will be guessed:

Note: The number of slashes is important! Also make sure that you don’t try to connect to a normal web/REST/non-grpc server (port).

The SSL/TLS and other security relevant configuration is explained on the Client Security page.

Configuration via Beans

While this library intents to provide most of the features as configuration option, sometimes the overhead for adding it is too high and thus we didn’t add it, yet. If you feel like it is an important feature, feel free to open a feature request.

If you want to change the application beyond what you can do through the properties, then you can use the existing extension points that exist in this library.

First of all most of the beans can be replaced by custom ones, that you can configure in every way you want. If you don’t wish to go that far, you can use classes such as GrpcChannelConfigurer and StubTransformer to configure the channels, stubs and other components without losing the features provided by this library.

GrpcChannelConfigurer

The grpc client configurer allows you to add your custom configuration to grpc’s ManagedChannelBuilders.

@Bean
public GrpcChannelConfigurer keepAliveClientConfigurer() {
    return (channelBuilder, name) -> {
        if (channelBuilder instanceof NettyChannelBuilder) {
            ((NettyChannelBuilder) channelBuilder)
                    .keepAliveTime(30, TimeUnit.SECONDS)
                    .keepAliveTimeout(5, TimeUnit.SECONDS);
        }
    };
}

Be aware that depending on your configuration there might be different types of ManagedChannelBuilders in the application context (e.g. the InProcessChannelFactory).

ClientInterceptor

ClientInterceptors can be used for various tasks, including:

There are three ways to add a ClientInterceptor to your channel.

The following examples demonstrate how to use annotations to create a global client interceptor:

@Configuration
public class ThirdPartyInterceptorConfig {}

    @GrpcGlobalServerInterceptor
    LogGrpcInterceptor logServerInterceptor() {
        return new LogGrpcInterceptor();
    }

}

This variant is very handy if you wish to add third-party interceptors to the global scope.

For your own interceptor implementations you can achieve the same result by adding the annotation to the class itself:

@GrpcGlobalServerInterceptor
public class LogGrpcInterceptor implements ServerInterceptor {

    private static final Logger log = LoggerFactory.getLogger(LogGrpcInterceptor.class);

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
            ServerCall<ReqT, RespT> serverCall,
            Metadata metadata,
            ServerCallHandler<ReqT, RespT> serverCallHandler) {

        log.info(serverCall.getMethodDescriptor().getFullMethodName());
        return serverCallHandler.startCall(serverCall, metadata);
    }

}

StubFactory

A StubFactory is used to create a Stub of a specific type. The registered stub factories will be checked in order and the first applicable factory will be used to create the stub.

This library has build in support for the Stub types defined in grpc-java:

But you can easily add support for other Stub types by adding a custom StubFactory to your application context.

@Component
public class MyCustomStubFactory implements StubFactory {

    @Override
    public MyCustomStub<?> createStub(Class<? extends AbstractStub<?>> stubType, Channel channel) {
        try {
            Class<?> enclosingClass = stubType.getEnclosingClass();
            Method factoryMethod = enclosingClass.getMethod("newMyBetterFutureStub", Channel.class);
            return stubType.cast(factoryMethod.invoke(null, channel));
        } catch (Exception e) {
            throw new BeanInstantiationException(stubType, "Failed to create gRPC stub", e);
        }
    }

    @Override
    public boolean isApplicable(Class<? extends AbstractStub<?>> stubType) {
        return AbstractMyCustomStub.class.isAssignableFrom(stubType);
    }

}

Note: Please report missing stub types (and the corresponding library) in our issue tracker so that we can add support if possible.

StubTransformer

The stub transformer allows you to modify Stubs right before they are injected to your beans. This is the recommended way to add CallCredentials to your stubs.

@Bean
public StubTransformer call() {
    return (name, stub) -> {
        if ("serviceA".equals(name)) {
            return stub.withWaitForReady();
        } else {
            return stub;
        }
    };
}

You can also use StubTransformers to add custom ClientInterceptors to your stub.

Note: The StubTransformers are applied after the @GrpcClient#interceptors(Names) have been added.

Custom NameResolverProvider

Sometimes you might have some custom logic that decides which server you wish to connect to, you can achieve this using a custom NameResolverProvider.

Note: This can only be used to decide this on an application level and not on a per request level.

This library provides some NameResolverProviders itself so you can use them as a reference.

You can register your NameResolverProvider by adding it to META-INF/services/io.grpc.NameResolverProvider for Java’s ServiceLoader or adding it your spring context. If you wish to use some spring beans inside your NameResolver, then you have to define it via spring context (unless you wish to use static).

Note: NameResolverProviders are registered gloablly, so might run into issues if you boot up two or more applications simulataneosly in the same JVM (e.g. during tests).

Additional Topics


<- Back to Index