Placeholder can't be resolved in Spring boot application

11,296

Solution 1

I resolved it. The problem was the configuration of spring cloud configserver. I forgot to add the folder to the searchpaths:

spring.cloud.config.server.git.searchPaths=service1,service2,webapimngmtservice

This was the reason why I got an empty List.

Solution 2

It looks like you are missing the @PropertySource annotation, which indicates which properties file to use.

You can use it this way, where something.properties is substituted with the correct filename:

@SpringBootApplication
@ComponentScan({ "de.sharing.webapimngmt.configuration", "de.sharing.webapimngmt.api", "de.sharing.webapimngmt.handler", "de.sharing.webapimngmt.service" })
@PropertySource("classpath:something.properties")
public class WebapimngmtApplication {

public static final String PROVIDER_KEY_SHARING_SERVER = "service-tokenprovider";

@Value("${keycloak.realm}")
private String keycloakRealm;

NOTE: Also make sure the file is in the classpath root (or provide the path), in the case of the spring version I am using (2.0.1) the root is the resources folder

Share:
11,296

Related videos on Youtube

n00bst3r
Author by

n00bst3r

Updated on June 04, 2022

Comments

  • n00bst3r
    n00bst3r almost 2 years

    I have several spring boot services and all services work fine except of one. One service can't resolve the placeholder if I use the @Value annotation. I can't find any difference to the other services. I'm using Spring cloud config server. It seems there is no problem to get the profiles from config server:

    [main] INFO 
    org.springframework.cloud.config.client.ConfigServicePropertySourceLocator - 
    Fetching config from server at: https://myurl:8888
    [main] INFO org.springframework.cloud.config.client.ConfigServicePropertySourceLocator -     Located environment: name=webapimngmtservice, profiles=[local], label=null, version=41d49e837c4d58b113611c5b8c13979922397238, state=null
    [main] INFO org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration - Located property source: CompositePropertySource [name='configService', propertySources=[MapPropertySource {name='configClient'}]]
    [main] INFO de.sharing.webapimngmt.WebapimngmtApplication - The following profiles are active: local
    

    Now the stack-trace:

    Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
     [main] ERROR org.springframework.boot.SpringApplication - Application startup failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webapimngmtApplication': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'keycloak.realm' in value "${keycloak.realm}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1268)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    at de.sharing.webapimngmt.WebapimngmtApplication.main(WebapimngmtApplication.java:41)
     Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'keycloak.realm' in value "${keycloak.realm}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:837)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1086)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    ... 15 more
    

    This is my Application-Class:

    @SpringBootApplication
    @ComponentScan({ "de.sharing.webapimngmt.configuration", "de.sharing.webapimngmt.api", "de.sharing.webapimngmt.handler", "de.sharing.webapimngmt.service" })
    public class WebapimngmtApplication {
    
    public static final String PROVIDER_KEY_SHARING_SERVER = "service-tokenprovider";
    
    @Value("${keycloak.realm}")
    private String keycloakRealm;
    
    @Value("${keycloak.auth-server-url}")
    private String keycloakServerURL;
    
    @Value("${keycloak.resource}")
    private String keycloakClientId;
    
    @Value("${keycloak.credentials.secret}")
    private String keycloakClientSecret;
    
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(WebapimngmtApplication.class);
        springApplication.addListeners(new ApplicationPidFileWriter());
        springApplication.run(args);
    }
    
