How can I inject OS hostname value in Spring Boot? - spring

Is it possible to do something like that?
#Value("${xxx.hostname}")
private String hostname;
Is it also possible to get any other System Environment Property like that?

Spring Boot automatically allow you to take environment variable.
You can just do #Value("${HOSTNAME}") (if HOSTNAME is defined ofc)
You can also use your application.properties to have something like :
xxx.hostname = ${HOSTNAME}

Related

Override Spring Boot yaml property via environment variable

Using Spring Boot 2.6.1, If I have an application.properties file that looks like:
spring.datasource.url="jdbc://blahblah"
I can override that value at runtime with an environment variable named spring.datasource.url and my application will connect to the database specified in the env var.
However, if I have an equivalent application.yaml file, specifying the environment variable that way appears to have no effect.
spring:
datasource:
url: "jdbc://localhost..."
However, if I rename my environment variable to SPRING_DATASOURCE_URL, the override works again. This appears to be consistent across other properties as well (not just the datasource url).
Looking through the docs it wasn't obvious why this should be the case, except that yaml configuration seems like it's generally treated a little different than "normal" properties files.
Is this behaviour expected?
As described in the documentation, you should use the environment variable SPRING_DATASOURCE_URL to set the spring.datasource.url property. I am surprised that spring.datasource.url worked at all when configured as an environment variable and I would not rely on it continuing to do so.

Injecting default "management.endpoints.web.base-path" value in Spring Boot 2.1

I'm trying to inject "management.endpoints.web.base-path" into my class's field that I need to know. I did a few hours of search for it, but all the answer is "how to customize your endpoint" by setting management.endpoints.web.base-path in the application.xml(or yaml), not "how to get a default of management.endpoints.web.base-path".
Simple code as below was expecting to grab whatever variable loaded when Spring Boot app is starting up, but nothing was retrieved in the variable.
#Autowired
private Environment environment;
public void myMethod(){
final String actuatorBase = environment.getProperty("management.endpoints.web.base-path");
}
If I define it in the application.properties I should be able to load it for sure, but I'd like to know why the default("/actuator") can't be retrieved here. However when I run the application, I had no problem to access all the actuator related functionality endpoint through /actuator.
Since it doesn't work, injecting the variable with #Value annotation also doesn't work either.
When I checked the environment variable in the debugger, I was able to see application.yaml is loaded and all the overrides variables are there, too, but not all the default "management" stuff was there.
Any idea? This app has some custom configuration, not using all the AutoConfigurer stuff, so wondering if there is specific autoconfig I need to use to make it happen.
I'm using Spring Boot 2.1.0.RELEASE.
Self answering here.
WebEndpointProperties is the one that loads all the management.endpoints.web prefix properties, so simply
#Autowired
private WebEndpointProperties webEndpointProperties;
in the class and then
String actuatorWebBasePath = this.webEndpointProperties.getBasePath();
in my method gave me a base path(/actuator).

Custom application property to be supplied to spring boot app through cmd line

I was wondering if we can supply a custom attribute (a key to be in application.properties file), I know for sure that -Dserver.port=8080 works, and overrides the property value, but server.port is a spring boot's expected property value.
How about something other than that, for example a jdbc connection string or service name? does -Ddb.service.name=dbservice work?
Yes, any property can be set via system property. You can use -D or -- notation. There are also a variety of property sources Spring Boot uses:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Setting variable value based on spring profile

How to assign value to variable based on region?
Lets says
system properties,
dev-url="dev-abc.com",
prod-url="prod-abc.com" and
qa-url="qa-abc.com"
#Value( #{systemProperties. ??? )
String url;
if you have all properties inside on property file you can use :
#Value("${spring.profiles.active}-url") String url;
I would suggest to avoid profiles as much as possible. Modern applications should strive to follow rule 3 of 12 Factor app:
The twelve-factor app stores config in environment variables
With Spring Boot you would have environment variable URL environment variable and use it in Spring Boot as ${URL}. Each environment would have this environment variable configured to correct value.

Set/override Spring / Spring Boot properties at runtime

At the project with Spring Boot we use application.properties but need to configure some of these properties (like port number of logging level) based on an external configuration. We access the configuration via API so it is known only at runtime.
Is there a way to override or set some Spring properties at runtime (for example using a bean) and if yes how can this be achieved?
You could do this with Spring Cloud Config
Just for the purpose of illustration, here's a relatively quick way to see dynamic property overrides at runtime:
First, for your bean to be able to pick up changed properties, you need to annotate it with
#RefreshScope
Add the spring cloud dependency to your spring boot app, eg for gradle
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter', version: '1.1.1.RELEASE'
( NB You also need the spring boot actuator dependency.)
With the app running, you can view your current config at eg
http://localhost:8080/env
eg if you have a property 'my.property' in application.properties, you'll see something like:
"applicationConfig: [classpath:/application.properties]": {
"my.property": "value1",
etc
To change the value, POST my.property=value2 to /env as application/x-www-form-urlencoded
eg
curl -X POST http://localhost:8080 -d my.property=value2
GET /env again and you'll see the new value appears under the "manager" section
To apply the changed properties, do an empty POST to /refresh. Now your bean will have the new value.
Could you use system properties to pass in the variable? If you configure the PropertyPlaceholderConfigurer you can set the precedence of system properties vs file properties.
For example, something like:
#Bean public PropertyPlaceholderConfigurer placeHolderConfigurer() {
PropertyPlaceholderConfigurer props = new PropertyPlaceholderConfigurer()
props.setSystemPropertiesMode( PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE )
props.setLocations(new
PathMatchingResourcePatternResolver().getResources("classpath:/**.properties"));
props
}
The above would load your .properties file, but we set the priority to be system variables first, so if you set a system variable that will override the same variable in the config.
Alternatively, looking at the docs, Spring recommends defining a search order in your Environment:
[PropertyPlaceholderConfigurer is still appropriate for use when]
existing configuration makes use of the "systemPropertiesMode" and/or "systemPropertiesModeName" properties. Users are encouraged to
move away from using these settings, and rather configure property
source search order through the container's Environment; however,
exact preservation of functionality may be maintained by continuing to
use PropertyPlaceholderConfigurer.
Hopefully one of the above should sort out what you need?

Resources