Spring boot config client properties - spring

//This is the value of the property which needs to be fetched via config server from git repo
ConfigClientController(#Value("**${foo:test}"**) String value) {
this.value = value;
}
The above code is a spring cloud config client(spring.application.name=foo) that gets the config properties from the git config repo.
Foo is the property in foo.properties. Here I am little confused about the :test param in the code above. I wanted to know what is the significance of this param in getting the property.

If foo parameter is not present meaning it cannot be obtained from the config test string will be used instead. Meaning - what's after the : is a default value for the #Value annotated param.

Related

Spring Cloud Config Server ResourceController does not map request with useDefaultLabel when path contains slashes

I have a simple Spring Cloud Config Server project (using spring-cloud-config-server-4.0.0)
With a default branch property set
spring.cloud.config.server.git.default-label
This works without a label:
GET http://localhost:8888/myAppName/myProfiles/test.txt?useDefaultLabel
This does not (path includes slash):
GET http://localhost:8888/myAppName/myProfiles/path/test.txt?useDefaultLabel
Throws the following Exception:
RefNotFoundException: Ref path cannot be resolved
...
at org.springframework.cloud.config.server.resource.ResourceController.retrieve(ResourceController.java:107)
It resolves to the wrong controller endpoint:
#GetMapping("/{name}/{profile}/{label}/**")
instead of
#GetMapping(value = "/{name}/{profile}/{path:.*}", params = "useDefaultLabel")
To my understanding this should work because of this change: https://github.com/spring-cloud/spring-cloud-config/issues/824
I've tried without success:
Encoding the slash
Assigning something ("true") to the useDefaultLabel request parameter

Spring spring.profiles.include: doesn't read profile-related properties

There are several ways present to define "active profiles" for a Spring Boot application.
The default one is to pass it through a command line, like this:
java -Dspring.profiles.active=dev,local -jar myapp.jar
it works just fine (as expected): All three sets of profile-related properties will be loaded in proper order:
application.yaml
application-dev.yaml will override the previous one
application-local.yaml will override the previous one as well (these properties will have the most priority)
Based on the idea, that my "local" profile should always "use and overrides" properties from the "dev", let's "hardcode" such behavior.
Let's use the 'spring.profiles.include' feature for this. So, the following lines are added to the 'application-local.yaml':
spring.profiles:
include:
- dev
I expect, now I can pass the "local" profile only in the command line, and the "dev" profile will be applied automatically (with his properties, of course):
java -Dspring.profiles.active=local -jar myapp.jar
But ooop!*: properties from the 'application-dev.yaml' are ignored.
Why? Is it a bug? Is it a feature that forces me to list all profiles in a command line directly?
I'm sure that the behavior around profiles activation should be the same without any difference in how the active-profiles list was passed to Spring Boot framework.
The application:
#SpringBootApplication #EnableConfigurationProperties( MyProps::class )
class SpringApp4
#ConfigurationProperties("my.db") #ConstructorBinding
data class MyProps(val name: String, val url: String, val user: String)
#Component
class MyRunner(val myProps: MyProps, val env: Environment) : CommandLineRunner {
override fun run(vararg args: String) {
println("myProps = $myProps")
println("activeProfiles = ${env.activeProfiles.joinToString()}")
exitProcess(0)
}
}
fun main() { runApplication<SpringApp4>() }
application.yaml:
my.db:
name: "default-name"
url: "default-url"
user: "default-user"
application-dev.yaml:
my.db:
url: "dev-url"
user: "dev-user"
application-local.yaml:
spring.profiles.include:
- dev
my.db:
user: "local-user"
Run1: java -Dspring.profiles.active=dev,local -jar myapp.jar
Correct output:
myProps = MyProps(name=default-name, url=dev-url, user=local-user)
activeProfiles = dev, local
it's correct because the url=dev-url
Run2: java -Dspring.profiles.active=local -jar myapp.jar
Incorrect output:
myProps = MyProps(name=default-name, url=default-url, user=local-user)
activeProfiles = local
It's not correct because the url=default-url and the activeProfiles doesn't contain the "dev" at all.
Help me please to figure out how to use the spring.profiles.include feature in yaml to build a kind of top level profiles that will activate other automatically.
In Run2 You are giving profile as local
i.e
-Dspring.profiles.active=local
So spring will first load application.yml and then application-local.yml
I can see the output is expected.
Since some properties like name and url are not present in application-local.yml, so the values of these fields will be same as present in application.yml
FYI : application.yml is always called irrespective of profile, and then it gets overridden by the profile mentioned in -Dspring.profiles.active property
spring.profiles.include deprecated in Spring Boot 2.4 and no longer works: https://spring.io/blog/2020/08/14/config-file-processing-in-spring-boot-2-4
It caused recursive resource loading; that broke Kubernates ConfigMap so they removed recursion.
Use spring.profiles.active or spring.profiles.group.

Spring ignores `spring.cloud.config.discovery` set as default properties

