Spring gRPC Documentation

repository·main·Indexed 19 days ago

https://github.com/spring-projects/spring-grpc

Spring gRPC provides a Spring-friendly API and abstractions for developing gRPC applications, featuring a core library for dependency injection and a Spring Boot starter for autoconfiguration. It supports gRPC server and client implementation, named channel configuration via application.properties, OAuth2 authentication, and native image support via GraalVM.

Tokens
13.8K
Snippets
50
Records
81
Agent score
61%

What's inside Spring gRPC

  1. Overview of Spring gRPC

    main

    Spring gRPC provides a Spring-friendly API and abstractions for developing gRPC applications. It consists of two main components:

    1. Core Library: Provides abstractions to make working with gRPC and dependency injection seamless.
    2. Spring Boot Starter: Enables rapid development in Spring Boot applications through autoconfiguration and dedicated configuration properties.
  2. Filter which services are bound to a gRPC server

    main

    By default, all BindableService beans are bound to all running gRPC servers. You can control this by registering a ServerServiceDefinitionFilter bean.

    For InProcessGrpcServerFactory, the filter is applied automatically. For other factories (like NettyGrpcServerFactory), you must provide a GrpcServerFactoryCustomizer to register the filter.

    // 1. Define the filter
    @Bean
    ServerServiceDefinitionFilter myServiceFilter() {
        return (serviceDefinition, __) ->
                !Set.of(HealthGrpc.SERVICE_NAME, ServerReflectionGrpc.SERVICE_NAME)
                        .contains(serviceDefinition.getServiceDescriptor().getName());
    }
    
    // 2. Apply it via a customizer (required for Netty)
    @Bean
    GrpcServerFactoryCustomizer myServerFactoryCustomizer(ServerServiceDefinitionFilter myServiceFilter) {
        return factory -> {
            if (factory instanceof NettyGrpcServerFactory nettyServerFactory) {
                nettyServerFactory.setServiceFilter(myServiceFilter);
            }
        };
    }
  3. Run gRPC in a Servlet Container

    main

    You can run a gRPC server inside any servlet container (like Tomcat or Jetty).

    Requirements & Behavior:

    • HTTP/2: You must enable HTTP/2 on the servlet container using its native configuration. Spring Boot provides auto-configuration for Tomcat and Jetty.
    • Path Mapping: The servlet maps HTTP POST requests to service paths using the pattern /<service-name>/*.
    • Limitations: The servlet-based server has fewer configuration options than native builders because the container manages the network layer. Some ServerBuilderCustomizer features may throw exceptions at runtime.
    • Native Coexistence: A native gRPC server (e.g., Netty) can run alongside a servlet container on a different port.
  4. Add Client Interceptors

    main

    Interceptors can be applied at three levels:

    1. Global: Register a bean annotated with @GlobalClientInterceptor. These are applied to all channels in @Order sequence.
    2. Per-Channel: Pass interceptors via ChannelBuilderOptions.withInterceptors(List.of(...)) when creating a channel. These are applied after global interceptors.
    3. Blended: By default, global interceptors run first, then per-channel interceptors. If you set ChannelBuilderOptions.withInterceptorsMerge(true), all interceptors (global and per-channel) are combined and sorted together by their @Order.

    Note: For proper merging, per-channel interceptors should be beans with @Order or implement Ordered.

    // Global interceptor registration
    @Bean
    @Order(100)
    @GlobalClientInterceptor
    ClientInterceptor globalLoggingInterceptor() {
        return new LoggingInterceptor();
    }
    
    // Per-channel interceptor registration
    @Bean
    SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channelFactory) {
        ClientInterceptor interceptor1 = getChannelInterceptor1();
        ChannelBuilderOptions options = ChannelBuilderOptions.defaults()
                .withInterceptors(List.of(interceptor1));
        ManagedChannel channel = channelFactory.createChannel("localhost", options);
        return SimpleGrpc.newBlockingStub(channel);
    }
  5. Understand Maven Parent overrides in this project

    main

    This project uses empty overrides for <license> and <developers> elements in its POM file. This is done to prevent unwanted inheritance of these specific elements from the parent POM.

    Note: If you manually change the parent of this project and wish to inherit license and developer information, you must remove these empty overrides from your project's POM.

  6. Quickstart: Create a working Spring gRPC service

    main

    To quickly set up a Spring gRPC service, follow these steps:

    1. Initialize Project: Use Spring Initializr and select the gRPC dependency.
    2. Define Proto: Create src/main/proto/hello.proto. Ensure the java_package matches your project's package name.
    3. Generate Stubs: Run ./mvnw clean package (Maven) or ./gradlew build (Gradle) to generate Java source code from your .proto file.
    4. Implement Service: Create a class annotated with @Service that extends the generated ImplBase class.
    5. Run: Execute the application using ./mvnw spring-boot:run or ./gradlew bootRun.

    Generated Source Locations:

    • Maven: target/generated-sources/protobuf/grpc-java and target/generated-sources/protobuf/java
    • Gradle: build/generated/source/proto/main/grpc and build/generated/source/proto/main/java

    Note: You may need to manually mark these folders as 'Generated Source Roots' in your IDE (e.g., IntelliJ IDEA).

    syntax = "proto3";
    
    option java_multiple_files = true;
    option java_package = "<your-package-name-goes-here>.proto";
    option java_outer_classname = "HelloWorldProto";
    
    service Simple {
      rpc SayHello(HelloRequest) returns (HelloReply) {}
      rpc StreamHello(HelloRequest) returns (stream HelloReply) {}
    }
    
    message HelloRequest {
      string name = 1;
    }
    
    message HelloReply {
      string message = 1;
    }
  7. Quickstart: Create a Spring gRPC service

    main

    To quickly set up a working gRPC service with Spring gRPC:

    1. Generate Project: Use Spring Initializr and select the gRPC dependency.
    2. Define Proto: Create src/main/proto/hello.proto. Ensure the java_package matches your project's package name.
    3. Generate Stubs: Run ./mvnw clean package (Maven) or ./gradlew build (Gradle).
      • Maven paths: target/generated-sources/protobuf/grpc-java and target/generated-sources/protobuf/java.
      • Gradle paths: build/generated/source/proto/main/grpc and build/generated/source/proto/main/java.
      • Note: You may need to mark these as 'Generated Source Roots' in your IDE.
    4. Implement Service: Create a class annotated with @Service that extends the generated ImplBase class.
    5. Run: Use ./mvnw spring-boot:run or ./gradlew bootRun.
    syntax = "proto3";
    
    option java_multiple_files = true;
    option java_package = "<your-package-name-goes-here>.proto";
    option java_outer_classname = "HelloWorldProto";
    
    service Simple {
      rpc SayHello(HelloRequest) returns (HelloReply) {}
      rpc StreamHello(HelloRequest) returns (stream HelloReply) {}
    }
    
    message HelloRequest {
      string name = 1;
    }
    
    message HelloReply {
      string message = 1;
    }