I want to bind properties from the application.yml automatically by using @ConfigurationProperties on a bean but the properties won't be injected.
My problem seems similar to ConfigurationProperties does not bind properties but the solutions in that post didn't work for me.
My setup is as follows:
application.yml
keycloak:
host: localhost
port: 8085
security:
oauth2:
client:
clientId: admin-cli
username: admin
password: secret
accessTokenUri: http://${keycloak.host}:${keycloak.port}/auth/realms/master/protocol/openid-connect/token
clientAuthenticationScheme: form
KeycloakFeignClientConfiguration.java
public class KeycloakFeignClientConfiguration {
@Value("${security.oauth2.client.clientId}")
private String clientId;
@Bean
@ConfigurationProperties("security.oauth2.client")
public ResourceOwnerPasswordResourceDetails resourceDetails() {
// ResourceOwnerPasswordResourceDetails comes from org.springframework.security
return new ResourceOwnerPasswordResourceDetails();
}
@Bean
public RequestInterceptor oauth2FeignRequestInterceptor(ResourceOwnerPasswordResourceDetails resourceDetails) {
return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), resourceDetails);
}
}
If I set a breakpoint in the oauth2FeignRequestInterceptor-Method and look for resourceDetails-Properties all of them are null. In case of the @Value annotation the value is set correctly. To add an annotation @Configuration on the KeycloakFeignClientConfiguration-Class makes no difference.
KeycloakProxy.java
@FeignClient(name ="noName", url = "http://${keycloak.host}:${keycloak.port}/auth", configuration = KeycloakFeignClientConfiguration.class)
public interface KeycloakProxy {
// ...some request mappings
}
We must specify an explicit configuration class because otherwise the wrong configuration class will be used for this proxy. The project contains multiple feign client configuration classes).
ServiceApplication.java
@EnableDiscoveryClient
@EnableFeignClients
@EnableTransactionManagement
@SpringBootApplication
public class ServiceApplication {
public static void main(String[] args) {
Validate.notNull(args, "args");
SpringApplication.run(ServiceApplication.class, args);
}
}
Adding @EnableConfigurationProperties to the ServiceApplication makes also no difference. If I add @EnableConfigurationProperties(KeycloakFeignClientConfiguration.class) or @EnableConfigurationProperties(ResourceOwnerPasswordResourceDetails.class) I get an exception which says that the classes have no @ConfigurationProperties.
Caused by: java.lang.IllegalArgumentException: No ConfigurationProperties annotation found on 'com.gbtec.bic.cloud.tenant.remote.keycloak.KeycloakFeignClientConfiguration'.
What works for me is if I move the resourceDetails-Method from KeycloakFeignClientConfiguration to an additional configuration class and annotate these with @Configuration. For example:
@Configuration
public class ServiceConfiguration {
@Bean
@ConfigurationProperties("security.oauth2.client")
public ResourceOwnerPasswordResourceDetails resourceDetails() {
return new ResourceOwnerPasswordResourceDetails();
}
}
This way the bean will be created (in right application context?) and the properties will be injected. Here I will get resourceDetails with the whole configuration inside oauth2FeignRequestInterceptor-Method in KeycloakFeignClientConfiguration.java
I want to avoid to create the additional configuration class to create a resource details bean. Do you have any ideas to solve this problem?
Edit 23.07.2018
As requested we created an example project which illustrates the problem: Link to GitHub-Project
- To run the test, Docker is required because we use Testcontainers.
- The KeycloakProxy is named (in the test Project) ExampleFeignClient