Skip to content

Commit 7da1e80

Browse files
makingonobc
authored andcommitted
Allow GrpcServlet to be configured
This adds the ability to apply `ServerBuilderCustomizer` customizers and `spring.grpc.server.max-inbound-message-size` property to `GrpcServlet`. Signed-off-by: Toshiaki Maki <makingx@gmail.com>
1 parent 5ab408b commit 7da1e80

File tree

2 files changed

+53
-32
lines changed

2 files changed

+53
-32
lines changed

spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerFactoryAutoConfiguration.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@
2525
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2626
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
2727
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
28+
import org.springframework.boot.context.properties.PropertyMapper;
2829
import org.springframework.boot.web.servlet.ServletRegistrationBean;
2930
import org.springframework.context.annotation.Bean;
3031
import org.springframework.context.annotation.Configuration;
3132
import org.springframework.context.annotation.Import;
3233
import org.springframework.core.Ordered;
34+
import org.springframework.util.unit.DataSize;
3335

3436
import io.grpc.BindableService;
3537
import io.grpc.servlet.jakarta.GrpcServlet;
38+
import io.grpc.servlet.jakarta.ServletServerBuilder;
3639

3740
/**
3841
* {@link EnableAutoConfiguration Auto-configuration} for gRPC server-side components.
@@ -42,6 +45,7 @@
4245
*
4346
* @author David Syer
4447
* @author Chris Bono
48+
* @author Toshiaki Maki
4549
*/
4650
@AutoConfiguration
4751
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@@ -62,11 +66,21 @@ static class GrpcServerFactoryConfiguration {
6266
static class GrpcServletConfiguration {
6367

6468
@Bean
65-
public ServletRegistrationBean<GrpcServlet> grpcServlet(List<BindableService> services) {
69+
public ServletRegistrationBean<GrpcServlet> grpcServlet(GrpcServerProperties properties,
70+
List<BindableService> services, ServerBuilderCustomizers serverBuilderCustomizers) {
6671
List<String> paths = services.stream()
6772
.map(service -> "/" + service.bindService().getServiceDescriptor().getName() + "/*")
6873
.collect(Collectors.toList());
69-
ServletRegistrationBean<GrpcServlet> servlet = new ServletRegistrationBean<>(new GrpcServlet(services));
74+
ServletServerBuilder servletServerBuilder = new ServletServerBuilder();
75+
services.forEach(servletServerBuilder::addService);
76+
PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull();
77+
// Only maxInboundMessageSize is customizable
78+
mapper.from(properties.getMaxInboundMessageSize())
79+
.asInt(DataSize::toBytes)
80+
.to(servletServerBuilder::maxInboundMessageSize);
81+
serverBuilderCustomizers.customize(servletServerBuilder);
82+
ServletRegistrationBean<GrpcServlet> servlet = new ServletRegistrationBean<>(
83+
servletServerBuilder.buildServlet());
7084
servlet.setUrlMappings(paths);
7185
return servlet;
7286
}

spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServletAutoConfigurationTests.java

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,49 +16,31 @@
1616

1717
package org.springframework.grpc.autoconfigure.server;
1818

19-
import static org.assertj.core.api.Assertions.assertThat;
20-
import static org.mockito.ArgumentMatchers.any;
21-
import static org.mockito.ArgumentMatchers.anyInt;
22-
import static org.mockito.Mockito.inOrder;
23-
import static org.mockito.Mockito.mock;
24-
import static org.mockito.Mockito.when;
25-
26-
import java.time.Duration;
27-
import java.util.List;
28-
import java.util.concurrent.TimeUnit;
29-
30-
import org.assertj.core.api.InstanceOfAssertFactories;
19+
import io.grpc.BindableService;
20+
import io.grpc.ServerServiceDefinition;
21+
import io.grpc.internal.GrpcUtil;
22+
import io.grpc.servlet.jakarta.ServletServerBuilder;
3123
import org.junit.jupiter.api.Test;
32-
import org.mockito.InOrder;
33-
import org.mockito.MockedStatic;
34-
import org.mockito.Mockito;
35-
import org.mockito.stubbing.Answer;
24+
3625
import org.springframework.boot.autoconfigure.AutoConfigurations;
37-
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
3826
import org.springframework.boot.test.context.FilteredClassLoader;
3927
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
4028
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
4129
import org.springframework.boot.web.servlet.ServletRegistrationBean;
42-
import org.springframework.context.annotation.Bean;
43-
import org.springframework.context.annotation.Configuration;
44-
import org.springframework.core.annotation.Order;
45-
import org.springframework.grpc.server.GrpcServerFactory;
46-
import org.springframework.grpc.server.NettyGrpcServerFactory;
4730
import org.springframework.grpc.server.ServerBuilderCustomizer;
48-
import org.springframework.grpc.server.ShadedNettyGrpcServerFactory;
49-
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
31+
import org.springframework.util.unit.DataSize;
5032

51-
import io.grpc.BindableService;
52-
import io.grpc.Grpc;
53-
import io.grpc.ServerBuilder;
54-
import io.grpc.ServerServiceDefinition;
55-
import io.grpc.ServiceDescriptor;
56-
import io.grpc.netty.NettyServerBuilder;
33+
import static org.assertj.core.api.Assertions.assertThat;
34+
import static org.mockito.ArgumentMatchers.any;
35+
import static org.mockito.Mockito.mock;
36+
import static org.mockito.Mockito.verify;
37+
import static org.mockito.Mockito.when;
5738

5839
/**
5940
* Tests for {@link GrpcServerAutoConfiguration}.
6041
*
6142
* @author Chris Bono
43+
* @author Toshiaki Maki
6244
*/
6345
class GrpcServletAutoConfigurationTests {
6446

@@ -93,4 +75,29 @@ void whenWebApplicationServletIsAutoConfigured() {
9375
this.contextRunner().run((context) -> assertThat(context).getBean(ServletRegistrationBean.class).isNotNull());
9476
}
9577

78+
@Test
79+
void whenCustomizerIsRegistered() {
80+
ServerBuilderCustomizer<ServletServerBuilder> customizer = mock();
81+
this.contextRunner()
82+
.withBean(ServerBuilderCustomizer.class, () -> customizer)
83+
.run(context -> verify(customizer).customize(any(ServletServerBuilder.class)));
84+
}
85+
86+
@Test
87+
void whenMaxInboundMessageSizeIsSetThenItIsUsed() {
88+
this.contextRunner()
89+
.withPropertyValues("spring.grpc.server.max-inbound-message-size=10KB")
90+
.run(context -> assertThat(context).getBean(ServletRegistrationBean.class)
91+
.hasFieldOrPropertyWithValue("servlet.servletAdapter.maxInboundMessageSize",
92+
Math.toIntExact(DataSize.ofKilobytes(10).toBytes())));
93+
}
94+
95+
@Test
96+
void whenMaxInboundMessageSizeIsNotSetThenDefaultIsUsed() {
97+
this.contextRunner()
98+
.run((context) -> assertThat(context).getBean(ServletRegistrationBean.class)
99+
.hasFieldOrPropertyWithValue("servlet.servletAdapter.maxInboundMessageSize",
100+
GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE));
101+
}
102+
96103
}

0 commit comments

Comments
 (0)