Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to escape SpEL dollar signs in Spring YAML configuration?

In a Spring YAML configuration file, I need to have a parameter like

csv:
  file:
    pattern: /some/path/${app-name}.csv

where the ${app-name} is dynamically replaced in run time by the Java code, and I do not want Spring to replace it at the startup.

To achieve this, I need to escape the $ character so Spring does not interpret it as SpEL.

The following answers do not work in YAML:

  • \$ How to escape EL dollar signs?

  • #{'$'} Escape property reference in Spring property file

  • Could not read properties if it contains dollar symbol (${var})

I tried all the combinations, like

pattern: /some/path/\${app-name}.csv
pattern: "/some/path/\${app-name}.csv"
pattern: /some/path/#{'$'}{app-name}.csv
pattern: "/some/path/#{'$'}{app-name}.csv"

and none of them produces the variable containing the requested string, with the dollar sign but without the escape characters.

Please notice that it is YAML configuration. In YAML files, # is the line comment character, everything from this character on is ignored. And if I use \#, the \ is then passed to the string.

ADDED: There has been an Spring project open issue 9628 open since 25.06.2008:

There is presently no way to inject a ${...} expression that won't be picked up by PropertyPlaceholderConfigurer. Ideally we should be able to inject a string that contains ${...} for later use in its target bean without involvement from PropertyPlaceholderConfigurer.

like image 503
Honza Zidek Avatar asked Dec 21 '17 16:12

Honza Zidek


3 Answers

I had the same problem, i just found dumb clever solution define a property named dollarSign or ds for short.

ds: "$"

then use it like so, ${ds} will be replace by $ at runtime.

csv:
  file:
    pattern: /some/path/${ds}{app-name}.csv

it was kind of funny when it worked.

like image 101
IWonderHowLongANameICanTypeInH Avatar answered Nov 09 '22 10:11

IWonderHowLongANameICanTypeInH


I've encountered a same problem. So you can resolve this by using yaml literal style symbol "|" , or by using literal_strip "|-" like following example.

application.yml

csv:
  file:
    pattern: |-
      /some/path/${app-name}.csv

Actually My problem is config a formula in yml and then dynamic resolve the expression in java. Sharing the solution here.

I choose spring el solution and use spring version 5.0.9.RELEASE.

I define a formular in yml,

score:
  formula: |-
    10 * #x + #y

Then in a spring component bean,

@Value("${score.formula}")
String scoreFormula;

At last by using spring el,

ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

context.setVariable("x", 1);
context.setVariable("y", 1);
Integer score = parser.parseExpression(scoreFormula).getValue(context,Integer.class);

reference

yaml-multi-line

like image 40
Aylwyn Lake Avatar answered Nov 09 '22 08:11

Aylwyn Lake


Spring currently does not offer an escaping mechanism for property placeholders, there is an open issue (opened on 25.06.2008). In the comments, this workaround is mentioned (I am not sure whether it works with YAML):

csv:
  file:
    pattern: /some/path/#{'$'}{app-name}.csv

Note that when used after whitespace or at the beginning of a line, # in YAML starts a comment.

like image 3
flyx Avatar answered Nov 09 '22 08:11

flyx