Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@SpyBean and @Transactional and SelfInjection regression in 2.6.4 #30575

Closed
jonenst opened this issue Apr 7, 2022 · 9 comments
Closed

@SpyBean and @Transactional and SelfInjection regression in 2.6.4 #30575

jonenst opened this issue Apr 7, 2022 · 9 comments
Assignees
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@jonenst
Copy link

jonenst commented Apr 7, 2022

Hi, when using @SpyBean on a transactional (proxied) bean that uses self injection (to have transaction semantics for inner calls), everything works on 2.6.3, but on 2.6.4 the bean in the test is not the mockito mock anymore, so calling mockito mocks method fail.
Maybe a regression from #29909 ?

Edit: see repro below.

@snicoll
Copy link
Member

snicoll commented Apr 7, 2022

Thanks for the report.

pom.xml if you want to reproduce this problem:

Can you please take the time to move all of that in a project that we can clone and run. We'd have to do that anyway and we'd rather focus on the problem at hand rather than copy bits and pieces to a new project.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 7, 2022
@mhalbritter mhalbritter added the status: waiting-for-feedback We need additional information before we can continue label Apr 7, 2022
@jonenst
Copy link
Author

jonenst commented Apr 7, 2022

bar.zip

Is this ok ?

$ unzip bar.zip 
$ cd bar
$ mvn test
 :: Spring Boot ::                (v2.6.4)
 START TEST
service foo.AppTest$App$MyService@1d7c9811
service.self foo.AppTest$App$MyService$MockitoMock$1531434114@39342614
FAILURE
$ mvn test -Dspringboot.version=2.6.3
 :: Spring Boot ::                (v2.6.3)
START TEST
service foo.AppTest$App$MyService$MockitoMock$423369319@612ac38b
service.self foo.AppTest$App$MyService$MockitoMock$423369319@14993306
SUCCESS

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 7, 2022
@wilkinsona
Copy link
Member

Thanks for the sample, @jonenst. Unfortunately, I'm not sure that it's possible to fix this without regressing the fix for #29909 or introducing a similar problem.

I've prototyped something in this branch. The approach that I have taken is to restore the old behavior when raw injection is allowed. It fixes the scenario described in this issue, restoring the behaviour where MyService is spied and a different MyService spy is injected into the MyService spy bean. This is covered by SpyBeanOnTestFieldForExistingSelfInjectingProxiedBeanTests. Unfortunately it does not work for the situation where there are two separate beans with a circular dependency when raw injection is enabled. This is covered by SpyBeanOnTestFieldForExistingCircularBeansWithRawInjectionAllowedIntegrationTests. This latter test passes without the changes to MockitoPostProcessor.

The javadoc for setAllowRawInjectionDespiteWrapping contains the following note:

It is generally recommended to not rely on circular references between your beans, in particular with auto-proxying involved.

This is exactly the situation here. There's auto-proxying involved and there's a circular reference as a bean depends upon itself.

There's also a note on the javadoc for setAllowCircularReferences that is relevant to this situation:

It is generally recommended to not rely on circular references between your beans. Refactor your application logic to have the two beans involved delegate to a third bean that encapsulates their common logic.

Given the apparent difficulty in fixing this in a way that will work for everyone and the recommendations made in Framework, I am inclined to decline this issue. I think our priority should be on @SpyBean working when raw injection is disabled. With that priority in mind, I think the changes for #29909 were a step in the right direction.

I'll flag this for a forthcoming team meeting so that we can discuss this in case the rest of the team disagree.

@wilkinsona wilkinsona added for: team-meeting An issue we'd like to discuss as a team to make progress and removed status: feedback-provided Feedback has been provided labels Apr 7, 2022
@jonenst
Copy link
Author

jonenst commented Apr 7, 2022

Hi,
Thanks a lot for your time.

I always thought that self injecting was a legitimate use case (typically for @Transactional proxying), and different from a more general dependency cycle. Isn't that the case ? Is there an official recommendation on this ?

In any case, I'm happy to wait for your decision during your next team meeting. I assume you'll update this issue.
Thanks

@wilkinsona
Copy link
Member

wilkinsona commented Apr 7, 2022

I always thought that self injecting was a legitimate use case (typically for @Transactional proxying), and different from a more general dependency cycle. Isn't that the case?

There's no distinction that I am aware of in Framework between a cycle caused by a bean injecting itself and a larger cycle involving multiple beans. I'd take the need to enable raw injection and the note in its javadoc as a strong signal that you're doing something that's not recommended and is best avoided.

spring-projects/spring-framework#28299 will hopefully result in a definitive answer and some recommendations from the Framework team.

@philwebb philwebb assigned philwebb and wilkinsona and unassigned philwebb Apr 11, 2022
@wilkinsona
Copy link
Member

Given the apparent difficulty in fixing this in a way that will work for everyone and the recommendations made in Framework, I am inclined to decline this issue. I think our priority should be on @SpyBean working when raw injection is disabled. With that priority in mind, I think the changes for #29909 were a step in the right direction.

I'll flag this for a forthcoming team meeting so that we can discuss this in case the rest of the team disagree.

We've discussed this today and we are in agreement. Closing.

@wilkinsona wilkinsona added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged for: team-meeting An issue we'd like to discuss as a team to make progress labels Apr 11, 2022
@jonenst
Copy link
Author

jonenst commented Apr 13, 2022

Hi, just to be sure that I understood correctly: when using raw injection, in order to support spybean on two mutually injected beans, you are dropping support for spybean on self injecting beans ?
Thanks

@wilkinsona
Copy link
Member

Not exactly. We want to tolerate using SpyBean when multiple beans create a cycle that does not require raw injection to be enabled. Beyond that, we do not want to make any changes to support SpyBean with raw injection enabled. It does not appear to be possible to support all scenarios and flip-flopping from one to the other as issues are raised isn’t a viable option, particularly given the recommendations against using raw injection in the first place.

@jonenst
Copy link
Author

jonenst commented Apr 13, 2022

Thank you for taking the time to clarify this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

6 participants