Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spring-projects-issues opened this issue Jun 16, 2016 · 2 comments
Closed
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jun 16, 2016

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

@spring-projects-issues
Copy link
Collaborator Author

Allen AI HUA commented

Hi @Nicoll,

I faced the same issue of using spring and apache camel, it can be resolved by below configuration:

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

@spring-projects-issues spring-projects-issues added type: enhancement A general enhancement in: core Issues in core modules (aop, beans, core, context, expression) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 5.x Backlog milestone Jan 11, 2019
@snicoll
Copy link
Member

snicoll commented Dec 21, 2023

Apologize for the delay. The need here is to be able to escape the placeholder syntax so that the value is evaluated as is. This is what we're investigating as part of #9628.

In practice it would boil down to escape the $ prefix, something like 001.\${date:now:yyyyMMdd.HHmmss} would evaluate to 001.${date:now:yyyyMMdd.HHmmss}. I am closing this issue as a duplicate of the one I referenced.

@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Dec 21, 2023
@snicoll snicoll added the status: duplicate A duplicate of another issue label Dec 21, 2023
@snicoll snicoll removed this from the 6.x Backlog milestone Dec 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants