Spring gRPC reference documentation covering server, client, security, and configuration
92
Pending
Does it follow best practices?
Impact
92%
2.19xAverage score across 3 eval scenarios
Pending
The risk profile of this skill
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.
@Service
public class MyGrpcService extends MyServiceGrpc.MyServiceImplBase {
// implementation
}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);
}
};
}Configure via spring.grpc.server.*:
spring.grpc.server.port=9090Maven:
<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")
}
}
}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 (useserver.*), exceptspring.grpc.server.max-inbound-message-size.
To run the native gRPC server on a separate port alongside a web app, exclude grpc-servlet-jakarta or:
spring.grpc.server.servlet.enabled=falseInclude io.grpc:grpc-inprocess:
spring.grpc.server.inprocess.name=my-serverClients connect using in-process:<name>. The in-process factory runs alongside the regular factory.
@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());
}
};
}@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() { /* ... */ }Autoconfigured when io.grpc:grpc-services is on the classpath:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-services</artifactId>
</dependency>Autoconfigured with io.grpc:grpc-services. Enabled automatically when at least one BindableService is present. To force-enable:
spring.grpc.server.health.enabled=trueA HealthStatusManager bean is provided for updating per-service health.
When Spring Boot Actuator is present, gRPC health reflects configured health indicators:
spring:
grpc:
server:
health:
actuator:
health-indicator-paths:
- db
- redisspring:
grpc:
client:
default-channel:
health:
enabled: true
channels:
one:
health:
enabled: true
service-name: service-oneRequires default-load-balancing-policy=round_robin (Spring gRPC's default).
Autoconfigured interceptor when Actuator is present:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>@Bean
GrpcExceptionHandler myExceptionHandler() {
return new MyExceptionHandler();
}Add spring-grpc-test and enable the in-process server in tests:
spring.grpc.test.inprocess.enabled=trueOr:
@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 { }
}spring:
grpc:
server:
ssl:
bundle: ssltest
ssl:
bundle:
jks:
ssltest:
keystore:
location: classpath:test.jks
password: secret
type: JKS
key:
password: passwordAllow self-signed certs (testing only):
spring.grpc.server.ssl.secure=falseWith 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();
}JWT:
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/.well-known/jwks.jsonRequires 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@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=truePer-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();
}evals