I'm trying to create Spring Application without referring to any external files. This is supposed to be a module that you'd then include as a dependency, configure and use to plug in the service into an existing ecosystem. This is how I'm doing that:
Map<String, Object> properties = new HashMap<>();
properties.put("server.address", "0.0.0.0")
properties.put("server.port", 8080)
properties.put("spring.profiles.active", "cloud")
properties.put("spring.application.name", "someApp")
properties.put("spring.cloud.config.failFast", true)
properties.put("spring.cloud.config.discovery.enabled", true)
properties.put("spring.cloud.config.discovery.serviceId", "config")
properties.put("eureka.instance.preferIpAddress", true)
properties.put("eureka.instance.statusPageUrlPath", "/health")
new SpringApplicationBuilder()
.bannerMode(Banner.Mode.OFF)
.properties(properties)
.sources(SpringConfiguration.class)
.web(false)
.registerShutdownHook(true)
.build()
I then go on to provide Eureka default zone in the run command, via environmental variables:
--env eureka_client_serviceUrl_defaultZone='http://some-host:8765/eureka/' --env SPRING_CLOUD_CONFIG_LABEL='dev' --env SPRING_CLOUD_INETUTILS_PREFERRED_NETWORKS='10.0'
Application registers successfully in Eureka, but unfortunately it tries to fetch the config prior to that and it's looking for it under the default URL (http://localhost:8888) instead of fetching config server IP from the registry. And yes, it does work if I put all of those properties in the bootstrap.yml file. Can I somehow make it work without using file-resources?
You are passing the properties using SpringApplicationBuilder which is responsible for SpringApplication and ApplicationContext instances.
From the documentation , the properties provided here will be part of ApplicationContext NOT the BootstrapContext. ApplicationContext is the child of BootstrapContext.
You can read more about the Bootstrap Context here -
http://cloud.spring.io/spring-cloud-commons/1.3.x/single/spring-cloud-commons.html#_the_bootstrap_application_context
Bootstrap.yml/properties is used to configure your Bootstrap Context.
You can look at these properties to change the name or location of the file -
spring.cloud.bootstrap.name - bootstrap(default)
spring.cloud.bootstrap.location
You will have to use a file resource(yml or properties).

Call /env on Spring cloud config client side, password property shows " portal.db.password=*** "

My config file on remote git repo:
myapp-uat.properties:
portal.db.userName=allen
portal.db.password=allen1235
I could load this file on client side, and I want save these properties by call /env, but get portal.db.password=***.
I wonder if I could get real value (portal.db.password=allen1235) by adding some properties in client config file or some other methods. Hope for your help.
The below is the default sanitized keywords for /env endpoint.
endpoints:
env:
keys-to-sanitize: password,secret,key,token,.*credentials.*,vcap_services
You can override the below property without password by defining below in your application.yml/properties.
endpoints:
env:
keys-to-sanitize: secret,key,token,.*credentials.*,vcap_services

#ConfigurationProperties not pulling the external properties file

I've created a personal repository on Git where I have kept my application.properties file.
I've created a cloud config server ('my-config-server') and used the git repository url.
I have bound my spring-boot application that is supposed to access the external properties file with Git repository.
#javax.jws.WebService(
serviceName = "myService",
portName = "my_service",
targetNamespace = "urn://vdc.com/xmlmessaging/SD",
wsdlLocation = "classpath:myService.wsdl",
endpointInterface = "com.my.service.SDType")
#PropertySource("application.properties")
#ConfigurationProperties
public class SDTypeImpl implements SDType {
/*It has various services implementation that use following method**/
private SDObj getObj (BigDecimal value) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(
SDTypeImpl.class);
SDObj obj = context.getBean(SDPropertiesUtil.class).getObj(value);
context.close();
return obj;
}
}
Another Class:
public class SDPropertiesUtil {
#Autowired
public Environment env;
public SDObj getObj(BigDecimal value) {
String valueStr = env.getProperty(value.toString());
/*do logic*/
}
My application starts but fails to load properties file from my git repository.
I believe I should have an application.properties at src/main/resources in my application but since I'm using
#PropertySource("application.properties")
#ConfigurationProperties
I'm telling my application to use the application.properties from an external location and do not use internal properties file. But this is not happening. My application is still using the internal properties file.
The source you included doesn't show your app configuration settings to connect to the Config server. Do you mind sharing it?
This is how the config server could be queried from a client app:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
Let's say a Config server points to a Git repo which includes this file: demo-config-client-development.properties
You should be able to query the Config Server as:
curl http://localhost:8101/demo-config-client-development.properties
Assuming Config Server is running in locally and listening on 8181.
Let's also say you have a client app named: demo-config-client that connects to the Config server and runs using the development Spring profile, this app would now be able to read remote properties hosted in a Git repo through a Config server.
A detailed tutorial could be found at my blog at: http://tech.asimio.net/2016/12/09/Centralized-and-Versioned-Configuration-using-Spring-Cloud-Config-Server-and-Git.html

Resources