From 3d289869b15faf781a7d79e610892782f91fbcb7 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Fri, 20 Mar 2026 10:14:41 -0400 Subject: [PATCH 1/3] Add gRPC server sample with Spring Integration Introduce a new basic sample demonstrating the GrpcInboundGateway. This provides users with a reference implementation for handling both unary and server streaming gRPC requests using Spring Boot. - Add grpc-server module with protobuf definitions - Configure GrpcInboundGateway to route by service method - Include tests demonstrating in-process gRPC communication --- basic/grpc-server/README.md | 36 ++ basic/grpc-server/pom.xml | 406 ++++++++++++++++++ .../samples/grpc/server/Application.java | 39 ++ .../grpc/server/GrpcServerConfiguration.java | 103 +++++ basic/grpc-server/src/main/proto/hello.proto | 23 + .../src/main/resources/application.properties | 1 + .../samples/grpc/server/GrpcServerTests.java | 127 ++++++ build.gradle | 57 ++- 8 files changed, 791 insertions(+), 1 deletion(-) create mode 100644 basic/grpc-server/README.md create mode 100644 basic/grpc-server/pom.xml create mode 100644 basic/grpc-server/src/main/java/org/springframework/integration/samples/grpc/server/Application.java create mode 100644 basic/grpc-server/src/main/java/org/springframework/integration/samples/grpc/server/GrpcServerConfiguration.java create mode 100644 basic/grpc-server/src/main/proto/hello.proto create mode 100644 basic/grpc-server/src/main/resources/application.properties create mode 100644 basic/grpc-server/src/test/java/org/springframework/integration/samples/grpc/server/GrpcServerTests.java diff --git a/basic/grpc-server/README.md b/basic/grpc-server/README.md new file mode 100644 index 000000000..f67b43828 --- /dev/null +++ b/basic/grpc-server/README.md @@ -0,0 +1,36 @@ +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 + + $ gradlew :grpc-server:bootRun + +This will start the gRPC server application using Spring Boot. + +## 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..69c4d8118 --- /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; + +/** + * 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..f2fa48ae4 --- /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; + +/** + * Configure {@link org.springframework.integration.grpc.inbound.GrpcInboundGateway}. + *

+ * Demonstrate various gRPC communication patterns: + *

