Skip to content

Commit 473a742

Browse files
committed
Improve channel factory type contract
This commit improves the GrpcChannelFactory contract by introducing generic builder type and simplifying the API with the addition of ChannelBuilderOptions that holds customizer, shutdownGracePeriod, and interceptors.
1 parent b3271be commit 473a742

File tree

24 files changed

+1058
-190
lines changed

24 files changed

+1058
-190
lines changed

samples/grpc-server-netty-shaded/src/test/java/com/example/demo/DemoApplicationTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import org.apache.commons.logging.Log;
66
import org.apache.commons.logging.LogFactory;
77
import org.junit.jupiter.api.Test;
8+
89
import org.springframework.beans.factory.annotation.Autowired;
910
import org.springframework.boot.SpringApplication;
1011
import org.springframework.boot.test.context.SpringBootTest;
1112
import org.springframework.boot.test.context.TestConfiguration;
1213
import org.springframework.context.annotation.Bean;
1314
import org.springframework.context.annotation.Lazy;
15+
import org.springframework.grpc.client.ChannelBuilderOptions;
1416
import org.springframework.grpc.client.GrpcChannelFactory;
1517
import org.springframework.grpc.test.LocalGrpcPort;
1618
import org.springframework.test.annotation.DirtiesContext;
@@ -51,7 +53,8 @@ static class TestListener {
5153
@Bean
5254
@Lazy
5355
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels, @LocalGrpcPort int port) {
54-
return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:" + port).build());
56+
return SimpleGrpc
57+
.newBlockingStub(channels.createChannel("0.0.0.0:" + port, ChannelBuilderOptions.defaults()));
5558
}
5659

