Spring boot how to append multiple properties to single value? - spring-boot

I have multiple properties in my application.properties file
prop.a=A
prop.b=B
prop.c=C
// and more
Now i have to add the property A to the rest of them. I am doing this like following
#Value("${prop.a}")
private String a;
#Value("${prop.b}")
private String b;
b = new StringBuffer(b).append(a).toString();
I have to individually append each string. Can i do this in the annotation? like #Value("${prop.b}" + "${prop.a}") ?

If you want to do this programmatically, you have to do this:
#Value( "${prop.a}${prop.b}" )
private String b;
You can, however, achieve this in application.properties itself this way:
prop.a=A
prop.b=${prop.a}B
prop.c=${prop.a}C
(Please note that wherever your example says prob.*,I have changed to prop.*.)

Related

Is there a way to configure 2 property system in same #Value ins spring boot?

I trying to use 2 different property files with the same parameters which every parameter is describing the same property for example:
NewsPaperConsumer.properties, MarketConsumer.properties when every file have the same parameters.
My aim is to use the separated way to make the configuration files more readable but at the progromatic side union them to one hash map for example:
NewPaperConsumer and MarketConsumer have the parameter serverAddress so I'll get it by:
#Value("${serverAddress}")
private HashMap<String,String> serverAdresses;
how I change the way the system property save the parameter (instead of assign the value to string that It will assign it to hash map - {"key" : "value }

Sping-Boot Config: How to keep whitespace in yaml key being used to populate Map<String, String>

Let's say we have a configuration properties class:
#ConfigurationProperties(prefix = "whitespace.test")
public class WhitespaceTestConfig {
private Map<String, String> configs;
public Map<String, String> getConfigs() {
return configs;
}
public void setConfigs(Map<String, String> configs) {
this.configs = configs;
}
}
and we try to configure it with a key with space included in it:
whitespace.test.configs:
Key With Whitespace: "I am a value with whitespace in it"
Seems as through spring can parse this yaml fine, and it is apparently valid yaml. However, spring (SnakeYaml?) removes the spaces in the Key string:
KeyWithWhitespace -> I am a value with whitespace in it
An easy solution is to designate a special character for space and replace it within the application, but I was wondering if spring already handled this in some fashion? Perhaps there is a way to escape a space in the config in such a way that spring (SnakeYaml?) knows the we want to keep it, or perhaps there is a way to configure this?
For the sake of completeness I've tried using single and double quotations as well as \s \b.
Update:
After some additional research I found an example from SnakeYaml repository that seems to indicate that what I'm looking for should be possible: https://bitbucket.org/asomov/snakeyaml/wiki/Documentation#markdown-header-block-mappings
Specifically this example:
# YAML
base armor class: 0
base damage: [4,4]
plus to-hit: 12
plus to-dam: 16
plus to-ac: 0
# Java
{'plus to-hit': 12, 'base damage': [4, 4], 'base armor class': 0, 'plus to-ac': 0, 'plus to-dam': 16}
In the example the spaces persist in the keys. Unfortunately, I'm at a loss with regard to figuring out where the whitespace is actually getting removed.
For map keys with special characters you need to surround the key with '[]' for the key to be used as specified.
So, in your case it will be
whitespace.test.configs:
'[Key With Whitespace]': "I am a value with whitespace in it"
The new binder is much stricter about property names which means you need to surround them in square brackets. Try the following:
shiro:
testMap:
"[/test1]": test1
"[/test2]": test2

Spring boot request mapping

I have following request parameters.
a
b
c
d
e
f
Request can contain all the parameters or some of them. I am currently using regex /** to resolve this.
Is there any way to explicitly mention the request mapping instead ** and say it is optional. And any order also should match.
/a/1/b/f2
and
/b/f2/a/1
Both should match that mapping.
There is no way to achieve this via #PathVariable's. If you want the flexibility of random order & number of path variables. You can just do the following;
#GetMapping("/myEndpoint/**")
public void theEndpoint(HttpServletRequest request) {
String requestURI = request.getRequestURI();
Stream.of(requestURI.split("myEndpoint/")[1].split("/")).forEach(System.out::println);
}
You can put a .filter(StringUtils::isNotBlank) in case /myEndpoint/a///b/c
Will give you
a
1
b
f2
d
x
when you call /myEndpoint/a/1/b/f2/d/x
b
f2
1
when you call /myEndpoint/b/f2/1
Also, be aware that you'd need some anchor base in your endpoint, e.g. /myEndpoint. Otherwise all your other endpoints will be conflicted with this endpoint.
ps. Better to use request params for such inputs tbh, not sure your requirement here, but just FYI. It is not the best to have such a hacky structure really...
You can make a RequestParam optional by adding the required flag false.
#RequestParam(value = "a", required=false)
For PathVariables i would try to use the Optional type but i have never done this before.
#PathVariable Optional<String> a for /path/{a}

How to load value with dynamic key place holder in spring batch?

Spring Batch: How to get value from property file if key is generated dynamically from input parameter
propertyfile content:
my.table.book.bic.code=11111
my.table.news.bic.code=22222
Spring batch configuration
< property name="bicCodeValue" value="#{jobParameters['inputTable'] + '.bic.code'}" />
Where inputTable is input parameter for batch
inputTable = my.table.book
inputTable = my.table.news
I am not getting value from property file instead of value from property file I am getting only key in code "my.table.book.bic.code".
I need to update only in xml file like
< property name="bicCodeValue" value="#{jobParameters['inputTable'] + '.bic.code'}" / >
But this is not working.
You could inject an instance of
#Autowired
private Environment env;
and then do something like:
env.getProperty("my.table."+inputTable+".book.bic.code")
According to your properties, the SpEL expression jobParameters['inputTable'] should return a String value, so you can try to use the concat method in your expression:
<property name="bicCodeValue" value="#{jobParameters['inputTable'].concat('.bic.code')}" />
For more details about SpEL, please see here: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions

Spring setting #value from another variable

Is it possible to set #Value from another variable
For eg.
System properties : firstvariable=hello ,secondvariable=world
#Value(#{systemProperties['firstvariable'])
String var1;
Now I would like to have var2 to be concatenated with var1 and dependant on it , something like
#Value( var1 + #{systemProperties['secondvariable']
String var2;
public void message(){ System.out.printlng("Message : " + var2 );
No, you can't do that or you will get The value for annotation attribute Value.value must be a constant expression.
However, you can achieve same thing with following
In your property file
firstvariable=hello
secondvariable=${firstvariable}world
and then read value as
#Value("${secondvariable}")
private String var2;
Output of System.out.println("Message : " + var2 ) would be Message : helloworld.
As the question use the predefined systemProperties variable with EL expiration.
My guess is that the meaning was to use java system properties (e.g. -D options).
As #value accept el expressions you may use
#Value("#{systemProperties['firstvariable']}#systemProperties['secondvariable']}")
private String message;
You said
Now I would like to have var2 to be concatenated with var1 and
dependent on it
Note that in this case changing var2 will not have effect on message as the
message is set when the bean is initialized
In my case (using Kotlin and Springboot together), I have to escape "$" character as well. Otherwise Intellij IDEA gives compile time error:
Implementation gives error:
#Value("${SCRIPT_PATH}")
private val SCRIPT_PATH: String = ""
Error: An annotation argument must be a compile-time constant
Solution:
#Value("\${SCRIPT_PATH}")
private val SCRIPT_PATH: String = ""

Resources