#ConfigurationProperties returns property placeholder instead of null - spring-boot

I have the following #ConfigurationProperties property holder:
#ConfigurationProperties(prefix = "custom.service")
public class CustomServicePropertyHolder {
private String name;
}
and my application.properties looks like this:
custom.service.name=${remote.service.name}
custom.service.....=...
custom.service.....=...
remove.service.name is an environment variable received in the runtime.
However, when remote.service.name was not provided, the value of the EtlConfigurationHolder.name is a string "${remote.service.name}".
How to make the property to return null instead of this placeholder string ?

I also encountered such a problem ... And it has been present for a long time
Unresolved Placeholder Validation for Spring Boot Configuration Properties
https://github.com/spring-projects/spring-boot/issues/4302
https://github.com/spring-projects/spring-boot/issues/1768
I found only one place where at least some solution is attached
https://davidagood.com/spring-boot-fail-on-missing-env-vars/

Related

PropertySourcesPlaceholderConfigurer can't resolve property

I am reading document here
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-value-annotations
#Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(#Value("${catalog.name}") String catalog) {
this.catalog = catalog;
}
}
#Configuration
#PropertySource("classpath:application.properties")
public class AppConfig { }
And the following application.properties file:
catalog.name=MovieCatalog
A default lenient embedded value resolver is provided by Spring. It
will try to resolve the property value and if it cannot be resolved,
the property name (for example ${catalog.name}) will be injected as
the value.
What does "it cannot be resolved" mean? If I don't have this property in the application.properties, it gives me error:
Could not resolve placeholder 'catalog.name' in value "${catalog.name}"
Updated:
I figured it out. In Spring core, if property not found, it uses ${catalog.name}
But in SpringBoot, if property not found, it gives error.
Resolve means find. Sometime the resolution (finding) can be complicated.
An SpringBoot each property in application properties can also be injected with an environment variable. So catalog.name could be left out of apllication.properties and used as env var CATALOG_NAME.
AFAIK a value can also come in on a command line.

Is it possible to pass a key as default value in #Value annotation of Spring

I have a situation where we are reading one property from properties file and now we have been asked to point to another endpoint and for some time we have to manage both these endpoints unless this new endpoint is tested and validated throughly.
I wanted to handle this situation by adding this newer property in properties file and in the actual class were we are reading this property with #Value Annotation the old one can be passed as default with its key as value something like
#Value("${backend.endpoint:${older.endpoint}}"). is it possible ?
Yes you can do it, I have tested it, my sample code
code:
#Value("#{ ${spring.myapp.usenewval} ? '${spring.myapp.newval}' : '${spring.myapp.oldval}}'}")
private String message;
Properties
spring:
myapp:
usenewval: false
newval: hello
oldval: world.....
You can always set spring.myapp.usenewval from outside like
java -jar -Dspring.myapp.usenewval=true myapp.jar
You can use it like this. (I've personally never done it, so forgive me if I'm wrong)
#Configuration
public class PropertyConfiguration {
#Value("{'${backend.endpoint:${older.endpoint:}}'}")
private String myValue;
}
This #Value annotation uses backend.endpoint, if it is provided and defaults to older.endpoint, if backend.endpoint is not provided.
If neither is provided, the property must be set null.
There are other ways to handle this as well. Probably, use #Value for both the property and handle in code.
Here is quick fix for you. Kindly refer it.
You can set default value to #Value annotation of spring as following.
#Controller
#RequestMapping(value = "/your path")
public class MyController {
#Value("${key:true}")
private boolean booleanWithDefaultValue;
}
Here, I take Boolean variable and set default value as "true".
Hope this solution works.

Spring Custom Configuration not populating properties with underscore

I am trying to populate Custom class with properties. following is my Custom Properties class:
#Configuration
#ConfigurationProperties(prefix = "foo.bar")
public class CustomProperties{
private String PROPERTY_ONE;
private String propertyTwo;
//setters
//getters
}
and my properties in application.properties are:
foo.bar.PROPERTY_ONE=some text
foo.bar.PROPERTY_TWO=some other text
When I am trying to use value from CustomProperties this is what I gets:
customProperties.getPROPERTY_ONE() = null
customProperties.getPopertyTwo() = some other text
So I observed that if I have variable name with underscore(_) in it not populating the property value.
is there any way to get the value with variable having underscore?
Yes, it is 100% possible to get your configuration values.
It's all about the casing! Inside of CustomProperties simply name your first property propertyOne ... and refactor your getters/setters appropriately ... and you'll be good to go!
Spring's got the camel casing going on when translating the configuration fields to your Configuration classes/properties. So instead of matching the casing of your properties, follow the camel casing equivalent of the property name found in your configuration file.
Example: PROPERTY_ONE translates to propertyOne

Using #Value annotation with Spring and SPeL

I am trying to find a way to do the following in my spring boot 1.5 application.
I have a variable who's value is dynamic meaning it comes in from an external system.
String name = "abc"; //gets set externally
I want to try and use the name's value to lookup my property file and see if there is a matching property defined. something like..
#Value("#{myClassName.name.concat('something')}")
String propertyValue;
Now my application.property file has the following property set
assume name has the value "abc"
property file contents:
abc.something:abcValue
Now, when i try to access the value of the variable propertyValue it gets set to the value abc.something and not abcValue.
I probably think I cannot use #Value with #{} to get to that, I was wondering if there was a way to to use #{} inside ${} so that I goes and fetches the property value after calculating the name of the property using #{}.
Let me know if you need more details please.
A bean life-cycle requires properties to be resolved at compile time. So, #Value requires constant parameter.
You can use Environment bean to access your properties programmatically.
import org.springframework.core.env.Environment;
#Service
public class Serivce {
#Autowired
private Environment environment;
public String getProperty(final String keyPart) {
String key = "build.your." + keyPart;
return environment.getProperty(key)
}
}
By the way you can use #('${spring.some.property}') in SpEL to access placeholder.
// This is valid access to property
#Value("#('${spring.some.property}')")
private String property;

Can I use a placeholder to dynamically add text to a string imported from a property file with Spring's #Value annotation

Does anyone know if I can use placeholders with Spring's #Value annotion?
For example:
#Value("${a.url.from.propertiesFile}")
private void setUrl(String myUrlFromProperties)
{
this.url = myUrlFromProperties;
}
where my properties file would have:
a.url.from.propertiesFile=/firstPartOfUrl{dynamicBitToAddTo}restOfUrl
Yes you can do that.
In this case if you have passed a null value in the parameter then the default value will be taken as defined with the annotation #Value.
But if you are passing a not null value in the parameter then it will not take the default value.
Hope this helps you.

Resources