+ * + * @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/main/resources/application.properties b/basic/grpc-server/src/main/resources/application.properties new file mode 100644 index 000000000..604c08e93 --- /dev/null +++ b/basic/grpc-server/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.grpc.client.default-channel.address=static://localhost:9090 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..f3c841fee --- /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", + "spring.grpc.client.channels.spring-integration.address=in-process: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.get(0)).extracting(HelloReply::getMessage).isEqualTo("Hello Stream Jane"); + assertThat(replies.get(1)).extracting(HelloReply::getMessage).isEqualTo("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..8b711d03e 100644 --- a/build.gradle +++ b/build.gradle @@ -887,7 +887,7 @@ 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 @@ -936,6 +936,61 @@ project('grpc-client') { } +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" + + configurations { + testRuntimeOnly.exclude group: 'io.grpc', module: 'grpc-netty' + } + } + + 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' From d2348ce5cbae4cadab2b78a53111baef97889419 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Wed, 25 Mar 2026 11:32:54 -0400 Subject: [PATCH 2/3] Add grpc-client using grpc-server in readme - Remove unused properties from application.properties and test - Simplify exclusion for netty in tests - Update javadoc for Applicaition.java to be 3rd person narrative --- basic/grpc-server/README.md | 14 +++++++++++++- .../samples/grpc/server/Application.java | 2 +- .../src/main/resources/application.properties | 1 - .../samples/grpc/server/GrpcServerTests.java | 8 ++++---- build.gradle | 16 ++++++---------- 5 files changed, 24 insertions(+), 17 deletions(-) delete mode 100644 basic/grpc-server/src/main/resources/application.properties diff --git a/basic/grpc-server/README.md b/basic/grpc-server/README.md index f67b43828..da871a95e 100644 --- a/basic/grpc-server/README.md +++ b/basic/grpc-server/README.md @@ -14,9 +14,21 @@ The sample uses a simple greeting service defined in a Protocol Buffers (protobu ### Command Line Using Gradle +To start the gRPC server application using Spring Boot run the following: + $ gradlew :grpc-server:bootRun -This will start the gRPC server application using Spring Boot. +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 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 index 69c4d8118..23a384d01 100644 --- 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 @@ -20,7 +20,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * Demonstrate Spring Integration's + * The Spring Boot application to demonstrate Spring Integration's * {@link org.springframework.integration.grpc.inbound.GrpcInboundGateway} support. * * @author Glenn Renfro diff --git a/basic/grpc-server/src/main/resources/application.properties b/basic/grpc-server/src/main/resources/application.properties deleted file mode 100644 index 604c08e93..000000000 --- a/basic/grpc-server/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.grpc.client.default-channel.address=static://localhost:9090 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 index f3c841fee..7433671be 100644 --- 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 @@ -39,8 +39,7 @@ * @author Glenn Renfro */ @SpringBootTest({ - "spring.grpc.server.inprocess.name=test", - "spring.grpc.client.channels.spring-integration.address=in-process:test" + "spring.grpc.server.inprocess.name=test" }) @ImportGrpcClients( types = { @@ -88,8 +87,9 @@ void serverStreaming() throws InterruptedException { assertThat(replyLatch.await(10_000, TimeUnit.MILLISECONDS)).isTrue(); - assertThat(replies.get(0)).extracting(HelloReply::getMessage).isEqualTo("Hello Stream Jane"); - assertThat(replies.get(1)).extracting(HelloReply::getMessage).isEqualTo("Hello again!"); + assertThat(replies) + .extracting(HelloReply::getMessage) + .containsOnly("Hello Stream Jane", "Hello again!"); } /** diff --git a/build.gradle b/build.gradle index 8b711d03e..c178e8001 100644 --- a/build.gradle +++ b/build.gradle @@ -891,10 +891,8 @@ project('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' } } @@ -926,11 +924,11 @@ 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 } @@ -948,10 +946,8 @@ project('grpc-server') { 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' } } From 9be3f2ebbb9ecd72f2a25734673dcf97d09d9ce7 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Wed, 25 Mar 2026 12:31:54 -0400 Subject: [PATCH 3/3] Update configuration class javadoc - All class javadocs should be 3rd person narrative vs imperative - Add TODO to check exclude for grpc tests --- .../samples/grpc/server/GrpcServerConfiguration.java | 4 ++-- build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 index f2fa48ae4..f9c542b5f 100644 --- 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 @@ -26,9 +26,9 @@ import org.springframework.messaging.Message; /** - * Configure {@link org.springframework.integration.grpc.inbound.GrpcInboundGateway}. + * Configures {@link GrpcInboundGateway}. *

- * Demonstrate various gRPC communication patterns: + * Demonstrates various gRPC communication patterns: *

    *
  • Unary RPC (SayHello)
  • *
  • Server streaming RPC (StreamHello)
  • diff --git a/build.gradle b/build.gradle index c178e8001..059126e98 100644 --- a/build.gradle +++ b/build.gradle @@ -892,7 +892,7 @@ project('grpc-client') { //Test testImplementation ('org.springframework.boot:spring-boot-starter-grpc-test') { - exclude group: 'io.grpc', module: 'grpc-netty' + exclude group: 'io.grpc', module: 'grpc-netty' //TODO Review this exclusion prior to 7.1.0 release } } @@ -947,7 +947,7 @@ project('grpc-server') { //Test testImplementation ('org.springframework.boot:spring-boot-starter-grpc-test') { - exclude group: 'io.grpc', module: 'grpc-netty' + exclude group: 'io.grpc', module: 'grpc-netty' //TODO Review this exclusion prior to 7.1.0 release } }