Is it possible to pass a key as default value in #Value annotation of Spring - 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.

Related

Spring boot #Value SPEL

I want to inject property from .yml file. If property doesn`t exist or null I would like to inject default value
prop.yml
security:
disable:
#Value("${security.disable ? security.disable : false}")
It work correctly but when I add disable: true it don`t read value and inject default value(false)
With #Value you can use ':' for specifying default value
#Value("${security.disable:false}")
private final Boolean propVal;
Or you can use #ConfigurationProperties("security") on a class with default value inside. It needs a bit more work to get done (mostly adding #EnableConfigurationProperties), but it's much cleaner imho.
#ConfigurationProperties("security")
public class SecurityProperties{
#Getter #Setter
private Boolean disable=false;
}

Can you or can't you use a property from a config file when using Spring #Condition?

I have read pretty much everything I can find on StackOverflow and other sites and I don't see a definitive answer anywhere.
I have a class that implements #Condition that I use in a #Configuration file to conditionally load some beans. I am doing something like this:
public class MyCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metdata) {
String property = context.getEnvironment().getProperty("some.prop.from.file");
boolean enable = Boolean.parseBoolean(property);
return enable;
}
}
When debugging I see that getting the property from the environment always returns null, even though the property is injected in other beans using #Value.
So my question can you or can't you attempt to get a property value from a file within a #Condition class? Can you only get System properties? I would think that this is a common use case that I would think Spring could handle.
Had to add the property to application.properties and not the other property files that are loaded during startup.

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;

how to apply user defined properties value to #RequestMapping

I have several #RequestMapping which value will subject to change from "/XXX" to "/V100" on someday. So I need to define it in properties. I've googled and there's way using application.properties but I have to keep "/XXX" value in a user defined properties like a "local.properties". Is it possible to define #RequestMapping value on a user defined properties?
#Controller
#RequestMapping("/XXX")
public class MyController {
...
}
** UPDATE : tried several hours and get it to work.
my.properties
api.version=V100
mvc-context.xml
<context:property-placeholder ignore-unresolvable="true" location="/WEB-INF/config/property/my.properties"/>
controller
#RequestMapping("/${api.version}")
tomcat log
localhost-startStop-1> [2016-04-28 15:01:35.410] [INFO] [RequestMappingHandlerMapping] [534] Mapped "{[/V100/detail],methods=[GET]}"...
In addition to the xml solution provided by #JustinB, here is an annotation-only solution (tested with Spring Boot):
#Controller
#PropertySource(value = "classpath:/user.properties", ignoreResourceNotFound = true)
#RequestMapping("/${api.version:}")
public class MyController {
...
}
The value of api.version is read from If src/main/resources/user.properties if it exists. If the file is missing or api.version is not set, it will default to an empty string.
Beware, if api.version is also defined in application.properties it will take precedence whether or not user.properties exists and api.version is set in it.
More examples of #PropertySource are provided here.

How do #value annotations work in Spring?

I've never worked with Spring before, and I've run into a configuration object that looks somewhat like this
public class Config {
#Value("${app.module.config1}")
private String config1;
#Value("${app.module.config2}")
private String config2
...
public String getConfig1() {
return config1;
}
...
Can anyone explain what is happening here? I'm assuming this is some type of code injection, but I can't find where these values are coming from!
They allow you to direct inject a Value from a properties file (system or declared property) in the variable. Using the util:properties tag you can add something like this in your applicationContext.xml
<util:properties id="message" location="classpath:com/your/program/resources/message.properties" />
Pointing for a properties file named "message.properties" with some content:
application.hello.message = Hello World!
And then, in your java source file, inject a direct value from this properties file using the #Value annotation:
#Value("#{message['application.hello.message']}")
private String helloWorldMessage;
#Value("${app.module.config1}")
This is part of the spring expression language where the spring framework would look for app.module.config1 JVM property from System.getProperties() and injects the value of that property into config1 attribute in that class. Please see this reference for more details in Spring 3.0.x and this reference for the current docs.

Resources