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

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

Related

How define properties names using #ConfigurationProperties in 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.

Spring property binding with multiple separation

I have an application.property like this:
somevalue.api.test=something
somevalue.anotherproperty=stuff
I have made a configuration bean like this:
#Configuration
#ConfigurationProperties("somevalue")
public class SomeProperties {
#NotNull
private String apiTest;
#NotNull
private String anotherproperty;
}
Is it possible to refer to api.test like apiTest?
Mainly my issue is that I want to use the somevalue starting point for both property. I know if I don't separate with a dot the apiTest and I use it in this way somevalue.api-test I can refer to that with apiTest in my bean, but in my case it's not possible the renaming. So with dot separation can I achieve the same result or I should create two separate config bean, one refering to somevalue.api and the another only to somevalue?
If you can't rename the property then no, you can't reference it using String apiTest. You need an additional class as follows:
#Configuration
#ConfigurationProperties("somevalue")
public class GcssProperties {
#NotNull
private GcssApiProperties api;
#NotNull
private String anotherproperty;
}
public class GcssApiProperties {
#NotNull
private String test;
}
This should work.

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.

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;
}

SpringBoot #Value annotation use

I have been working on a scenario wherein I want to decrypt an entry in the application.yml .The value I want to encrypt, keep in yml file and then decrypt while the module comes up
#Value("${app.datasource.password}")
private String password;
I was trying to figure out how #Value works internally so that I could modify it to include this feature. If there is other way possible say by introducing custom annotation and AnnotationProcessor, it would also help.
#Value Annotation just takes a Spring SPEL expression and evaluates it to set the result value for the annotated field.
For your use case you can write a Decrypter object and write a method to decrypt your data and use it as below.
#Value("#{passwordDecrypter.decrypt()}")
private String password;
Write a Bean for doing decryption
#Component
public class PasswordDecrypter{
#Value("${app.datasource.password}")
private String password;
public String decrypt(){
// Return decrypted value
}
}

Resources