Skip to content

Commit 52405c5

Browse files
committed
Support ServerBuilderCustomizer and spring.grpc.server.max-inbound-message-size property for GrpcServlet
Signed-off-by: Toshiaki Maki <makingx@gmail.com>
1 parent 5ab408b commit 52405c5

File tree

2 files changed

+63
-32
lines changed

2 files changed

+63
-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: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,49 +16,33 @@
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;
19+
import java.util.concurrent.atomic.AtomicBoolean;
2520

26-
import java.time.Duration;
27-
import java.util.List;
28-
import java.util.concurrent.TimeUnit;
29-
30-
import org.assertj.core.api.InstanceOfAssertFactories;
21+
import io.grpc.BindableService;
22+
import io.grpc.ServerServiceDefinition;
23+
import io.grpc.internal.GrpcUtil;
24+
import io.grpc.servlet.jakarta.GrpcServlet;
25+
import io.grpc.servlet.jakarta.ServletAdapter;
26+
import io.grpc.servlet.jakarta.ServletServerBuilder;
3127
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;
28+
3629
import org.springframework.boot.autoconfigure.AutoConfigurations;
37-
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
3830
import org.springframework.boot.test.context.FilteredClassLoader;
3931
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
4032
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
4133
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;
4734
import org.springframework.grpc.server.ServerBuilderCustomizer;
48-
import org.springframework.grpc.server.ShadedNettyGrpcServerFactory;
49-
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
35+
import org.springframework.util.unit.DataSize;
5036

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;
37+
import static org.assertj.core.api.Assertions.assertThat;
38+
import static org.mockito.Mockito.mock;
39+
import static org.mockito.Mockito.when;
5740

5841
/**
5942
* Tests for {@link GrpcServerAutoConfiguration}.
6043
*
6144
* @author Chris Bono
45+
* @author Toshiaki Maki
6246
*/
6347
class GrpcServletAutoConfigurationTests {
6448

@@ -90,7 +74,40 @@ void whenNoBindableServicesRegisteredAutoConfigurationIsSkipped() {
9074

9175
@Test
9276
void whenWebApplicationServletIsAutoConfigured() {
93-
this.contextRunner().run((context) -> assertThat(context).getBean(ServletRegistrationBean.class).isNotNull());
77+
this.contextRunner().run((context) -> {
78+
assertThat(context).getBean(ServletRegistrationBean.class)
79+
.isNotNull()
80+
.extracting("servlet")
81+
.isInstanceOf(GrpcServlet.class)
82+
.extracting("servletAdapter")
83+
.isInstanceOf(ServletAdapter.class)
84+
.extracting("maxInboundMessageSize")
85+
.isEqualTo(GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE);
86+
});
87+
}
88+
89+
@Test
90+
void whenCustomizerIsRegistered() {
91+
AtomicBoolean invoked = new AtomicBoolean(false);
92+
ServerBuilderCustomizer<ServletServerBuilder> customizer = serverBuilder -> invoked.set(true);
93+
this.contextRunner().withBean(ServerBuilderCustomizer.class, () -> customizer).run(context -> {
94+
assertThat(context).getBean(ServletRegistrationBean.class).isNotNull();
95+
assertThat(invoked.get()).isTrue();
96+
});
97+
}
98+
99+
@Test
100+
void whenMaxInboundMessageSizeIsConfigured() {
101+
this.contextRunner().withPropertyValues("spring.grpc.server.max-inbound-message-size=10KB").run(context -> {
102+
assertThat(context).getBean(ServletRegistrationBean.class)
103+
.isNotNull()
104+
.extracting("servlet")
105+
.isInstanceOf(GrpcServlet.class)
106+
.extracting("servletAdapter")
107+
.isInstanceOf(ServletAdapter.class)
108+
.extracting("maxInboundMessageSize")
109+
.isEqualTo((int) DataSize.ofKilobytes(10).toBytes());
110+
});
94111
}
95112

96113
}

0 commit comments

Comments
 (0)