I am trying to learn Spring Cloud Config. So first I setup a Server, where I can fetch the properties using http://localhost:9090/config/default/master/app.static.properties
on the browser. It has about 5 or 6 properties. I am trying to get just one for now.
I wrote my classes like:
package com.gcp.logicalprovisioning.config.server; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class DemoClientApplication { private static final Logger LOGGER = LoggerFactory.getLogger(DemoClientApplication.class); public static void main(String[] args) { SpringApplication.run(DemoClientApplication.class, args); } /** * Output property from cloud-config-server on startup of app, * * also can be seen at: * http://localhost:9090/env/APP.aaf.env */ @Bean public CommandLineRunner printProperties(@Value("${APP.aaf.env}") final String appProperty) { return args -> LOGGER.info("APP.aaf.env is: [{}]", appProperty); } }
and
package com.gcp.logicalprovisioning.config.server; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController // This will allow us to reinitialize this controller to get any new config // values when the /refresh endpoint is POSTed to. @RefreshScope public class DemoClientController { @Value("${APP.aaf.env}") private String appProperty; @RequestMapping("/") public String hello() { return "Using [" + appProperty + "] from config server"; } }
My bootstrap.properties look like:
spring.application.name=client spring.cloud.config.label=master spring.cloud.config.uri=http://localhost:9090/config/default/master/ spring.cloud.config.enabled=true spring.security.user.name=admin spring.security.user.password=admin logging.level.web=DEBUG debug=false spring.output.ansi.enabled=ALWAYS spring.devtools.restart.enabled=true spring.config.import=optional:configserver:http://localhost:9090/ spring.cloud.config.import-check.enabled=false
But I get this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'printProperties' defined in com.gcp.logicalprovisioning.config.server.DemoClientApplication: Unexpected exception during bean creation; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'APP.aaf.env' in value "${APP.aaf.env}" at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:537) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.9.jar:5.3.9] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.9.jar:5.3.9] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.3.jar:2.5.3] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-2.5.3.jar:2.5.3] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) [spring-boot-2.5.3.jar:2.5.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) [spring-boot-2.5.3.jar:2.5.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) [spring-boot-2.5.3.jar:2.5.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) [spring-boot-2.5.3.jar:2.5.3] at com.att.logicalprovisioning.config.server.DemoClientApplication.main(DemoClientApplication.java:20) [classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_281] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_281] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_281] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_281] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.5.3.jar:2.5.3] Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'APP.aaf.env' in value "${APP.aaf.env}" at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180) ~[spring-core-5.3.9.jar:5.3.9] at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) ~[spring-core-5.3.9.jar:5.3.9] at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239) ~[spring-core-5.3.9.jar:5.3.9] at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) ~[spring-core-5.3.9.jar:5.3.9] at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175) ~[spring-context-5.3.9.jar:5.3.9]
I searched for the problem on StackOverflow, found a few solutions, tried it. But nothing worked. But since I am getting my feet wet, I am not exactly sure what is going wrong. Am I missing some extra configuration? Any help would be appreciated.
I haven’t posted my server’s code, if needed let me know, I will add it.
Advertisement
Answer
With help for Gregor, I was able to solve it. These are the changes I did:
I added a messageConverter
:
package com.gcp.logicalprovisioning.config.server; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class DemoClientApplication { private static final Logger LOGGER = LoggerFactory.getLogger(DemoClientApplication.class); public static void main(String[] args) { SpringApplication.run(DemoClientApplication.class, args); } /** * Output property from cloud-config-server on startup of app, * * also can be seen at: * http://localhost:9090/env/APP.aaf.env */ @Bean public CommandLineRunner printProperties(@Value("${APP.aaf.env}") final String appProperty) { return args -> LOGGER.info("APP.aaf.env is: [{}]", appProperty); } @Bean public RestTemplate restTemplate() { final RestTemplate restTemplate = new RestTemplate(); List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL)); messageConverters.add(mappingJackson2HttpMessageConverter); restTemplate.setMessageConverters(messageConverters); return restTemplate; } }
And in the bootstrap.properties
, added a few extra configs here too:
debug=false logging.level.web=DEBUG server.port=1010 spring.application.name=app.static spring.cloud.config.uri=http://localhost:9090/ spring.cloud.config.username=admin spring.cloud.config.password=admin spring.cloud.config.enabled=true spring.cloud.config.import-check.enabled=false spring.devtools.restart.enabled=true spring.output.ansi.enabled=ALWAYS spring.security.user.name=admin spring.security.user.password=admin
Now I can fetch the configs from the config server by using the URL http://localhost:9090/app.static/default
So in short:
- I had to add messageConverter.
- Change the git.config.uri.
- And add username/password to the bootstrap.properties because the config server is tied with a username/password.
- Remove the spring.config.import properties.