Problem
After upgrading Spring Boot to version 2.2.0.M2 (from 2.2.0.M1) beans annotated with @ConfigurationProperties are loaded twice causing application to fail with following exception -
Parameter 0 of constructor in config.HazelcastConfiguration required a single bean, but 2 were found:
- hazelcastProperties: defined in file [D:\LocationGuru\Projects\JavaEE\spring-boot-issues\target\classes\config\HazelcastProperties.class]
- application.hazelcast-config.HazelcastProperties: defined in null
See application log below -
2019-04-16 20:40:51.517 INFO 14804 --- [ main] config.HazelcastProperties : Creating bean HazelcastProperties ..
2019-04-16 20:40:51.517 INFO 14804 --- [ main] config.HazelcastProperties : Creating bean HazelcastProperties ..
2019-04-16 20:40:51.517 INFO 14804 --- [ main] config.HazelcastConfiguration : Found 2 HazelcastProperties beans ..
Workaround
Adding @Primary to all the classes which are annotated with @ConfigurationProperties seems to resolve the issue temporarily.
Observation 1
With proposed workaround applied autowiring list of instances (as below) makes Spring Boot to load the beans twice -
@Autowired
public HazelcastConfiguration(final List<HazelcastProperties> propertiesList)
{
logger.info("Found {} HazelcastProperties beans ..", propertiesList.size());
}
Observation 2
With proposed workaround applied autowiring single instances (as below) makes Spring Boot to load the beans once (as expected) -
@Autowired
public HazelcastConfiguration(final HazelcastProperties properties)
{
logger.info("Found 1 HazelcastProperties beans ..");
}
Please see attached project (spring-boot-issues.zip) for reproducing the issue.
Might be related to gh-15802.
I just reported the same problem just a few minutes ago in #16580 :-)
Thank you for trying out M2, @kedar-joshi and @Polve. Much appreciated. Despite #16580 being created first, let's keep this one as it has a sample that reproduces the problem.
The problem is that your bean is being found by both component scanning and the new configuration property scanning. In the short term removing @Component will give you a single bean for your configuration properties class. We'll need to figure out what to do for this in M3.
@mbhave has reminded me that this is expected and is documented. I missed it when I added the section on configuration property scanning to the release notes. I'll correct that now. I'm leaving this open so that we can revisit the decision and see if there's a way to smooth things out a bit.
In the short term removing @Component will give you a single bean for your configuration properties class
I can't use this workaround because the problem arises also using @RestController annotation.
So I'll wait for next milestone to do some testing.
Thanks for the additional information, @Polve. This problem aside, I would recommend that you don't use @RestController and @ConfigurationProperties on the same class. Conceptually, REST controllers and configuration properties are two separate things and I'd encourage you to reflect that in your classes.
In the short term removing
@Componentwill give you a single bean for your configuration properties class.
Removing @Component works for me. Thank you.
We'll look to see if we can throw a specific exception to guide people not to use @Component with @ConfigurationProperties.
In the short term removing @component will give you a single bean for your configuration properties class
After a big refactor I was able to create separate classes with only @ConfigurationProperties annotations, but this becomes incompatible with 2.1 because with it I need to mark them also with @Component.
I wrote the details in #16580 and #16969
@wilkinsona .
I have the same issue:
***************************
APPLICATION FAILED TO START
***************************
Description:
guru.springframework.msscbreweryclient.web.client.BreweryClient is annotated with @ConfigurationProperties and @Component. This may cause the @ConfigurationProperties bean to be registered twice.
Action:
Remove @Component from guru.springframework.msscbreweryclient.web.client.BreweryClient or consider disabling automatic @ConfigurationProperties scanning.
I am using spring-boot-starter-parent 2.2.0.M4 and the branch is: https://gitlab.com/cviniciusm/mssc-brewery-client/tree/fail-configuration_properties-and-component
@ConfigurationProperties(value = "sfg.brewery", ignoreUnknownFields = false)
@Component
public class BreweryClient {
private final String BEER_PATH_V1 = "/api/v1/beer/";
private String apiHost;
@SpringBootTest
class BreweryClientTest {
@Autowired
BreweryClient client;
...
@cassiusvm this asks you to remove @Component so please do that. If there is a problem doing so, please create a separate issue with a small sample that demonstrates the problem.
Hello @snicoll ,
If I do that then the error is:
Failed to bind properties under 'sfg.brewery' to guru.springframework.msscbreweryclient.web.client.BreweryClient:
Reason: Failed to bind properties under 'sfg.brewery' to guru.springframework.msscbreweryclient.web.client.BreweryClient
Under 2.1.x.RELEASE the error is another: BreweryClient is not injected in BreweryClientTest due the lack of annotation Component.
So, I solved this issue by getting the property on another class BreweryProperties with annotation ConfigurationProperties then injected the last one in BreweryClient.
Notes:
1) I did show you my branch, the solution and there is the merge to the master too;
2) On 2.1.x.RELEASE the BreweryClient with annotation ConfigurationProperties and Component works with success.
@cassiusvm @ConfigurationProperties are meant to be isolated class and should not mix configuration binding and other logic (i.e. what a regular component does) so moving it to a separate class is what you should have done in the first place anyway. I've looked at your project and the upgrade experience is not great indeed. I've created https://github.com/spring-projects/spring-boot/issues/17750