grpc-ecosystem / grpc-spring

Spring Boot starter module for gRPC framework.
https://grpc-ecosystem.github.io/grpc-spring/
Apache License 2.0
3.46k stars 811 forks source link

Error creating bean with name 'grpcHealthService' #994

Open michaldCX opened 9 months ago

michaldCX commented 9 months ago

The context

Error creating bean with name 'grpcHealthService'

The question

I'm using grpc-server-spring-boot-starter - 2.14.0.RELEASE ans when start my app i got error while Initialization bean grpcHealthService

Stacktraces and logs

2023-11-20T18:24:03.159Z [main] error SpringApplication.java:830 - Application run failed 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'grpcHealthService' defined in class path resource [net/devh/boot/grpc/server/autoconfigure/GrpcHealthServiceAutoConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class io.grpc.protobuf.services.HealthServiceImpl: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class io.grpc.protobuf.services.HealthServiceImpl
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628)
    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:953)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
    at com.checkmarx.ast.flow.listener.FlowListenerApp.main(FlowListenerApp.java:16)
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class io.grpc.protobuf.services.HealthServiceImpl: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class io.grpc.protobuf.services.HealthServiceImpl
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:209)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:478)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:342)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:291)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:455)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
    ... 15 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class io.grpc.protobuf.services.HealthServiceImpl
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:660)
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy.generate(ClassLoaderAwareGeneratorStrategy.java:57)
    at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:358)
    at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108)
    at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
    at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572)
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:419)
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:57)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:206)
    ... 22 more

The application's environment

Which versions do you use?

Additional information

michaldCX commented 9 months ago

I do have an interceptor that using @Aspect with this method: @Before("execution(public void io.grpc.BindableService+.*(..))") public void beforeEachIncomingGrpcCall() { context.restoreForIncomingGrpcCall(); }

And If I remove it the application start as well

ST-DDT commented 9 months ago

You can also exclude the auto configuration that adds the HealthServiceImpl.

https://github.com/grpc-ecosystem/grpc-spring/blob/e6cb04498b0db0d60ec5f690498a0c54af18d06f/grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/autoconfigure/GrpcHealthServiceAutoConfiguration.java#L37

Note: I also had issues with overwriting Bindable.bind/making it non final as that bypassed spring security.

What does your

context.restoreForIncomingGrpcCall();

do?

michaldCX commented 9 months ago

I dont want to exclude the auto configuration since i do want the functionality of HealthServiceImpl.

context.restoreForIncomingGrpcCall(); Copied values from gRPC context into our contaext (We cannot populate our context directly in IncomingInterceptor, because interceptor and business logic may execute in different threads under high load)

ST-DDT commented 9 months ago

I dont know much about aspect entrypoint syntax. Maybe you can define an exclude somehow. Please be careful when using thread locals in combination with streaming calls like this.

Grpc has a class called Context that can be used to store variables throughout the entire call. This library uses it to implememt the grpc request scope feature. Have you considered scoping your context bean instead? That way you can already use them in the interceptor.

https://grpc-ecosystem.github.io/grpc-spring/en/server/contextual-data.html

ST-DDT commented 9 months ago

Is there anything else we can help you with?