Can property name be given alias - spring

I'm using a 3rd party Spring Boot module that requires a "validation.url" property to be set
This same value exists in our centralized config service as "url.for.validation", which we retrieve via a PropertyPlaceholderConfigurer
Outside of intercepting the Properties from the PropertyPlaceholderConfigurer and adding a new one for "validation.url", what is the recommended way to achieve this?
Is there any alias functionality for properties?

Related

How to get access and customize Freemarker's Configuration object in spring-boot 2.x?

How to get access and customize Freemarker's Configuration object in spring-boot 2.x?
It allows to set square bracket syntax as default option with something like:
Configuration#setTagSyntax(Configuration.SQUARE_BRACKET_TAG_SYNTAX)
which is not possible with any of spring.freemarker.* configuration property.
Also, it should be possible to introduce default imports having access to direct configuration of this object.
It's possible to set any FreeMarker configuration settings with spring.freemarker.settings.<settingName>, like spring.freemarker.settings.tagSyntax = square_bracket. See the JavaDoc of Configuration.setSetting(String, String) for more (https://freemarker.apache.org/docs/api/freemarker/core/Configurable.html#setSetting-java.lang.String-java.lang.String-). This is the method to which Spring delegates the assignments under spring.freemarker.settings; Spring itself doesn't know what "settings" exist or how to parse them.

Spring boot - expose common application properties with different names

I have a requirement where I need my custom application properties to act as aliases to various common application properties that spring provides for different packages.
Example:
Whenever I set a value to the application property foo.host, it should set the value for spring.rabbit.host property.
Similarly setting the value for foo.port should set the value for spring.rabbitmq.port.
Can this be achieved?
It can, you can add these to your application.properties:
spring.rabbit.host=${foo.host}
spring.rabbit.port=${foo.port}
However, if you still provide spring.rabbit.host via system properties, as an environment variable or as direct argument then it will take precedence over foo config.

How do I access Spring properties in a logback configuration

Is there a way to access Spring properties within a logback.xml file?
I know one can import a properties file if you know its location, but I'm using Spring profiles to control where the properties file should be loaded or not.
Is there done kind of connector that asked me to feed Spring data into logback? This would only be at startup; I don't need to be able to do this on the fly.
I'm guessing you do have to import a property file (common property file, non-environment specific one) that will contain the name of the property that you are going to use in the logback.xml, and that you want to optionally override the value of the property for some environment (you need at least one property file containing the name of the property, because you will be using that property in the logback.xml, and you need it to be available to be able to use it).
For the optional environment-override, how about including an additional property file? For example, we use both application.properties and application-${spring.profiles.active}.properties files. Then if we don't need to override the property for some environment, we simply don't include it in the environment specific property file (application-dev.properties, etc.)

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?

Spring environment validation

We're building a Spring-based application which will be delivered to end users as a distribution package. Users are responsible for properly configuring whatever needs to be configured (it's mostly about various filesystem locations, folder access permissions, etc). There's a good idea to make the app help users understand what is not configured or which parts of configuration are invalid.
Our current approach is a custom ApplicationContextInitializer which does all the environment validation "manually" and then registers few "low level" beans in the application context explicitly. If something is wrong, initializer throws, exception is caught somewhere in main(), interpreted (converted into plain English) and then displayed.
While this approach works fine, I'm wondering if there are any best practices to minimize hand-written code and use Spring whenever possible.
Here's an illustrative example. The application requires a folder for file uploads. This means:
There should be a configuration file
This file should be accessible by the app
This file should have no syntax errors
This file should explicitly define some specific property (let it be app.uploads.folder)
This property should describe the existing filesystem entity
This entity should be a folder
The app should have read/write access to this folder
Does Spring provide any tools to implement this sort of validation easily?
Spring Boot has a nice feature for context and external configuration validation. If you define a POJO class and declare it as #ConfigurationProperties then Spring will bind the Environment (external properties and System/OS typically) to its properties using a DataBinder. E.g.
#ConfigurationProperties(name="app.uploads")
public class FileUploadProperties {
private File folder;
// getters and setters ommitted
}
will bind to app.uploads.folder and ensure that it is a File. For extra validation you can do it manually in the setter, or you can implement Validator in your FileUploadProperties or you can use JSR-303 annotations on the fields. By default an external property in app.uploads.* that doesn't bind will throw an exception (e.g. a mis-spelled property name, or a conversion/format error).
If you use Spring Boot Autoconfigure #EnableAutoConfigure you don't have to do anything else, but if it's just vanilla Spring (Boot) you need to say #EnableConfigurationProperties in your #Configuration somewhere as well.
A bonus feature: if you also use the Spring Boot Actuator you will also get JMX and HTTP support (in a webapp) for inspecting the bindable and bound properties of #ConfigurationProperties beans. The HTTP endpoint is "/configprops".

Resources