GoogleCloudPlatform / spring-cloud-gcp

New home for Spring Cloud GCP development starting with version 2.0.
Apache License 2.0
428 stars 318 forks source link

Missing Netty for Spring Cloud Gateway & spring-cloud-gcp-starter-logging #1314

Closed norbertspiess closed 2 years ago

norbertspiess commented 2 years ago

Describe the bug When adding spring-cloud-gcp-starter-logging to a spring cloud gateway project, the applicaion (or spring test) fails with the following stacktrace:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'routeDefinitionRouteLocator' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]: Unsatisfied dependency expressed through method 'routeDefinitionRouteLocator' parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jsonToGRPCFilterFactory' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]: Unsatisfied dependency expressed through method 'jsonToGRPCFilterFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'grpcSslConfigurer' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]: Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.gateway.config.GrpcSslConfigurer] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@251a69d7]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734)
...
Caused by: java.lang.ClassNotFoundException: io.grpc.netty.NettyChannelBuilder
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    ... 128 common frames omitted

Issue GCP starter logging ships netty, but only in the shaded variant. Shaded brings a different package structure.

Solution adding netty itself solves the issue, providing all necessary classes.

    <dependency>
      <groupId>io.grpc</groupId>
      <artifactId>grpc-netty</artifactId>
    </dependency>

Sample gateway-cloud-dependencies.zip

elefeint commented 2 years ago

Spring Cloud Gateway docs say that "Spring Cloud Gateway requires the Netty runtime provided by Spring Boot and Spring Webflux" -- are you perhaps missing a Spring Webflux dependency?

Netty shading is not something we can remove in Spring Cloud GCP; it's integral to how the client libraries are built.

norbertspiess commented 2 years ago

Even adding

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

doesn't resolve it. We have it in our Gateway project as well.

Important to know: everything worked with spring cloud dependencies 2021.0.3.

elefeint commented 2 years ago

So it stopped working with spring-cloud-dependencies 2021.0.4? It sounds like this issue belongs in the https://github.com/spring-cloud/spring-cloud-gateway repository.

norbertspiess commented 2 years ago

opened a new issue over there... let's see what they have to say about it

elefeint commented 2 years ago

Linking the Spring Cloud Gateway issue: https://github.com/spring-cloud/spring-cloud-gateway/issues/2769

I am going to close the issue in this repo, since this isn't a problem that can be resolved in Spring Cloud GCP. Most likely, there is some autoconfiguration that's triggered in Spring Cloud Gateway that relies on detection of something it finds in the shaded dependency but then can't actually use it.