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.
Please note that Spring Cloud Config Server client will build the full path to your application's profile specific configuration for you. Therefore, you should only provide the base URL in bootstrap.properties
. In your case this would be probable some like this:
spring.cloud.config.uri=http://localhost:9090/
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With