{"id":3961,"date":"2026-01-15T10:00:00","date_gmt":"2026-01-15T15:00:00","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=3961"},"modified":"2026-01-15T09:05:24","modified_gmt":"2026-01-15T14:05:24","slug":"architecting-spring-boot-4-with-official-spring-grpc-support","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/spring\/spring4\/architecting-spring-boot-4-with-official-spring-grpc-support\/","title":{"rendered":"Architecting Spring Boot 4 with Official Spring gRPC Support"},"content":{"rendered":"\n<p>For years, the Spring community relied on excellent third-party starters (like <code>net.devh<\/code>) to bridge the gap between Spring Boot and gRPC. With the evolution of Spring Boot 4 and the official <strong>Spring gRPC<\/strong> project, we now have native support that aligns perfectly with Spring&#8217;s dependency injection, observability, and configuration models.<\/p>\n\n\n\n<p>This guide covers how to set up a production-grade Spring gRPC application using <strong>Gradle<\/strong>, specifically focusing on the critical step of generating Java stubs from your <code>.proto<\/code> definitions.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. The Blueprint: Contract-First Design<\/h2>\n\n\n\n<p>In gRPC, the API contract is defined before a single line of Java is written. We use Protocol Buffers (protobuf) to define our services and messages.<\/p>\n\n\n\n<p>Create a file named <code>src\/main\/proto\/calculator.proto<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>syntax = \"proto3\";\n\n\/\/ This option places generated classes in this specific package\noption java_package = \"com.example.grpc.demo.proto\";\n\/\/ This option generates a separate .java file for each class (recommended)\noption java_multiple_files = true;\n\nservice CalculatorService {\n  rpc Add (OperationRequest) returns (OperationResponse);\n}\n\nmessage OperationRequest {\n  int32 number1 = 1;\n  int32 number2 = 2;\n}\n\nmessage OperationResponse {\n  int32 result = 1;\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2. The Build: Gradle Configuration<\/h2>\n\n\n\n<p>The most complex part of gRPC integration is often the build system. We need to configure Gradle to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Download the <code>protoc<\/code> compiler.<\/li>\n\n\n\n<li>Use the <code>grpc-java<\/code> plugin to generate gRPC-specific stubs (Base implementations and Client stubs).<\/li>\n\n\n\n<li>Attach these generated sources to the project&#8217;s source set so your IDE can see them.<\/li>\n<\/ol>\n\n\n\n<p>Here is the <code>build.gradle<\/code> configuration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>plugins {\n    id 'java'\n    id 'org.springframework.boot' version '4.0.0' \/\/ Updated to Spring Boot 4\n    id 'io.spring.dependency-management' version '1.1.7'\n    \/\/ The official protobuf plugin for Gradle\n    id 'com.google.protobuf' version '0.9.4'\n}\n\ngroup = 'com.example'\nversion = '0.0.1-SNAPSHOT'\n\njava {\n    toolchain {\n        \/\/ Spring Boot 4 likely requires Java 21 as the baseline\n        languageVersion = JavaLanguageVersion.of(21)\n    }\n}\n\nrepositories {\n    mavenCentral()\n}\n\n\/\/ Manage versions using the official Spring gRPC BOM\ndependencyManagement {\n    imports {\n        \/\/ Assuming 1.0.0 aligns with the Spring Boot 4 release\n        mavenBom \"org.springframework.grpc:spring-grpc-dependencies:1.0.0\" \n    }\n}\n\ndependencies {\n    \/\/ The new official starter\n    implementation 'org.springframework.grpc:spring-grpc-spring-boot-starter'\n    \n    \/\/ Grpc Netty Shaded is the recommended transport\n    implementation 'io.grpc:grpc-netty-shaded'\n    \n    \/\/ Protobuf dependencies\n    implementation 'io.grpc:grpc-protobuf'\n    implementation 'io.grpc:grpc-stub'\n    \n    \/\/ Helper to prevent annotation issues (Tomcat version bumped for SB 4)\n    compileOnly 'org.apache.tomcat:annotations-api:11.0.0' \n}\n\n\/\/ Configuration for code generation\nprotobuf {\n    protoc {\n        \/\/ download the compiler artifact from maven central\n        artifact = \"com.google.protobuf:protoc:3.25.1\"\n    }\n    plugins {\n        grpc {\n            \/\/ download the grpc-java plugin\n            artifact = \"io.grpc:protoc-gen-grpc-java:1.69.0\"\n        }\n    }\n    generateProtoTasks {\n        all()*.plugins {\n            grpc {}\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Generating the Code<\/h3>\n\n\n\n<p>To generate the Java files, simply run the build. The plugin hooks into the build lifecycle.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/gradlew build\n<\/code><\/pre>\n\n\n\n<p><em>Tip: If your IDE doesn&#8217;t see the generated classes immediately, look for the <code>build\/generated\/source\/proto<\/code> directory and mark it as a &#8220;Generated Source Root&#8221;.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. The Server: Implementing the Service<\/h2>\n\n\n\n<p>With the official Spring gRPC starter, we no longer need special <code>@GrpcService<\/code> annotations from third-party libraries. We can use the standard Spring <code>@Service<\/code> annotation.<\/p>\n\n\n\n<p>The starter automatically scans for beans that extend <code>BindableService<\/code> (which your generated <code>ImplBase<\/code> class does).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.grpc.demo.service;\n\nimport com.example.grpc.demo.proto.CalculatorServiceGrpc;\nimport com.example.grpc.demo.proto.OperationRequest;\nimport com.example.grpc.demo.proto.OperationResponse;\nimport io.grpc.stub.StreamObserver;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class CalculatorServiceImpl extends CalculatorServiceGrpc.CalculatorServiceImplBase {\n\n    @Override\n    public void add(OperationRequest request, StreamObserver&lt;OperationResponse&gt; responseObserver) {\n        int result = request.getNumber1() + request.getNumber2();\n\n        OperationResponse response = OperationResponse.newBuilder()\n                .setResult(result)\n                .build();\n\n        \/\/ Send the response\n        responseObserver.onNext(response);\n        \/\/ Complete the RPC call\n        responseObserver.onCompleted();\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4. The Client: Consumption<\/h2>\n\n\n\n<p>To consume the service, we can use the <code>GrpcChannelFactory<\/code> provided by the starter to create channels. As an architect, you might prefer defining these clients as explicit Beans for better testability and injection control.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.grpc.demo.config;\n\nimport com.example.grpc.demo.proto.CalculatorServiceGrpc;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.grpc.client.GrpcChannelFactory;\n\n@Configuration\npublic class GrpcClientConfig {\n\n    @Bean\n    public CalculatorServiceGrpc.CalculatorServiceBlockingStub calculatorClient(GrpcChannelFactory channelFactory) {\n        \/\/ \"0.0.0.0:9090\" is the default server address; in prod, this would be a service name\n        return CalculatorServiceGrpc.newBlockingStub(channelFactory.createChannel(\"0.0.0.0:9090\"));\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>You can now inject <code>CalculatorServiceBlockingStub<\/code> into any controller or service just like a standard Spring bean.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>The official <code>spring-grpc<\/code> support simplifies the ecosystem significantly. By combining the power of Gradle&#8217;s protobuf plugin with Spring Boot 4&#8217;s auto-configuration, we get a type-safe, high-performance RPC layer that feels entirely native to the Spring developer experience.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For years, the Spring community relied on excellent third-party starters (like net.devh) to bridge the gap between Spring Boot and gRPC. With the evolution of Spring Boot 4 and the official Spring gRPC project, we now have native support that aligns perfectly with Spring&#8217;s dependency injection, observability, and configuration models. This guide covers how to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3962,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[483],"tags":[491,69,319],"series":[],"class_list":["post-3961","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spring4","tag-grpc","tag-java-2","tag-spring"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif","jetpack-related-posts":[{"id":3912,"url":"https:\/\/www.mymiller.name\/wordpress\/uncategorized\/spring-boot-4-0-whats-next-for-the-modern-java-architect\/","url_meta":{"origin":3961,"position":0},"title":"Spring Boot 4.0: What&#8217;s Next for the Modern Java Architect?","author":"Jeffery Miller","date":"September 24, 2025","format":false,"excerpt":"A Forward-Looking Comparison of Spring Boot 3.x and 4.0 Staying on top of the rapidly evolving Java ecosystem is paramount for any software architect. The shift from Spring Boot 2.x to 3.x brought significant changes, notably the move to Jakarta EE. Now, with the horizon of Spring Boot 4.0 and\u2026","rel":"","context":"Similar post","block_context":{"text":"Similar post","link":""},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/09\/per-2056740_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/09\/per-2056740_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/09\/per-2056740_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/09\/per-2056740_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/09\/per-2056740_1280.avif 3x"},"classes":[]},{"id":3951,"url":"https:\/\/www.mymiller.name\/wordpress\/java\/scaling-streams-mastering-virtual-threads-in-spring-boot-4-and-java-25\/","url_meta":{"origin":3961,"position":1},"title":"Scaling Streams: Mastering Virtual Threads in Spring Boot 4 and Java 25","author":"Jeffery Miller","date":"December 22, 2025","format":false,"excerpt":"As a software architect, I\u2019ve seen the industry shift from heavy platform threads to reactive streams, and finally to the \"best of both worlds\": Virtual Threads. With the recent release of Spring Boot 4.0 and Java 25 (LTS), Project Loom's innovations have officially become the bedrock of high-concurrency enterprise Java.\u2026","rel":"","context":"In &quot;JAVA&quot;","block_context":{"text":"JAVA","link":"https:\/\/www.mymiller.name\/wordpress\/category\/java\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif 3x"},"classes":[]},{"id":3539,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_databases\/spring-data-cassandra-simplifying-java-development-with-apache-cassandra\/","url_meta":{"origin":3961,"position":2},"title":"Spring Data Cassandra: Simplifying Java Development with Apache Cassandra","author":"Jeffery Miller","date":"September 22, 2025","format":false,"excerpt":"Apache Cassandra is a powerful NoSQL database known for its scalability and high availability. Spring Data Cassandra seamlessly integrates Spring\u2019s familiar programming model with Cassandra, boosting developer productivity. Why Spring Data Cassandra? Simplified Configuration: Spring Boot auto-configuration minimizes manual setup. Object-Relational Mapping (ORM): Easily map Java objects to Cassandra tables.\u2026","rel":"","context":"In &quot;Spring Databases&quot;","block_context":{"text":"Spring Databases","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_databases\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3632,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_sockets\/real-time-communication-with-spring-boot-websockets-a-comprehensive-guide\/","url_meta":{"origin":3961,"position":3},"title":"Real-Time Communication with Spring Boot WebSockets: A Comprehensive Guide","author":"Jeffery Miller","date":"September 22, 2025","format":false,"excerpt":"In the world of modern web applications, real-time communication has become a necessity. Whether it\u2019s live chat, collaborative editing, or real-time data updates, WebSockets have emerged as the go-to technology to enable seamless, bidirectional communication between the browser and server. In this article, we\u2019ll dive into how to harness the\u2026","rel":"","context":"In &quot;Spring Sockets&quot;","block_context":{"text":"Spring Sockets","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_sockets\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/07\/cpu-4393380_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/07\/cpu-4393380_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/07\/cpu-4393380_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/07\/cpu-4393380_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/07\/cpu-4393380_1280-jpg.avif 3x"},"classes":[]},{"id":3919,"url":"https:\/\/www.mymiller.name\/wordpress\/spring\/unleashing-scalability-spring-boot-and-java-virtual-threads\/","url_meta":{"origin":3961,"position":4},"title":"Unleashing Scalability: Spring Boot and Java Virtual Threads","author":"Jeffery Miller","date":"November 18, 2025","format":false,"excerpt":"Java has long been a powerhouse for enterprise applications, and Spring Boot has made developing them an absolute dream. But even with Spring Boot's magic, a persistent bottleneck has challenged developers: the overhead of traditional thread-per-request models when dealing with blocking I\/O operations. Think database calls, external API integrations, or\u2026","rel":"","context":"In &quot;Spring&quot;","block_context":{"text":"Spring","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/fiber-4814456_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/fiber-4814456_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/fiber-4814456_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/fiber-4814456_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/fiber-4814456_1280.avif 3x"},"classes":[]},{"id":3569,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_ai\/integrating-prolog-with-spring-boot\/","url_meta":{"origin":3961,"position":5},"title":"Integrating Prolog with Spring Boot","author":"Jeffery Miller","date":"September 22, 2025","format":false,"excerpt":"Prolog, a declarative logic programming language, shines in solving specific types of problems that require knowledge representation and logical inference. Integrating Prolog with Spring Boot can bring the power of logic programming to your Java applications. 1. Setting Up Your Environment Add JPL Dependency: Include the Java Prolog Interface (JPL)\u2026","rel":"","context":"In &quot;Spring AI&quot;","block_context":{"text":"Spring AI","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_ai\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_avkkoeavkkoeavkk.jpg?fit=1200%2C1200&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_avkkoeavkkoeavkk.jpg?fit=1200%2C1200&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_avkkoeavkkoeavkk.jpg?fit=1200%2C1200&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_avkkoeavkkoeavkk.jpg?fit=1200%2C1200&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_avkkoeavkkoeavkk.jpg?fit=1200%2C1200&ssl=1&resize=1050%2C600 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3961","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=3961"}],"version-history":[{"count":1,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3961\/revisions"}],"predecessor-version":[{"id":3963,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3961\/revisions\/3963"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/3962"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=3961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=3961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=3961"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=3961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}