5760
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
* Copyright 2024-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.grpc.sample;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
21+
import org.junit.jupiter.api.Nested;
22+
import org.junit.jupiter.api.Test;
23+
24+
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.boot.test.context.SpringBootTest;
26+
import org.springframework.boot.test.context.TestConfiguration;
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.grpc.client.ChannelBuilderOptions;
29+
import org.springframework.grpc.client.GrpcChannelBuilderCustomizer;
30+
import org.springframework.grpc.client.GrpcChannelFactory;
31+
import org.springframework.grpc.client.NettyGrpcChannelFactory;
32+
import org.springframework.grpc.sample.proto.HelloReply;
33+
import org.springframework.grpc.sample.proto.HelloRequest;
34+
import org.springframework.grpc.sample.proto.SimpleGrpc;
35+
import org.springframework.grpc.test.LocalGrpcPort;
36+
37+
import io.grpc.ManagedChannel;
38+
import io.grpc.ManagedChannelBuilder;
39+
import io.grpc.netty.NettyChannelBuilder;
40+
41+
/**
42+
* More detailed integration tests for {@link GrpcChannelFactory gRPC channel factories}.
43+
*/
44+
class GrpcClientIntegrationTests {
45+
46+
@Nested
47+
@SpringBootTest(properties = { "spring.grpc.server.host=127.0.0.1", "spring.grpc.server.port=0",
48+
"spring.grpc.inprocess.enabled=false" })
49+
class ChannelBuilderCustomizerUsageTests {
50+
51+
@Test
52+
void channelFactoryWithConcreteCustomizer(@Autowired NettyGrpcChannelFactory channels,
53+
@LocalGrpcPort int port) {
54+
GrpcChannelBuilderCustomizer<NettyChannelBuilder> customizer = (__, b) -> b.flowControlWindow(5);
55+
var channel = channels.createChannel("127.0.0.1:" + port,
56+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
57+
assertThatResponseIsServedToChannel(channel);
58+
}
59+
60+
@Test
61+
void concreteChannelFactoryWithWildcardBaseCustomizer(@Autowired NettyGrpcChannelFactory channels,
62+
@LocalGrpcPort int port) {
63+
GrpcChannelBuilderCustomizer<?> customizer = wildcardBase((__, b) -> b.userAgent("foo"));
64+
var channel = channels.createChannel("127.0.0.1:" + port,
65+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
66+
assertThatResponseIsServedToChannel(channel);
67+
}
68+
69+
@Test
70+
void concreteChannelFactoryWithRawWBaseCustomizer(@Autowired NettyGrpcChannelFactory channels,
71+
@LocalGrpcPort int port) {
72+
GrpcChannelBuilderCustomizer customizer = (__, b) -> b.userAgent("foo");
73+
var channel = channels.createChannel("127.0.0.1:" + port,
74+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
75+
assertThatResponseIsServedToChannel(channel);
76+
}
77+
78+
@Test
79+
<T extends ManagedChannelBuilder<T>> void concreteChannelFactoryWithGenericBaseCustomizer(
80+
@Autowired NettyGrpcChannelFactory channels, @LocalGrpcPort int port) {
81+
GrpcChannelBuilderCustomizer<T> customizer = (__, b) -> b.userAgent("foo");
82+
var channel = channels.createChannel("127.0.0.1:" + port,
83+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
84+
assertThatResponseIsServedToChannel(channel);
85+
}
86+
87+
@Test
88+
void wildcardBaseChannelFactoryWithConcreteCustomizer(@Autowired GrpcChannelFactory channels,
89+
@LocalGrpcPort int port) {
90+
GrpcChannelBuilderCustomizer<NettyChannelBuilder> customizer = (__, b) -> b.flowControlWindow(5);
91+
var channel = channels.createChannel("127.0.0.1:" + port,
92+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
93+
assertThatResponseIsServedToChannel(channel);
94+
}
95+
96+
@Test
97+
void wildcardBaseChannelFactoryWithWildcardBaseCustomizer(@Autowired GrpcChannelFactory channels,
98+
@LocalGrpcPort int port) {
99+
GrpcChannelBuilderCustomizer<?> customizer = wildcardBase((__, b) -> b.userAgent("foo"));
100+
var channel = channels.createChannel("127.0.0.1:" + port,
101+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
102+
assertThatResponseIsServedToChannel(channel);
103+
}
104+
105+
@Test
106+
void wildcardBaseChannelFactoryWithRawWBaseCustomizer(@Autowired GrpcChannelFactory channels,
107+
@LocalGrpcPort int port) {
108+
GrpcChannelBuilderCustomizer customizer = (__, b) -> b.userAgent("foo");
109+
var channel = channels.createChannel("127.0.0.1:" + port,
110+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
111+
assertThatResponseIsServedToChannel(channel);
112+
}
113+
114+
@Test
115+
<T extends ManagedChannelBuilder<T>> void wildcardBaseChannelFactoryWithGenericBaseCustomizer(
116+
@Autowired GrpcChannelFactory channels, @LocalGrpcPort int port) {
117+
GrpcChannelBuilderCustomizer<T> customizer = (__, b) -> b.userAgent("foo");
118+
var channel = channels.createChannel("127.0.0.1:" + port,
119+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
120+
assertThatResponseIsServedToChannel(channel);
121+
}
122+
123+
@Test
124+
void rawBaseChannelFactoryWithConcreteCustomizer(@Autowired GrpcChannelFactory channels,
125+
@LocalGrpcPort int port) {
126+
GrpcChannelBuilderCustomizer<NettyChannelBuilder> customizer = (__, b) -> b.flowControlWindow(5);
127+
var channel = channels.createChannel("127.0.0.1:" + port,
128+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
129+
assertThatResponseIsServedToChannel(channel);
130+
}
131+
132+
@Test
133+
void rawBaseChannelFactoryWithWildcardRawCustomizer(@Autowired GrpcChannelFactory channels,
134+
@LocalGrpcPort int port) {
135+
GrpcChannelBuilderCustomizer<?> customizer = wildcardBase((__, b) -> b.userAgent("foo"));
136+
var channel = channels.createChannel("127.0.0.1:" + port,
137+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
138+
assertThatResponseIsServedToChannel(channel);
139+
}
140+
141+
@Test
142+
void rawBaseChannelFactoryWithRawWBaseCustomizer(@Autowired GrpcChannelFactory channels,
143+
@LocalGrpcPort int port) {
144+
GrpcChannelBuilderCustomizer customizer = (__, b) -> b.userAgent("foo");
145+
var channel = channels.createChannel("127.0.0.1:" + port,
146+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
147+
assertThatResponseIsServedToChannel(channel);
148+
}
149+
150+
@Test
151+
<T extends ManagedChannelBuilder<T>> void rawBaseChannelFactoryWithGenericBaseCustomizer(
152+
@Autowired GrpcChannelFactory channels, @LocalGrpcPort int port) {
153+
GrpcChannelBuilderCustomizer<T> customizer = (__, b) -> b.userAgent("foo");
154+
var channel = channels.createChannel("127.0.0.1:" + port,
155+
ChannelBuilderOptions.defaults().withCustomizer(customizer));
156+
assertThatResponseIsServedToChannel(channel);
157+
}
158+
159+
private GrpcChannelBuilderCustomizer<?> wildcardBase(GrpcChannelBuilderCustomizer rawBase) {
160+
return (GrpcChannelBuilderCustomizer<?>) rawBase;
161+
}
162+
163+
@TestConfiguration
164+
static class ChannelBuilderCustomizerConfig {
165+
166+
@Bean
167+
GrpcChannelBuilderCustomizer<NettyChannelBuilder> nettyTypedCustomizer() {
168+
return (__, b) -> b.flowControlWindow(5);
169+
}
170+
171+
}
172+
173+
}
174+
175+
private void assertThatResponseIsServedToChannel(ManagedChannel clientChannel) {
176+
SimpleGrpc.SimpleBlockingStub client = SimpleGrpc.newBlockingStub(clientChannel);
177+
HelloReply response = client.sayHello(HelloRequest.newBuilder().setName("Alien").build());
178+
assertThat(response.getMessage()).isEqualTo("Hello ==> Alien");
179+
}
180+
181+
}

samples/grpc-server/src/test/java/org/springframework/grpc/sample/GrpcServerApplicationTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import org.apache.commons.logging.Log;
66
import org.apache.commons.logging.LogFactory;
77
import org.junit.jupiter.api.Test;
8+
89
import org.springframework.beans.factory.annotation.Autowired;
910
import org.springframework.boot.builder.SpringApplicationBuilder;
1011
import org.springframework.boot.test.context.SpringBootTest;
1112
import org.springframework.boot.test.context.TestConfiguration;
1213
import org.springframework.context.annotation.Bean;
1314
import org.springframework.context.annotation.Lazy;
15+
import org.springframework.grpc.client.ChannelBuilderOptions;
1416
import org.springframework.grpc.client.GrpcChannelFactory;
1517
import org.springframework.grpc.sample.proto.HelloReply;
1618
import org.springframework.grpc.sample.proto.HelloRequest;
@@ -50,7 +52,8 @@ static class ExtraConfiguration {
5052
@Bean
5153
@Lazy
5254
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels, @LocalGrpcPort int port) {
53-
return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:" + port).build());
55+
return SimpleGrpc
56+
.newBlockingStub(channels.createChannel("0.0.0.0:" + port, ChannelBuilderOptions.defaults()));
5457
}
5558

5659
}

samples/grpc-server/src/test/java/org/springframework/grpc/sample/GrpcServerHealthIntegrationTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.springframework.boot.test.context.SpringBootTest;
3333
import org.springframework.boot.test.context.TestConfiguration;
3434
import org.springframework.context.annotation.Bean;
35+
import org.springframework.grpc.client.ChannelBuilderOptions;
3536
import org.springframework.grpc.client.GrpcChannelFactory;
3637
import org.springframework.grpc.sample.proto.HelloReply;
3738
import org.springframework.grpc.sample.proto.HelloRequest;
@@ -62,7 +63,7 @@ class WithClientHealthEnabled {
6263
@Test
6364
void loadBalancerRespectsServerHealth(@Autowired GrpcChannelFactory channels,
6465
@Autowired HealthStatusManager healthStatusManager) {
65-
ManagedChannel channel = channels.createChannel("health-test").build();
66+
ManagedChannel channel = channels.createChannel("health-test", ChannelBuilderOptions.defaults());
6667
SimpleGrpc.SimpleBlockingStub client = SimpleGrpc.newBlockingStub(channel);
6768

6869
// put the service up (SERVING) and give load balancer time to update
@@ -117,7 +118,7 @@ class WithActuatorHealthAdapter {
117118

118119
@Test
119120
void healthIndicatorsAdaptedToGrpcHealthStatus(@Autowired GrpcChannelFactory channels) {
120-
var channel = channels.createChannel("0.0.0.0:0").build();
121+
var channel = channels.createChannel("0.0.0.0:0", ChannelBuilderOptions.defaults());
121122
var healthStub = HealthGrpc.newBlockingStub(channel);
122123
var serviceName = "custom";
123124

0 commit comments

Comments
 (0)