    @Bean
    public ServiceClient serviceClient() {
        ServiceClient serviceClient = new ServiceClient();
        ITokenProvider serviceTokenProvider = new ServiceTokenProvider(this.keycloakServerURL, this.keycloakRealm, this.keycloakClientId, this.keycloakClientSecret);
        serviceClient.putTokenProviderToStore(PROVIDER_KEY_SHARING_SERVER, serviceTokenProvider);
        return serviceClient;
    }
    }
    

    This is my config-file:

    #####SPRING-CLOUD-SETTINGS:  ######
    spring.cloud.config.enabled=true
    #####EUREKA-SETTINGS:  ######
    eureka.instance.preferIpAdress=true
    eureka.client.register-with-eureka=false
    eureka.client.fetch-registry=false
    eureka.client.serviceUrl.defaultZone=    {cipher}7ad0c41cba27150d50f488359d55eb96f7eaea5ab4fe9c43424048fd580f01f0fb486c7ad825d87e137d1ef3b286f31c5df2830d75ae68d9883cb996273fcec6
    #####KEYCLOAK-SETTINGS - GENERAL:######
    security.basic.authorize-mode=role
    keycloak.enabled=true
    keycloak.realm ={cipher}90d6d4e0b515a8fd01d2e8a967c09ed70788348d6045020ed9852e293e515ce8
    keycloak.auth-server-url={cipher}83fc4549f1cbbdf4beb94acc2cb3bb49760470f0649c0e957c3adcef6279682a3dc3abde090892095db3498554d4e12694f42175337e2dca9c725f30196bd8eb
    keycloak.ssl-required=external
    keycloak.autodetect-bearer-only=true
    keycloak.resource={cipher}45ff83eec48ca1c3773cc555e8749265e17f4a71441da91caeb845d79cce236a8c7f8bb07c3d6383d8ef025fd7e6b3f8
    keycloak.credentials.secret={cipher}d73b63d03ca411fbb57a6e1f5204a2d398f6c1d76cc4747cc7a7ee9ad14e0c0bbc21ddaeb9915bc06d9e100b495476f4e01a128d15a3eab973af0620bef3b5e6
    keycloak.use-resource-role-mappings=true
    #####KEYCLOAK-SETTINGS- ROLES:######
    keycloak.security-constraints[0].securityCollections[0].name=api-doc
    keycloak.security-constraints[0].securityCollections[0].patterns[0]=/rest-api.html
    keycloak.security-constraints[0].authRoles[0]=API_DOC
    #####Service To Service Communication:#####
    sharing.service.usermngmt.url=https:/myurl.com/
    sharing.service.productmngmt.url=https://myurl.com/
    #####TLS-SETTINGS:  ######
    server.ssl.enabled=true
    server.ssl.key-store =classpath:keystore.jks
    server.ssl.key-store-type=JKS
    server.ssl.key-store-password={cipher}7237044311ad207cca27578772985f317c02f8e11af4c295b182abc1de845f6f
    server.ssl.key-alias=myalias
    server.ssl.key-password={cipher}7237044311ad207cca27578772985f317c02f8e11af4c295b182abc1de845f6f
    server.ssl.trust-store=classpath:keystore.jks
    server.ssl.trust-store-type=JKS
    server.ssl.trust-store-password={cipher}7237044311ad207cca27578772985f317c02f8e11af4c295b182abc1de845f6f
    server.ssl.protocol=TLS
    security.basic.enabled=false
    ####SERVER-SETTINGS#####
    security.enable-csrf=false
    server.port=5030
    server.session.timeout=900
    

    Has anyone any idea what I am missing?

    Update:

    I Just figured out that the config server retrieves an empty list of propertySources:

    {
    "name": "webapimngmtservice",
    "profiles": [
        "dev"
    ],
    "label": null,
    "version": "cebc38d6688557e4dec95496544faf0df824aa1a",
    "state": null,
    "propertySources": []
    }
    
    • Sven Hakvoort
      Sven Hakvoort almost 6 years
      Can you also provide the relevant configuration file?
    • Hussain Akhtar Wahid 'Ghouri'
      Hussain Akhtar Wahid 'Ghouri' almost 6 years
      yml format seems to be broken , please verify yml file
    • n00bst3r
      n00bst3r almost 6 years
      added my config file @SvenHakvoort
    • Pavel Molchanov
      Pavel Molchanov almost 6 years
      Can it be because of the space after keycloak.realm = in the configuration? Other values do not have space before the = sign.
    • Sven Hakvoort
      Sven Hakvoort almost 6 years
      I tried that in one of my own projects @PavelMolchanov and in my case it didn't make a difference.
    • Sven Hakvoort
      Sven Hakvoort almost 6 years
      @n00bst3r can you provide a git repo with this project? Then i can try some things
    • n00bst3r
      n00bst3r almost 6 years
      @SvenHakvoort unfortunately it isn't a public repo. But I just figured out that the config server retrieves onyl an empty list of propertySources.