diff --git a/basic/grpc-server/README.md b/basic/grpc-server/README.md
new file mode 100644
index 000000000..da871a95e
--- /dev/null
+++ b/basic/grpc-server/README.md
@@ -0,0 +1,48 @@
+gRPC Server Sample
+==================
+
+This example demonstrates the use of **gRPC Inbound Gateway** with Spring Integration.
+
+It uses Java configuration and showcases various gRPC communication patterns including:
+
+* Unary RPC - client sends a single request and receives a single response
+* Server streaming RPC - client sends a single request and receives a stream of responses
+
+The sample uses a simple greeting service defined in a Protocol Buffers (protobuf) file that demonstrates how Spring Integration can handle gRPC service implementations through the `GrpcInboundGateway`.
+
+## Running the sample
+
+### Command Line Using Gradle
+
+To start the gRPC server application using Spring Boot run the following:
+
+ $ gradlew :grpc-server:bootRun
+
+To test the gRPC server application run the gRPC client sample using Spring Boot run as follows:
+
+ $ gradlew :grpc-client:bootRun
+
+You should see output that looks like the following:
+
+```log
+2026-03-25T11:10:18.538-04:00 INFO 91646 --- [ main] o.s.i.s.g.c.GrpcClientConfiguration : Single response reply: Hello Jack
+2026-03-25T11:10:18.544-04:00 INFO 91646 --- [ault-executor-0] o.s.i.s.g.c.GrpcClientConfiguration : Stream received reply: Hello Stream Jane
+2026-03-25T11:10:18.545-04:00 INFO 91646 --- [ault-executor-0] o.s.i.s.g.c.GrpcClientConfiguration : Stream received reply: Hello again!
+```
+
+## Testing the sample
+
+The sample includes JUnit tests that demonstrate the various gRPC communication patterns:
+
+ $ gradlew :grpc-server:test
+
+### Output
+
+The tests use an in-process gRPC server for testing, configured via `spring.grpc.server.inprocess.name` and `spring.grpc.client.default-channel.address`. When running the unary test, a request with name "Jack" returns:
+
+ Hello Jack
+
+When running the server streaming test, a request with name "Jane" returns multiple responses:
+
+ Hello Stream Jane
+ Hello again!
diff --git a/basic/grpc-server/pom.xml b/basic/grpc-server/pom.xml
new file mode 100644
index 000000000..0a1afc44e
--- /dev/null
+++ b/basic/grpc-server/pom.xml
@@ -0,0 +1,406 @@
+
+
+ 4.0.0
+ org.springframework.integration.samples
+ grpc-server
+ 7.1.0
+ jar
+ https://github.com/spring-projects/spring-integration-samples
+
+ Spring IO
+ https://spring.io/projects/spring-integration
+
+
+
+ Apache License, Version 2.0
+ https://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+
+ artembilan
+ Artem Bilan
+ artem.bilan@broadcom.com
+
+ project lead
+
+
+
+ garyrussell
+ Gary Russell
+ github@gprussell.net
+
+ project lead emeritus
+
+
+
+ markfisher
+ Mark Fisher
+ mark.ryan.fisher@gmail.com
+
+ project founder and lead emeritus
+
+
+
+ cppwfs
+ Glenn Renfro
+ glenn.renfro@broadcom.com
+
+ project committer
+
+
+
+
+ scm:git:scm:git:git://github.com/spring-projects/spring-integration-samples.git
+ scm:git:scm:git:ssh://git@github.com:spring-projects/spring-integration-samples.git
+ https://github.com/spring-projects/spring-integration-samples
+
+
+ GitHub
+ https://github.com/spring-projects/spring-integration-samples/issues
+
+
+
+ org.springframework.boot
+ spring-boot-starter-integration
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-grpc-server
+ runtime
+
+
+ org.springframework.integration
+ spring-integration-grpc
+ runtime
+
+
+ org.hamcrest
+ hamcrest-library
+ 2.2
+ test
+
+
+ org.mockito
+ mockito-core
+ 5.21.0
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.springframework.integration
+ spring-integration-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-grpc-test
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ runtime
+
+
+ org.junit.platform
+ junit-platform-launcher
+ runtime
+
+
+
+
+
+ org.springframework.integration
+ spring-integration-jdbc
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-ws
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-redis
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-r2dbc
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-rsocket
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-event
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-cassandra
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-scripting
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-websocket
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-graphql
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-jpa
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-test
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-cloudevents
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-http
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-zookeeper
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-ip
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-mail
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-camel
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-mongodb
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-stream
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-stomp
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-file
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-syslog
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-smb
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-jmx
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-webflux
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-sftp
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-mqtt
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-ftp
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-kafka
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-groovy
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-xmpp
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-feed
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-debezium
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-zeromq
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-hazelcast
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-test-support
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-amqp
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-grpc
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-xml
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-core
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-zip
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.integration
+ spring-integration-jms
+ 7.1.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ 4.1.0-SNAPSHOT
+ import
+ pom
+
+
+ org.junit
+ junit-bom
+ 6.0.2
+ import
+ pom
+
+
+ tools.jackson
+ jackson-bom
+ 3.0.3
+ import
+ pom
+
+
+ com.fasterxml.jackson
+ jackson-bom
+ 2.21.0
+ import
+ pom
+
+
+ org.springframework
+ spring-framework-bom
+ 7.0.5
+ import
+ pom
+
+
+ org.springframework.integration
+ spring-integration-bom
+ 7.1.0-SNAPSHOT
+ import
+ pom
+
+
+
+
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 4.1.0-SNAPSHOT
+
+
+
+ repo.spring.io.milestone
+ Spring Framework Maven Milestone Repository
+ https://repo.spring.io/milestone
+
+
+ repo.spring.io.snapshot
+ Spring Framework Maven Snapshot Repository
+ https://repo.spring.io/snapshot
+
+
+
diff --git a/basic/grpc-server/src/main/java/org/springframework/integration/samples/grpc/server/Application.java b/basic/grpc-server/src/main/java/org/springframework/integration/samples/grpc/server/Application.java
new file mode 100644
index 000000000..23a384d01
--- /dev/null
+++ b/basic/grpc-server/src/main/java/org/springframework/integration/samples/grpc/server/Application.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2026-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.integration.samples.grpc.server;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * The Spring Boot application to demonstrate Spring Integration's
+ * {@link org.springframework.integration.grpc.inbound.GrpcInboundGateway} support.
+ *
+ * @author Glenn Renfro
+ */
+@SpringBootApplication
+public class Application {
+
+ /**
+ * Main method to run the Spring Boot application.
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/basic/grpc-server/src/main/java/org/springframework/integration/samples/grpc/server/GrpcServerConfiguration.java b/basic/grpc-server/src/main/java/org/springframework/integration/samples/grpc/server/GrpcServerConfiguration.java
new file mode 100644
index 000000000..f9c542b5f
--- /dev/null
+++ b/basic/grpc-server/src/main/java/org/springframework/integration/samples/grpc/server/GrpcServerConfiguration.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2026-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.integration.samples.grpc.server;
+
+import reactor.core.publisher.Flux;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.dsl.IntegrationFlow;
+import org.springframework.integration.grpc.GrpcHeaders;
+import org.springframework.integration.grpc.inbound.GrpcInboundGateway;
+import org.springframework.messaging.Message;
+
+/**
+ * Configures {@link GrpcInboundGateway}.
+ *
+ * Demonstrates various gRPC communication patterns:
+ *
+ * - Unary RPC (SayHello)
+ * - Server streaming RPC (StreamHello)
+ *
+ *
+ * @author Glenn Renfro
+ */
+@Configuration(proxyBeanMethods = false)
+public class GrpcServerConfiguration {
+
+ /**
+ * Create a gRPC inbound gateway for the Simple service.
+ * @return the configured gRPC inbound gateway
+ */
+ @Bean
+ GrpcInboundGateway helloWorldService() {
+ return new GrpcInboundGateway(SimpleGrpc.SimpleImplBase.class);
+ }
+
+ /**
+ * Create the main integration flow that routes gRPC requests to appropriate handlers
+ * based on the service method name.
+ * @param helloWorldService the gRPC inbound gateway
+ * @return the configured integration flow
+ */
+ @Bean
+ IntegrationFlow grpcIntegrationFlow(GrpcInboundGateway helloWorldService) {
+ return IntegrationFlow.from(helloWorldService)
+ .route(Message.class, message ->
+ message.getHeaders().get(GrpcHeaders.SERVICE_METHOD, String.class),
+ router -> router
+
+ .subFlowMapping("SayHello", flow -> flow
+ .transform(this::requestReply))
+
+ .subFlowMapping("StreamHello", flow -> flow
+ .transform(this::streamReply))
+ )
+ .get();
+ }
+
+ /**
+ * Handle unary and bidirectional streaming requests by creating a simple greeting reply.
+ * @param helloRequest the incoming request
+ * @return the greeting reply
+ */
+ private HelloReply requestReply(HelloRequest helloRequest) {
+ return newHelloReply("Hello " + helloRequest.getName());
+ }
+
+ /**
+ * Handle server streaming requests by emitting multiple greeting replies.
+ * @param helloRequest the incoming request
+ * @return a flux of greeting replies
+ */
+ private Flux streamReply(HelloRequest helloRequest) {
+ return Flux.just(
+ newHelloReply("Hello Stream " + helloRequest.getName()),
+ newHelloReply("Hello again!"));
+ }
+
+ /**
+ * Create a new HelloReply with the specified message.
+ * @param message the message to include in the reply
+ * @return the constructed HelloReply
+ */
+ private static HelloReply newHelloReply(String message) {
+ return HelloReply.newBuilder().setMessage(message).build();
+ }
+
+}
+
diff --git a/basic/grpc-server/src/main/proto/hello.proto b/basic/grpc-server/src/main/proto/hello.proto
new file mode 100644
index 000000000..cf838730b
--- /dev/null
+++ b/basic/grpc-server/src/main/proto/hello.proto
@@ -0,0 +1,23 @@
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "org.springframework.integration.samples.grpc.server";
+option java_outer_classname = "HelloWorldProto";
+
+// The greeting service definition.
+service Simple {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {
+ }
+ rpc StreamHello(HelloRequest) returns (stream HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+}
+
+// The response message containing the greetings
+message HelloReply {
+ string message = 1;
+}
diff --git a/basic/grpc-server/src/test/java/org/springframework/integration/samples/grpc/server/GrpcServerTests.java b/basic/grpc-server/src/test/java/org/springframework/integration/samples/grpc/server/GrpcServerTests.java
new file mode 100644
index 000000000..7433671be
--- /dev/null
+++ b/basic/grpc-server/src/test/java/org/springframework/integration/samples/grpc/server/GrpcServerTests.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2026-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.integration.samples.grpc.server;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+import io.grpc.stub.StreamObserver;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.grpc.client.ImportGrpcClients;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test the gRPC server demonstrating various communication patterns.
+ *
+ * @author Glenn Renfro
+ */
+@SpringBootTest({
+ "spring.grpc.server.inprocess.name=test"
+})
+@ImportGrpcClients(
+ types = {
+ SimpleGrpc.SimpleBlockingStub.class,
+ SimpleGrpc.SimpleStub.class
+ },
+ target = "in-process:test"
+)
+class GrpcServerTests {
+
+ private static final Log LOGGER = LogFactory.getLog(GrpcServerTests.class);
+
+ /**
+ * The blocking stub for the Simple service.
+ */
+ @Autowired
+ SimpleGrpc.SimpleBlockingStub simpleBlockingStub;
+
+ /**
+ * The asynchronous stub for the Simple service.
+ */
+ @Autowired
+ SimpleGrpc.SimpleStub simpleStub;
+
+ /**
+ * Test unary RPC where client sends a single request and receives a single response.
+ */
+ @Test
+ void unary() {
+ HelloReply reply = this.simpleBlockingStub.sayHello(HelloRequest.newBuilder().setName("Jack").build());
+ assertThat(reply).extracting(HelloReply::getMessage).isEqualTo("Hello Jack");
+ }
+
+ /**
+ * Test server streaming RPC where client sends a single request and receives
+ * a stream of responses.
+ * @throws InterruptedException if the test is interrupted while waiting
+ */
+ @Test
+ void serverStreaming() throws InterruptedException {
+ List replies = new ArrayList<>();
+ CountDownLatch replyLatch = new CountDownLatch(1);
+ this.simpleStub.streamHello(HelloRequest.newBuilder().setName("Jane").build(),
+ replyObserver(replies::add, replyLatch));
+
+ assertThat(replyLatch.await(10_000, TimeUnit.MILLISECONDS)).isTrue();
+
+ assertThat(replies)
+ .extracting(HelloReply::getMessage)
+ .containsOnly("Hello Stream Jane", "Hello again!");
+ }
+
+ /**
+ * Create a stream observer for handling asynchronous gRPC responses.
+ * @param the response type
+ * @param replyConsumer consumer to process each reply
+ * @param completionLatch latch to signal completion
+ * @return the configured stream observer
+ */
+ private static StreamObserver replyObserver(Consumer replyConsumer,
+ CountDownLatch completionLatch) {
+
+ return new StreamObserver<>() {
+
+ @Override
+ public void onNext(R value) {
+ replyConsumer.accept(value);
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ LOGGER.error("Error occurred while obtaining items from the stream", t);
+ completionLatch.countDown();
+ }
+
+ @Override
+ public void onCompleted() {
+ completionLatch.countDown();
+ }
+
+ };
+ }
+
+}
+
diff --git a/build.gradle b/build.gradle
index 252742506..059126e98 100644
--- a/build.gradle
+++ b/build.gradle
@@ -887,14 +887,12 @@ project('grpc-client') {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-integration'
- implementation "org.springframework.boot:spring-boot-starter-grpc-client"
+ implementation 'org.springframework.boot:spring-boot-starter-grpc-client'
implementation 'org.springframework.integration:spring-integration-grpc'
//Test
- testImplementation "org.springframework.boot:spring-boot-starter-grpc-test"
-
- configurations {
- testRuntimeOnly.exclude group: 'io.grpc', module: 'grpc-netty'
+ testImplementation ('org.springframework.boot:spring-boot-starter-grpc-test') {
+ exclude group: 'io.grpc', module: 'grpc-netty' //TODO Review this exclusion prior to 7.1.0 release
}
}
@@ -926,16 +924,69 @@ project('grpc-client') {
}
springBoot {
- mainClass = 'org.springframework.integration.samples.Application'
+ mainClass = 'org.springframework.integration.samples.grpc.client.Application'
}
tasks.register('run', JavaExec) {
- mainClass = 'org.springframework.integration.samples.Application'
+ mainClass = 'org.springframework.integration.samples.grpc.client.Application'
classpath = sourceSets.main.runtimeClasspath
}
}
+project('grpc-server') {
+ description = 'gRPC server Basic Sample'
+
+ apply plugin: 'org.springframework.boot'
+ apply plugin: 'com.google.protobuf'
+
+ dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-integration'
+ implementation 'org.springframework.boot:spring-boot-starter-grpc-server'
+ implementation 'org.springframework.integration:spring-integration-grpc'
+
+ //Test
+ testImplementation ('org.springframework.boot:spring-boot-starter-grpc-test') {
+ exclude group: 'io.grpc', module: 'grpc-netty' //TODO Review this exclusion prior to 7.1.0 release
+ }
+ }
+
+ protobuf {
+ protoc {
+ artifact = "com.google.protobuf:protoc:$protobufVersion"
+ }
+ plugins {
+ grpc {
+ artifact = "io.grpc:protoc-gen-grpc-java:$grpcVersion"
+ }
+ }
+ generateProtoTasks {
+ all()*.plugins {
+ grpc {
+ option '@generated=omit'
+ }
+ }
+ }
+ }
+// Exclude generated protobuf/grpc code from checkstyle
+ checkstyleMain {
+ source = fileTree('src/main/java')
+ }
+
+ checkstyleTest {
+ source = fileTree('src/test/java')
+ }
+
+ springBoot {
+ mainClass = 'org.springframework.integration.samples.grpc.server.Application'
+ }
+
+ tasks.register('run', JavaExec) {
+ mainClass = 'org.springframework.integration.samples.grpc.server.Application'
+ classpath = sourceSets.main.runtimeClasspath
+ }
+}
+
project('jdbc') {
description = 'JDBC Basic Sample'