How to escape SpEL dollar signs in Spring YAML configuration?

12,515

Solution 1

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.

Solution 2

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.

Solution 3

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

Solution 4

Why not try using ${sys:$} which is ugly but effective. I think no one will use $ as the key.

Solution 5

Actually none of the answers worked for me. However, adding a double dollar sign worked for me fine:

csv:
  file:
    pattern: /some/path/$${app-name}.csv
Share:
12,515
Honza Zidek
Author by

Honza Zidek

.

Updated on June 05, 2022

Comments

  • Honza Zidek
    Honza Zidek almost 2 years

    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:

    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.

  • Honza Zidek
    Honza Zidek over 6 years
    As I wrote in the question, # in YAML causes that the rest of the line is ignored. It can be escaped by ` so YAML does not interpret #` as the line comment sign, but then the Java variable simply contains /some/path/\#{'$'}{app-name}.csv.
  • Honza Zidek
    Honza Zidek over 6 years
    And apparently this does not seem to be high priority for Spring: Created: 25/Jun/08, Updated: 02/Apr/15, Days since last comment: 2 years, 38 weeks, 1 day ago :(
  • Honza Zidek
    Honza Zidek over 6 years
    Thanks, I think I will extract the minimum example code after Christmas :) It's too late now...
  • flyx
    flyx over 6 years
    As I noted, # only starts a comment if preceded by whitespace. Which is not the case in this example. Moreover, you can put the scalar in double quotes.
  • Honza Zidek
    Honza Zidek over 6 years
    When I put it into double quotes, the Java variable contains the string exactly as is in the YAML file, i.e. with the escape characters.
  • flyx
    flyx over 6 years
    Um, if double-quoting leads to Spring not processing anything, isn't that the solution?
  • Honza Zidek
    Honza Zidek almost 3 years
    No, because the escape characters are also included in the string.
  • Honza Zidek
    Honza Zidek almost 3 years
    The issue github.com/spring-projects/spring-framework/issues/9628 is still open and not solved...
  • flyx
    flyx almost 3 years
    Java frameworks: bug open for 13 years, nobody cares, still used JavaScript frameworks: some guy dislikes the template syntax, everyone migrates to new framework 2 weeks later
  • lcnicolau
    lcnicolau about 2 years
    Thanks, it was the only thing that worked for me. Yours, gave me this idea in a more simplified way.
  • Sebastian
    Sebastian almost 2 years
    I am getting an "Invalid interpolation format" error when I try this solution.