diff --git a/samples/grpc-tomcat/src/main/java/org/springframework/grpc/sample/GrpcServerApplication.java b/samples/grpc-tomcat/src/main/java/org/springframework/grpc/sample/GrpcServerApplication.java index 090ddfc..d605209 100644 --- a/samples/grpc-tomcat/src/main/java/org/springframework/grpc/sample/GrpcServerApplication.java +++ b/samples/grpc-tomcat/src/main/java/org/springframework/grpc/sample/GrpcServerApplication.java @@ -1,35 +1,19 @@ package org.springframework.grpc.sample; -import java.util.List; -import java.util.stream.Collectors; - import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; -import org.springframework.grpc.autoconfigure.server.GrpcServerAutoConfiguration; import io.grpc.BindableService; import io.grpc.protobuf.services.ProtoReflectionService; -import io.grpc.servlet.jakarta.GrpcServlet; -@SpringBootApplication(exclude = GrpcServerAutoConfiguration.class) +@SpringBootApplication public class GrpcServerApplication { public static void main(String[] args) { SpringApplication.run(GrpcServerApplication.class, args); } - @Bean - public ServletRegistrationBean grpcServlet(List services) { - List paths = services.stream() - .map(service -> "/" + service.bindService().getServiceDescriptor().getName() + "/*") - .collect(Collectors.toList()); - ServletRegistrationBean servlet = new ServletRegistrationBean<>(new GrpcServlet(services)); - servlet.setUrlMappings(paths); - return servlet; - } - @Bean public BindableService serverReflection() { return ProtoReflectionService.newInstance(); diff --git a/samples/grpc-tomcat/src/test/java/org/springframework/grpc/sample/GrpcServerApplicationTests.java b/samples/grpc-tomcat/src/test/java/org/springframework/grpc/sample/GrpcServerApplicationTests.java index 7849926..fd747cb 100644 --- a/samples/grpc-tomcat/src/test/java/org/springframework/grpc/sample/GrpcServerApplicationTests.java +++ b/samples/grpc-tomcat/src/test/java/org/springframework/grpc/sample/GrpcServerApplicationTests.java @@ -24,7 +24,7 @@ public class GrpcServerApplicationTests { private static Log log = LogFactory.getLog(GrpcServerApplicationTests.class); public static void main(String[] args) { - new SpringApplicationBuilder(GrpcServerApplication.class, ExtraConfiguration.class).profiles("ssl").run(args); + new SpringApplicationBuilder(GrpcServerApplication.class, ExtraConfiguration.class).run(args); } @Autowired diff --git a/spring-grpc-spring-boot-autoconfigure/pom.xml b/spring-grpc-spring-boot-autoconfigure/pom.xml index 4c5211d..23a7e94 100644 --- a/spring-grpc-spring-boot-autoconfigure/pom.xml +++ b/spring-grpc-spring-boot-autoconfigure/pom.xml @@ -45,6 +45,16 @@ ${project.version} true + + org.apache.tomcat.embed + tomcat-embed-core + true + + + io.grpc + grpc-servlet-jakarta + true + io.grpc grpc-netty-shaded diff --git a/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerAutoConfiguration.java b/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerAutoConfiguration.java index fe82d86..2933939 100644 --- a/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerAutoConfiguration.java +++ b/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerAutoConfiguration.java @@ -15,14 +15,9 @@ */ package org.springframework.grpc.autoconfigure.server; -import io.grpc.BindableService; - -import io.grpc.CompressorRegistry; -import io.grpc.DecompressorRegistry; -import io.grpc.netty.NettyServerBuilder; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -30,14 +25,17 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Import; -import org.springframework.core.Ordered; import org.springframework.grpc.autoconfigure.common.codec.GrpcCodecConfiguration; import org.springframework.grpc.server.GrpcServerFactory; import org.springframework.grpc.server.ServerBuilderCustomizer; import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle; +import io.grpc.BindableService; +import io.grpc.CompressorRegistry; +import io.grpc.DecompressorRegistry; +import io.grpc.netty.NettyServerBuilder; + /** * {@link EnableAutoConfiguration Auto-configuration} for gRPC server-side components. *

@@ -48,12 +46,11 @@ import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle; * @author Chris Bono */ @AutoConfiguration -@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) +@AutoConfigureAfter(GrpcServerFactoryAutoConfiguration.class) @ConditionalOnClass(BindableService.class) @ConditionalOnBean(BindableService.class) @EnableConfigurationProperties(GrpcServerProperties.class) -@Import({ GrpcServerFactoryConfigurations.ShadedNettyServerFactoryConfiguration.class, - GrpcServerFactoryConfigurations.NettyServerFactoryConfiguration.class, GrpcCodecConfiguration.class }) +@Import({ GrpcCodecConfiguration.class }) public class GrpcServerAutoConfiguration { private final GrpcServerProperties properties; diff --git a/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerFactoryAutoConfiguration.java b/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerFactoryAutoConfiguration.java new file mode 100644 index 0000000..7b7361a --- /dev/null +++ b/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerFactoryAutoConfiguration.java @@ -0,0 +1,74 @@ +/* + * Copyright 2024-2024 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.grpc.autoconfigure.server; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.Ordered; + +import io.grpc.BindableService; +import io.grpc.servlet.jakarta.GrpcServlet; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for gRPC server-side components. + *

+ * gRPC must be on the classpath and at least one {@link BindableService} bean registered + * in the context in order for the auto-configuration to execute. + * + * @author David Syer + * @author Chris Bono + */ +@AutoConfiguration +@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) +@ConditionalOnClass(BindableService.class) +public class GrpcServerFactoryAutoConfiguration { + + @Configuration(proxyBeanMethods = false) + @ConditionalOnNotWebApplication + @Import({ GrpcServerFactoryConfigurations.ShadedNettyServerFactoryConfiguration.class, + GrpcServerFactoryConfigurations.NettyServerFactoryConfiguration.class }) + static class GrpcServerFactoryConfiguration { + + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnWebApplication + static class GrpcServletConfiguration { + + @Bean + public ServletRegistrationBean grpcServlet(List services) { + List paths = services.stream() + .map(service -> "/" + service.bindService().getServiceDescriptor().getName() + "/*") + .collect(Collectors.toList()); + ServletRegistrationBean servlet = new ServletRegistrationBean<>(new GrpcServlet(services)); + servlet.setUrlMappings(paths); + return servlet; + } + + } + +} diff --git a/spring-grpc-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-grpc-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 80bec31..a7e2a86 100644 --- a/spring-grpc-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-grpc-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1,3 @@ +org.springframework.grpc.autoconfigure.server.GrpcServerFactoryAutoConfiguration org.springframework.grpc.autoconfigure.server.GrpcServerAutoConfiguration org.springframework.grpc.autoconfigure.client.GrpcClientAutoConfiguration diff --git a/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServerAutoConfigurationTests.java b/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServerAutoConfigurationTests.java index 79df63b..312bfaf 100644 --- a/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServerAutoConfigurationTests.java +++ b/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServerAutoConfigurationTests.java @@ -66,7 +66,8 @@ class GrpcServerAutoConfigurationTests { when(service.bindService()).thenReturn(serviceDefinition); // NOTE: we use noop server lifecycle to avoid startup return new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(GrpcServerAutoConfiguration.class, SslAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(GrpcServerAutoConfiguration.class, + GrpcServerFactoryAutoConfiguration.class, SslAutoConfiguration.class)) .withBean("noopServerLifecycle", GrpcServerLifecycle.class, Mockito::mock) .withBean(BindableService.class, () -> service); } @@ -77,7 +78,8 @@ class GrpcServerAutoConfigurationTests { when(service.bindService()).thenReturn(serviceDefinition); // NOTE: we use noop server lifecycle to avoid startup return new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(GrpcServerAutoConfiguration.class, SslAutoConfiguration.class)) + .withConfiguration(AutoConfigurations.of(GrpcServerAutoConfiguration.class, + GrpcServerFactoryAutoConfiguration.class, SslAutoConfiguration.class)) .withBean(BindableService.class, () -> service); }