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

Some usage of @ConditionalOnMissingBean does not allow a bean defined as an interface to cause a concrete implementation to back off #18101

Closed
wilkinsona opened this issue Sep 3, 2019 · 3 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@wilkinsona
Copy link
Member

wilkinsona commented Sep 3, 2019

See DATAMONGO-2355 and this question on Stack Overflow for some background.

We have some places in our auto-configuration where we define a bean using a concrete type where it's typically injected as an interface. The definition that prompted this issue is the following:

@Bean
@ConditionalOnMissingBean
public ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory,
MongoConverter converter) {
return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory, converter);
}

A ReactiveMongoOperations bean won't cause the reactiveMongoTemplate bean to back off when it probably should. We're inconsistent about this as another bean in the same class will back off in the presence of a bean defined using the interface:

@Bean
@ConditionalOnMissingBean(MongoConverter.class)
public MappingMongoConverter mappingMongoConverter(MongoMappingContext context,
MongoCustomConversions conversions) {
MappingMongoConverter mappingConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context);
mappingConverter.setCustomConversions(conversions);
return mappingConverter;
}

While beans should generally be defined using their concrete type so that the bean factory has as much type information as possible, mocking a bean using an interface that it implements is a use case for defining a bean using an interface. With the current arrangement, a test that mocks MongoOperations and attempts to autowire that mock will fail:

@Autowired
MongoOperations mongoOperations;

@TestConfiguration
static class MockOperationsConfiguration {

	@Bean
	MongoOperations mockedMongoOperations(MongoConverter converter) {
		MongoOperations mongoOperations = mock(MongoOperations.class);
		given(mongoOperations.getConverter()).willReturn(converter);
		return mongoOperations;
	}

}

The failure occurs because there are two MongoOperations beans: mockedMongoOperations from the test configuration and mongoTemplate from Boot's auto-configuration.

@wilkinsona wilkinsona added for: team-attention An issue we'd like other members of the team to review and removed for: team-attention An issue we'd like other members of the team to review labels Sep 3, 2019
@wilkinsona wilkinsona added this to the 2.2.x milestone Sep 4, 2019
@wilkinsona wilkinsona added the type: bug A general bug label Sep 4, 2019
@wilkinsona wilkinsona self-assigned this Sep 4, 2019
@wilkinsona
Copy link
Member Author

The necessary changes are not very widespread, touching 13 files with 30 additions and 17 deletions.

@philwebb philwebb modified the milestones: 2.2.x, 2.1.x Sep 6, 2019
@philwebb
Copy link
Member

philwebb commented Sep 6, 2019

Let's try in 2.1.x then

@wilkinsona wilkinsona changed the title Review use of @ConditionalOnMissingBean to allow a bean defined as an interface to cause a concrete implementation to back off Some usage of @ConditionalOnMissingBean does not allow a bean defined as an interface to cause a concrete implementation to back off Sep 6, 2019
@wilkinsona wilkinsona modified the milestones: 2.1.x, 2.1.9 Sep 24, 2019
@wilkinsona
Copy link
Member Author

I messed up a bit and this went into 2.2 early and was actually part of 2.2.0.M6: 80b8f19

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants