add gRPC exception advice support for factory beans
This pull request addresses #265
When currently using @GRpcServiceAdvice on a bean that is being created within a @Configuration like so (Spring Boot 2.5.6):
@Bean
public GrpcExceptionAdvice grpcExceptionAdvice() {
return new GrpcExceptionAdvice();
}
it will produce the following exception on startup:
Caused by: java.lang.NullPointerException
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at org.lognet.springboot.grpc.autoconfigure.OnMissingErrorHandlerCondition.getMatchOutcome(OnMissingErrorHandlerCondition.java:35)
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
... 95 more
The reason is that the current logic does not support beans created through factory methods: https://github.com/LogNet/grpc-spring-boot-starter/blob/19fc75177a40d5b7b64cf6dcde81dfd4bb9a5eb9/grpc-spring-boot-starter/src/main/java/org/lognet/springboot/grpc/autoconfigure/OnMissingErrorHandlerCondition.java#L29
The solution
- added a check as suggested on stackoverflow to lookup the correct name from the
MethodMetadata.
Codecov Report
Merging #266 (860950d) into master (d70346b) will decrease coverage by
0.14%. The diff coverage is71.42%.
@@ Coverage Diff @@
## master #266 +/- ##
============================================
- Coverage 88.24% 88.09% -0.15%
- Complexity 317 318 +1
============================================
Files 50 50
Lines 1531 1537 +6
Branches 86 87 +1
============================================
+ Hits 1351 1354 +3
- Misses 143 144 +1
- Partials 37 39 +2
| Impacted Files | Coverage Δ | |
|---|---|---|
| .../autoconfigure/OnMissingErrorHandlerCondition.java | 77.77% <71.42%> (-7.94%) |
:arrow_down: |
Continue to review full report at Codecov.
Legend - Click here to learn more
Δ = absolute <relative> (impact),ø = not affected,? = missing dataPowered by Codecov. Last update d70346b...860950d. Read the comment docs.
I will add tests for this.
what is the spring boot version you are running with?
what is the spring boot version you are running with?
@jvmlet 2.5.6
@jvmlet any recommendations on how I can get the code coverage to pass? I checked https://app.codecov.io/gh/LogNet/grpc-spring-boot-starter/compare/266/changes and it seems to have no changes and I also added tests to ensure the bean loading works correctly but it complains about +0.15% coverage decrease.
I did some digging why that newly added code is not called during the integration tests. Here is my summary. Feedback welcome on how we could change these tests to reproduce this behaviour, as I am currently unable to determine what specifically is causing this behaviour to occur.
Scenario 1: AnnotatedGenericBeanDefinition
This is the current logic within the unit tests of this Spring Boot starter. Setting up the bean like this: https://github.com/LogNet/grpc-spring-boot-starter/blob/860950d7f261f41fe733f419d13ec7b3f7b529b0/grpc-spring-boot-starter-demo/src/test/java/org/lognet/springboot/grpc/recovery/GRpcRecoveryTest.java#L77
...will internally create an AnnotatedGenericBeanDefinition and set it on the internal beanFactoryMap within the beanFactory. As a result, beanDefinition.getBeanClassName() is not null.
Scenario 2: ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition
Within our codebase, we use a custom Spring Boot starter to define a custom advice like so:
@Bean
public GrpcExceptionAdvice grpcExceptionAdvice() {
return new GrpcExceptionAdvice();
}
which itself looks like this:
@GRpcServiceAdvice
public class GrpcExceptionAdvice {
/* exception handlers go here*/
}
This is literally the same setup, however, for some reason it is using a different bean definition where beanDefinition.getBeanClassName() returns null and instead the class name can be obtained from the internal MethodMetadata on the AnnotatedBeanDefinition.
Question time!
How can I change the tests within this Spring Boot starter to replicate Scenario 2?
See behavior difference if you define the inner advice class as static/non-static