Reputation: 1371
I have a java spring project with the below service:
@Slf4j
public class DialogFlowService {
private String projectId;
private String sessionId;
private String languageCode;
public DialogFlowService(DialogFlowConfig dialogFlowConfig) {
log.info("aaa" + dialogFlowConfig.languageCode);
this.projectId = dialogFlowConfig.projectId;
this.sessionId = dialogFlowConfig.sessionId;
this.languageCode = dialogFlowConfig.languageCode;
}
}
The constructor takes the below class as an argument:
@Configuration
@ConfigurationProperties(prefix = "dialog-flow")
public class DialogFlowConfig {
@NotNull
public String projectId;
@NotNull
public String sessionId;
@NotNull
public String languageCode;
}
In theory, this should be instantiated by the below bean:
@Bean
public DialogFlowService dialogFlowService() {
return new DialogFlowService(new DialogFlowConfig());
}
However in practice, when I try to log one of the constructor arguments, it comes up as null. Am I missing something?
Upvotes: 2
Views: 1476
Reputation: 3531
This is similar to what's being described here: Why is my Spring @Autowired field null?
Essentially, by instantiating the DialogFlowConfig
instance yourself and not handing it over to Spring, you're preventing Spring from post processing it and injecting ConfigurationProperties
property values.
Instead create a @Bean
method for DialogFlowConfig
and use the corresponding Spring bean to create your DialogFlowService
. For example
@Bean
public DialogFlowService dialogFlowService(DialogFlowConfig dialogFlowConfig) {
return new DialogFlowService(dialogFlowConfig);
}
@Bean
public DialogFlowConfig dialogFlowConfig() {
return new DialogFlowConfig();
}
Spring will use the @Bean
annotated dialogFlowConfig()
factory bean method to instantiate and process the corresponding instance (setting its fields). It'll then use it with the dialogFlowService()
factory method.
Note: If you do it this way, you'll need to remove @Configuration
annotation from DialogFlowConfig
, assuming you were previously component scanning it. Alternatively, if you were correctly component scanning, you don't even need the additional @Bean
annotated dialogFlowConfig()
factory method I proposed. Just inject the DialogFlowConfig
bean declared by its @Configuration
annotation in the dialogFlowService
method.
Upvotes: 1
Reputation: 384
First of all you need to use either setter getter in DialogFlowConfig or @Value annotation on all properties. You also need to annotate your service class DialogFlowService with @Service stereotype
Upvotes: -1
Reputation: 456
I think changing your third code snippet like this would do the trick.
@Bean
public DialogFlowService dialogFlowService(DialogFlowConfig dialogFlowConfig) {
return new DialogFlowService(dialogFlowConfig);
}
The DialogFlowConfig
class is already marked as @Configuration
. Hence it is managed by the Spring Application context. So you dont have to explicitly make an object using the new keyword. You can just take it as a parameter
Try putting @EnableConfigurationProperties(DialogFlowConfig.class)
into you Spring Application class.
Upvotes: 2