Fix enhanced instance causes Spring Application startup failure#762
Fix enhanced instance causes Spring Application startup failure#762wu-sheng merged 15 commits intoapache:mainfrom
Conversation
|
I am on vacation, can't review this until 26th. |
|
@lujiajing1126 Is this a case you are familiar with? |
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a Spring Application startup failure caused by enhanced instances in the SkyWalking agent. The fix introduces interceptors to handle enhanced instances during Spring's proxy creation process, preventing startup failures when beans have been enhanced by the agent.
Key changes:
- Adds interceptors for Spring's
ProxyProcessorSupportandAbstractAutoProxyCreatorclasses - Creates a test scenario for Spring Retry functionality to validate the fix
- Updates the CI configuration to include the new test scenario
Reviewed Changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/resources/skywalking-plugin.def |
Registers two new interceptors for Spring proxy creation |
apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/ProxyProcessorSupportInstrumentation.java |
Instrumentation for ProxyProcessorSupport class |
apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/AutoProxyCreatorInstrumentation.java |
Instrumentation for AbstractAutoProxyCreator class |
apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/ProxyProcessorSupportInterceptor.java |
Interceptor to handle EnhancedInstance in proxy processing |
apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/AutoProxyCreatorInterceptor.java |
Interceptor to handle EnhancedInstance in auto proxy creation |
test/plugin/scenarios/spring-retry-scenario/ |
Complete test scenario to validate the fix with Spring Retry |
.github/workflows/plugins-test.2.yaml |
Updates CI to include the new test scenario |
...ain/java/org/apache/skywalking/apm/plugin/spring/patch/ProxyProcessorSupportInterceptor.java
Show resolved
Hide resolved
...src/main/java/org/apache/skywalking/apm/plugin/spring/patch/AutoProxyCreatorInterceptor.java
Show resolved
Hide resolved
...try-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/retry/Application.java
Show resolved
Hide resolved
| spanType: Local | ||
| peer: '' | ||
| skipAnalysis: false | ||
| - operationName: HEAD:/case/healthCheck |
There was a problem hiding this comment.
This is not required from the expectation file.
| segments: | ||
| - segmentId: not null | ||
| spans: | ||
| - operationName: test.apache.skywalking.apm.testcase.spring.retry.service.CaseService.handle() |
There was a problem hiding this comment.
There is no client span and I can't see the retry working in the expectation file.
I think you should enhance your test scenario.
@tjuwangning Ning Wang also works in our team. We've already discussed this patch offline. I suppose he has to add some more detailed technical comments for this PR and explain better how the test case works. |
|
Yes, please. I am a little confused about reviewing this test scenario. |
Actually, the original issue can be reproduced in any case that an additional interface is added for the original class. In the |
Is this error caused by adding retry annotation, or retry actually happened? |
Spring cannot startup when add the retry annotation. |
|
Then, I think you just need to add this retry annotation to existing scenario. |
| import java.lang.reflect.Method; | ||
|
|
||
| /** | ||
| * <code>AutoProxyCreatorInterceptor</code> check that the bean has been implement {@link EnhancedInstance}. |
There was a problem hiding this comment.
I am clear about your new description, but a little confused about this comment word.
I think the original method is returning true/false, and we are just checking EnhancedInstance implementation when the original return is false.
When the original return is false? We should write this comment according to #isConfigurationCallbackInterface purpose, right?
There was a problem hiding this comment.
Yes, I have updated it.
|
And please update changes.md |
| @@ -0,0 +1,9 @@ | |||
| package test.apache.skywalking.apm.testcase.spring3.config; | |||


Fix apache/skywalking#13221
After Spring Framework 4.0.2.RELEASE, if we use a Spring Advisor to add an interface to a class and that same class is also enhanced by SkyWalking, Spring will fail to start.
Reproduce (using spring-retry as an example):
@EnableRetryand the method with@Retryable, the Spring Retry's annotations cause the bean class to implement theRetryableinterface at runtime.Root cause:
SkyWalking's enhancement changes how Spring decides which proxy type to use. As mentioned in #13221, SkyWalking modifies Spring's
hasNoUserSuppliedProxyInterfaces()to avoid affecting the choice of proxy type. But once Spring Retry has addedRetryableto the list of interfaces,hasNoUserSuppliedProxyInterfaces()will find a user-supplied interface and return false, which changes the proxy type and leads to a startup failure.Starting in 4.0.2.RELEASE, Spring adds a new hook method
evaluateProxyInterfaces(), which allows proxy-related flags (like proxyTargetClass) to be determined earlier in the lifecycle. We also need to enhanceevaluateProxyInterfaces()(and its related callbacks) so that SkyWalking's EnhancedInstance interface is always ignored.CHANGESlog.