Skip to content

Need a way to escape ${} syntax in property loading [SPR-14375] #18948

Closed as not planned
@spring-projects-issues

Description

@spring-projects-issues

Dan Dowma opened SPR-14375 and commented

Here's the scenario - I'm using Spring's configuration system to load my beans. The actual value that I want to load into my bean is this:

G001.${date:now:yyyyMMdd.HHmmss}

That value will be used in a camel application, and passed into a simple string, which camel will evaluate at runtime. This link shows how I'm trying to use this string value (search for "date")
http://camel.apache.org/simple.html

So I have this class:

@Component
@ConfigurationProperties(prefix="configurationProperties")
public class NameConfigurationProperties {
	private String namePattern;

	public String getNamePattern() { return namePattern; }
	public void setNamePattern(String namePattern) { this.namePattern = namePattern; }
}

The problem is how do I structure a value in a properties file such that I can get the value that I'm looking for.

Obviously this won't work:

configurationProperties.namePattern=G001.${date:now:yyyyMMdd.HHmmss}

^^ evaluates to...:

G001.now:yyyyMMdd.HHmmss

... because the ${} syntax is reserved for variable replacement. In the specific case of the string that I'm trying to load, the date portion evaluates to null (since it is an undefined value), so the now:yyyyMMdd.HHmmss is returned as the default option.

I found a work-around that gives me what I want:

configurationProperties.namePattern=G001.${dollar_sign:$}{date:now:yyyyMMdd.HHmmss}

This works for 2 reasons:

  • The ${dollar_sign:$} evaluates to $ because there is no defined value for dollar_sign
  • No secondary evaluation occurs for the ${} syntax when using the @ConfigurationProperties

Different behavior using @Value

I prefer to use @ConfigurationProperties over @Value because I generally load alot of properties into beans, and it requires less code rather than annotating every property in the bean with @Value

However, @Value works differently than @ConfigurationProperties in a couple of cases.

Consider the scenario when I use @Value.

@Component
public class NameValues {
    @Value("${value.namePattern}")
    private String namePattern;

    public String getNamePattern() { return namePattern; }
    public void setNamePattern(String namePattern) { this.namePattern = namePattern; }
}

Using the work-around from above does not work:

value.namePattern=G001.${dollar_sign:$}{date:now:yyyyMMdd.HHmmss}

Yields:

G001.now:yyyyMMdd.HHmmss

... because @Value performs another round of variable replacement.

However, this input does give the correct desired output:

value.namePattern=G001.${dollar_sign:$}{dollar_sign:$}{date:now:yyyyMMdd.HHmmss}

... because it looks like @Value does not perform a third round of variable replacement.

I can use SpEL syntax to create a work-around that works for @Value, as such:

value.namePattern=G001.#{'$'}{date:now:yyyyMMdd.HHmmss}

Conclusion

I'm a bit surprised that details behind @ConfigurationProperties and @Value work differently. Maybe that is by design, and there is likely more to the story than I understand, but regardless, I feel that I need to know the tricks behind either to make my seemingly straight forward scenario work.

Can you design a simpler way to escape the variable replacement mechanism to address this scenario?


Affects: 4.2.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)status: duplicateA duplicate of another issuetype: enhancementA general enhancement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions