I wrote a sample program like below.
@Configuration
public class MyclassName{
private final List<String> tableIds;
public MyclassName(
List<String> tableIds) {
this.tableIds = tableIds;
}
}
While running i am getting the below error.
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in MyclassName required a single bean, but 4 were found:
- spring.sleuth.baggage-keys: defined by method 'baggageKeys' in class path resource [org/springframework/cloud/sleuth/autoconfig/TraceBaggageConfiguration.class]
- spring.sleuth.local-keys: defined by method 'localKeys' in class path resource [org/springframework/cloud/sleuth/autoconfig/TraceBaggageConfiguration.class]
- spring.sleuth.propagation-keys: defined by method 'propagationKeys' in class path resource [org/springframework/cloud/sleuth/autoconfig/TraceBaggageConfiguration.class]
- spring.sleuth.log.slf4j.whitelisted-mdc-keys: defined by method 'whiteListedMDCKeys' in class path resource [org/springframework/cloud/sleuth/autoconfig/TraceBaggageConfiguration.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Process finished with exit code 0
We are using sleuth for tracing, so pom.xml has that dependencies aswell. But this is a very basic example, why iam getting this error. Can anyone help on this?
CodePudding user response:
public MyclassName(
List<String> tableIds) {
this.tableIds = tableIds;
}
This means that your MyclassNames
, as a Configuration
bean in Spring
, needs to inject a bean of type List<String>
, it happens that slueth
's TraceBaggageConfiguration
class defines some beans of type List<String>
:
@org.springframework.context.annotation.Bean({"spring.sleuth.baggage-keys"})
@org.springframework.boot.context.properties.ConfigurationProperties("spring.sleuth.baggage-keys")
java.util.List<java.lang.String> baggageKeys() { /* compiled code */ }
@org.springframework.context.annotation.Bean({"spring.sleuth.local-keys"})
@org.springframework.boot.context.properties.ConfigurationProperties("spring.sleuth.local-keys")
java.util.List<java.lang.String> localKeys() { /* compiled code */ }
@org.springframework.context.annotation.Bean({"spring.sleuth.propagation-keys"})
@org.springframework.boot.context.properties.ConfigurationProperties("spring.sleuth.propagation-keys")
java.util.List<java.lang.String> propagationKeys() { /* compiled code */ }
So spring
reported an error, did not know which bean to inject. You may need to use Qualifier
to specify the injected bean. Or, have you defined the corresponding bean which hash a List<String>
type need to be injected? What is List<String> tableIds
in your MyclassName
? You need to define a Bean
like this:
public MyclassNamesss(
@Qualifier("test") List<String> tableIds) {
this.tableIds = tableIds;
}
@Bean("test")
public List<String> myString() {
return new ArrayList<>();
}
Or you can use, in this case, the tableId will be null
:
public MyclassName(
@Autowired(required = false) List<String> tableIds) {
this.tableIds = tableIds;
}
CodePudding user response:
The class MyclassName
is known to the spring framework.
So spring will try to create an instance of MyclassName
by using the constructor:
public MyclassName(List<String> tableIds)
The Parameter 0 of constructor in MyclassName
is List<String> tableIds
Spring is trying to provide a value for this parameter but instead of only one available value, it founds 4. So Spring is not intelligent enought to choose one in your place.
The 4 available values are provided by Sleuth and are declared in the TraceBaggageConfiguration.class like follow:
@Bean(BAGGAGE_KEYS)
@ConfigurationProperties(BAGGAGE_KEYS)
List<String> baggageKeys() {...}
@Bean(LOCAL_KEYS)
@ConfigurationProperties(LOCAL_KEYS)
List<String> localKeys() {...}
@Bean(PROPAGATION_KEYS)
@ConfigurationProperties(PROPAGATION_KEYS)
List<String> propagationKeys() {...}
@Bean(WHITELISTED_MDC_KEYS)
@ConfigurationProperties(WHITELISTED_MDC_KEYS)
List<String> whiteListedMDCKeys() {...}
To solve the indecision you need to tell Spring which List<String>
you realy want injected in your constructor by using an unique identifier.
First qualify (give an id) to the expected bean
@Bean("myExpectedTableIds")
List<String> myTableIdsProcucerMethod()
Then use the org.springframework.beans.factory.annotation.Qualifier
annotation to tell Spring which bean you realy want:
public MyclassName(@Qualifier("myExpectedTableIds") List<String> tableIds)