How to get #value property from applicationContext - spring

I am trying to get class fields with #value annotation and then fill it by applicationContext.
I am using spring framework.
myClzz.java:
#Value("#{T(java.time.Duration).parse('${interval:PT12H}')}")
private Duration interval;
myService.java:
Field field = FieldUtils.getFieldsWithAnnotation(myClzz.getClass(), Value.class);
//get "#{T(java.time.Duration).parse('${interval:PT12H}')}" from the field:
String value = field.getDeclaredAnnotations()....
String result = applicationContext.getEnvironment().getProperty(value)
application.properties:
interval=PT12H
But getProperty does not work with that "#{T(java.time.Duration).parse('${interval:PT12H}')}" string.
Is there any way to make it work without parsing?

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.

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

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

#Value to retrieve #Query value

Requirement
I've been asked to retrieve the value of a query annotation from a custom property stored in the application.properties file.
Prievious attempt
I tried to use #Value without success
#Repository
public interface FooRepository
extends JpaRepository<Foo, Long> {
#Value("${db.queries.distance}")
String distanceQuery; // this raises an error
#Query(nativeQuery = true, value =distanceQuery)
...
Eclipse marks "distanceQuery" and states
The blank final field distanceQuery may not have been initialized
And force me to initialize the variable as follows
public static final Double distanceQuery = null;
Unfortunately it's not what I want
Question
Is there a workaround to fix this issue?
Thank you in advance!
Instead of defining in a properties file, you can define query in a constants java file and can get value as below
#Query(nativeQuery = true, value =Constants.DISTANCE_QUERY)

Resources