How define properties names using #ConfigurationProperties in Spring? - spring

I have class:
#ConfigurationProperties(prefix = "user")
public class BarcodeConfig {
private String customName;
private Details customDetails;
And property file with:
user.name=sampleName
user.details.address=sampleAddress
user.details.something=sampleSomething
How map "user.name" to field "customName" and "user.details.*" to "customeDetails" without changing field names?

you can use #AliasFor("name")

You have to provide the property path from your configuration file using the #Value annotation.
For example, if you want to map the user.name to customName:
...
#Value(${user.name})
private String customName;
...
Spring will automatically fetch the user.name property value and assigns it to the customName variable attribute.

Related

Hi I'm trying to add #Value("${name}") private String name; in dto field but not able to read it from application.properties

class dto{#Value("${name}") private String name; }
application.properties
op.name=${OP_NAME:22-2}
//When I try to read it is returning null how to solve this
The #Value annotation will only be processed on Spring-managed beans (e.g. a #Component annotated class).
Additionally, you would need to specify the property key in #Value as follows in order to match with the key defined in your property file:
#Value("${op.name:fallback}")
private String name;
Your properties file can then carry the configurable value:
op.name=Some Name

Initialize a list of map using ConfigurationProperties in Spring

I am looking for a neat way to initialize a List of Maps using Spring Boot from application.properties.
#ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private List<Map<String,String>> userList;
// standard getters and setters
}
I want to initialize the List of Maps "userList" from application.properties. How do we give values to mail.userList below in the application.properties file?
#application.properties
mail.hostname=host#mail.com
mail.port=9000
mail.userList=?
Thanks in advance.
You need to define it like this,
mail.userList[0].id=1
mail.userList[0].name=abc
mail.userList[1].id=2
mail.userList[1].name=pqr
mail.userList[2].id=3
mail.userList[2].name=xyz
This will load the in the userlist as list of map. Each entry in the list would contain
id and name.

validate ConfigurationProperties mapping

Is there a way to validate application.properties (or yml) if the properties match Java bean that it is mapped to via #ConfigurationProperties - so that if there is a typo in an attribute, exception will be thrown?
I tried using #Validated but it works only if every property has #NotNull annotation - but this is not exactly what I want to achieve... there may be some nullable properties in the config and I still want to "validate" them
I just spent 2 hours debugging an issue and I found out, the problem is that I misspelled an attribute name
e.g. application.yml
property1: 1
properrrrrty2: 2
#Configuration
#ConfigurationProperties
public class AppConfig {
private String property1;
private String property2; // <--- this property does not match due to typo in application.yml
}
A)
If you want to be sure that always a property exists then use #Validated with #NotNull for that property. #NotNull will complain if it does not find that property. You can still have the property there with an empty value if that is what you mean with nullable properties and NotNull will not complain.
You can't say I want it to be able to be nullable but also the validator should complain when that property is null.
So to sum things up.
#NotEmpty property must exist and also not have an empty value
#NotNull property must just exist. It does not care if it exists with an empty value.
That's why I insist you go with NotNull for your requirements.
B)
Also I can think of another way to handle that.
#Component
public class AppConfig {
#Value("${property1}")
private String property1;
#Value("${property2}")
private String property2;
}
Using injection with #Value, spring will fail to initialize the singleton AppConfig during application startup if some property with exactly the same name does not exist on properties file, therefore you will be informed that no property with that name exists and the application will not start up.
You can specify ignoreUnknownFields = false to ensure that no unknown properties are defined under the corresponding prefix. (docs):
Flag to indicate that when binding to this object unknown fields should be ignored. An unknown field could be a sign of a mistake in the Properties.
Borrowing from your example:
#Configuration
#ConfigurationProperties(prefix = "myapp", ignoreUnknownFields = false)
public class AppConfig {
private String property1;
private String property2;
}
This means myapp.property1 and myapp.property2 are allowed but not required to be set, so they remain nullable.
Any other set property with the myapp prefix (such as myapp.properrrrrty2=2) will cause a startup failure and the offending property name will be logged in the exception.

How to read property as List<String> from [] in springboot

Sometime i see somebody define like this in property file:
spring.autoconfigure.exclude[0]=com.vietnam.AAutoConfiguration
spring.autoconfigure.exclude[1]=com.vietnam.BAutoConfiguration
just question: how to define a property in Spring bean to collect this config as list?
in other place they said to use like this:
in propery:
spring.autoconfigure.exclude=com.vietnam.AAutoConfiguration,com.vietnam.BAutoConfiguration
in spring bean
#Value("#{'${spring.autoconfigure.exclude}'.split(',')}"
But i dont like this way in case the value is long. one config per line would be easier to read and mantain
Thanks
You can read multiple strings like below
in application.properties
app.names=vipul,uncle,bob
in you component class
#Value("${app.names}")
private List<String> names;
i found the way, use #Value will not support case i want.
We need to use #ConfigurationProperties then Spring will collect property as list
#ConfigurationProperties(prefix = "spring.autoconfigure")
public class SpringConfig {
#Setter //lombok
private List<String> exclude;
}
Config will simple like:
spring.autoconfigure.exclude[0]=com.vietnam.AAutoConfiguration
spring.autoconfigure.exclude[1]=com.vietnam.BAutoConfiguration
Lists may also be like this
app.names={'Baeldung','dot','com'}
app.names2={\
'One long text example',\
'Another long text example'\
}
#Value("#{${app.names}}")
private List<String> appNames;
Source https://www.baeldung.com/spring-inject-arrays-lists
Map example:
valuesMap={key1: '1', key2: '2', key3: '3'}
#Value("#{${valuesMap}}")
private Map<String, Integer> valuesMap;
Source https://www.baeldung.com/spring-value-annotation

Spring does not complain if a property is not set when using ConfigurationProperties

I have a bean that is configured via ConfigurationProperties:
#Component
#ConfigurationProperties(prefix = "mybean")
public class MyBean {
#NotEmpty
private String name;
// Getters, setters, ...
}
I configure the field values via application.yml but in "two levels". In the default application.yml I just set the value to the value of another property:
myBean.name: ${theValueOf.myBean.name}
In the profile specific YML file I have:
theValueOf.myBean.name: 'The desired value'
My expectation would be that if I forget to specify the property theValueOf.myBean.name then the application should fail at startup with the message that the placeholder 'theValueOf.myBean.name' could not be resolved. Instead, the field name is assigned the value (literally) ${theValueOf.myBean.name}.
If I annotate the name field with #Value("${myBean.name}") (and do not use ConfigurationProperties), and forget to define the property theValueOf.myBean.name, then the application fails at startup -- as expected.
My question is: How can I make Spring fail at startup with the message 'Could not resolve placeholder ...' when using ConfigurationProperties?
Simply mark your properties with JSR303 annotations, inside your #ConfigurationProperties.
#Component
#ConfigurationProperties(prefix = "mybean")
public class MyBean {
#NotEmpty
private String name;
}

Resources