CtrlK
BlogDocsLog inGet started
Tessl Logo

finkel/spring-grpc

Spring gRPC reference documentation covering server, client, security, and configuration

92

2.19x
Quality

Pending

Does it follow best practices?

Impact

92%

2.19x

Average score across 3 eval scenarios

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

server.mddocs/

gRPC Server

To create a gRPC server, you need to provide one or more beans of type BindableService. The BindableService is a gRPC service that can be bound to a server. The Server is the gRPC server that listens for incoming requests and routes them to the appropriate service implementations.

Defining a Service

@Service
public class MyGrpcService extends MyServiceGrpc.MyServiceImplBase {
    // implementation
}

Service Filtering

Decide which services bind to which factory:

@Bean
ServerServiceDefinitionFilter myServiceFilter() {
    return (serviceDefinition, __) ->
            !Set.of(HealthGrpc.SERVICE_NAME, ServerReflectionGrpc.SERVICE_NAME)
                .contains(serviceDefinition.getServiceDescriptor().getName());
}

@Bean
GrpcServerFactoryCustomizer myServerFactoryCustomizer(ServerServiceDefinitionFilter filter) {
    return factory -> {
        if (factory instanceof NettyGrpcServerFactory netty) {
            netty.setServiceFilter(filter);
        }
    };
}

Server Implementations

Netty (default)

Configure via spring.grpc.server.*:

spring.grpc.server.port=9090

Shaded Netty

Maven:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-grpc-server</artifactId>
  <exclusions>
    <exclusion>
      <groupId>io.grpc</groupId>
      <artifactId>grpc-netty</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-netty-shaded</artifactId>
</dependency>

Gradle:

dependencies {
  implementation "org.springframework.boot:spring-boot-starter-grpc-server"
  implementation 'io.grpc:grpc-netty-shaded'
  modules {
    module("io.grpc:grpc-netty") {
      replacedBy("io.grpc:grpc-netty-shaded", "Use Netty shaded")
    }
  }
}

Servlet Container

Run gRPC on top of a servlet container with HTTP/2:

server.http2.enabled=true
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-grpc-server</artifactId>
</dependency>
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-servlet-jakarta</artifactId>
</dependency>

spring.grpc.server.* properties are ignored in servlet mode (use server.*), except spring.grpc.server.max-inbound-message-size.

Native Server Inside a Servlet App

To run the native gRPC server on a separate port alongside a web app, exclude grpc-servlet-jakarta or:

spring.grpc.server.servlet.enabled=false

In-Process Server

Include io.grpc:grpc-inprocess:

spring.grpc.server.inprocess.name=my-server

Clients connect using in-process:<name>. The in-process factory runs alongside the regular factory.

Interceptors

Global

@Bean
@Order(100)
@GlobalServerInterceptor
ServerInterceptor myGlobalLoggingInterceptor() {
    return new MyLoggingInterceptor();
}

Filter which global interceptors apply:

@Bean
ServerInterceptorFilter myInterceptorFilter() {
    return (interceptor, service) -> !(interceptor instanceof ExtraThingsInterceptor);
}

@Bean
GrpcServerFactoryCustomizer customizer() {
    return factory -> {
        if (factory instanceof NettyGrpcServerFactory) {
            ((DefaultGrpcServerFactory) factory).setInterceptorFilter(myInterceptorFilter());
        }
    };
}

Per-Service

@Bean
MyServerInterceptor myServerInterceptor() { return new MyServerInterceptor(); }

@GrpcService(interceptors = MyServerInterceptor.class)
BindableService myService() { /* ... */ }

Blend per-service with global (sorted by @Order):

@GrpcService(interceptors = MyServerInterceptor.class, blendWithGlobalInterceptors = true)
BindableService myService() { /* ... */ }

Reflection Service

Autoconfigured when io.grpc:grpc-services is on the classpath:

<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-services</artifactId>
</dependency>

Health Service

Autoconfigured with io.grpc:grpc-services. Enabled automatically when at least one BindableService is present. To force-enable:

spring.grpc.server.health.enabled=true

A HealthStatusManager bean is provided for updating per-service health.

Actuator Integration

When Spring Boot Actuator is present, gRPC health reflects configured health indicators:

spring:
  grpc:
    server:
      health:
        actuator:
          health-indicator-paths:
            - db
            - redis

Client-Side Health Checks

spring:
  grpc:
    client:
      default-channel:
        health:
          enabled: true
      channels:
        one:
          health:
            enabled: true
            service-name: service-one

Requires default-load-balancing-policy=round_robin (Spring gRPC's default).

Observability

Autoconfigured interceptor when Actuator is present:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Exception Handling

@Bean
GrpcExceptionHandler myExceptionHandler() {
    return new MyExceptionHandler();
}

Testing

Add spring-grpc-test and enable the in-process server in tests:

spring.grpc.test.inprocess.enabled=true

Or:

@TestPropertySource(properties = { "spring.grpc.client.default-channel.address=localhost:9090" })
@SpringJUnitConfig(TestConfig.class)
@AutoConfigureInProcessTransport
public class GrpcServerSideTests {

    @Autowired SimpleBlockingStub stub;

    @Test
    void contextLoads() { /* use stub */ }

    @TestConfiguration
    @Import({ GrpcServerService.class })
    @EnableAutoConfiguration
    static class TestConfig { }
}

Security

Netty — TLS and mTLS

spring:
  grpc:
    server:
      ssl:
        bundle: ssltest
  ssl:
    bundle:
      jks:
        ssltest:
          keystore:
            location: classpath:test.jks
            password: secret
            type: JKS
          key:
            password: password

Allow self-signed certs (testing only):

spring.grpc.server.ssl.secure=false

Spring Security (Netty)

With Spring Security on the classpath, HTTP Basic and mTLS preauth are autoconfigured:

@Bean
@GlobalServerInterceptor
AuthenticationProcessInterceptor jwtSecurityFilterChain(GrpcSecurity grpc) throws Exception {
    return grpc
        .authorizeRequests(r -> r
            .methods("Simple/StreamHello").hasAuthority("ROLE_ADMIN")
            .methods("Simple/SayHello").hasAuthority("ROLE_USER")
            .methods("grpc.*/*").permitAll()
            .allRequests().denyAll())
        .httpBasic(withDefaults())
        .preauth(withDefaults())
        .build();
}

OAuth2 Resource Server

JWT:

spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/.well-known/jwks.json

Requires spring-security-oauth2-jose.

Opaque tokens:

spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://example.com/check-token
spring.security.oauth2.resourceserver.opaquetoken.client-id=my-client-id
spring.security.oauth2.resourceserver.opaquetoken.client-secret=my-client-secret

Servlet — Spring Security

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
        .httpBasic(Customizer.withDefaults())
        .authorizeHttpRequests(r -> r.anyRequest().authenticated())
        .build();
}

CSRF is disabled for gRPC by default. To enable:

spring.grpc.server.security.csrf.enabled=true

Per-method access rules:

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http.authorizeHttpRequests(r -> r
        .requestMatchers("/Simple/SayHello").hasRole("USER")
        .requestMatchers("/Simple/StreamHello").hasRole("ADMIN")
        .requestMatchers("/grpc.*/*").permitAll()
        .anyRequest().authenticated())
        .build();
}

docs

client.md

getting-started.md

index.md

server.md

tile.json