Skip to content
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

Support escaping placeholder prefix in property placeholders [SPR-4953] #9628

Open
spring-projects-issues opened this issue Jun 25, 2008 · 16 comments
Labels
has: votes-jira in: core status: pending-design-work type: enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Jun 25, 2008

Chris Lee opened SPR-4953 and commented

There is presently no way to inject a placeholder 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.

Perhaps a simple escape mechanism using the conventional backslash, such as "The current value is \\${...}" would suffice.


Affects: 2.5.4, 2.5.5

11 votes, 5 watchers

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 30, 2008

Timo Thomas commented

Apache Jakarta Commons-Lang has a similar technology known as "StrSubstitutor" (org.apache.commons.lang.text.StrSubstitutor). There, the default escape character is "$", but it is configurable (independently from the prefix and suffix).

I'm using StrSubstitutor on expressions in bean properties, and if there is no escaping, the only (ugly) option left for me is to change one of the prefixes.

IMHO not having an escape character nowadays should be considered as a production-critical feature (what if changing the prefix is not an option? The workarounds necessary then are even more ugly) - if not as a bug.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Aug 16, 2009

Eric Haszlakiewicz commented

It seems that you can work around this by defining a property that has a value of '$'. e.g.
dollarsign=$

and in the xml config to get a value of e.g. '$foo', you'd write '${dollarsign}foo'

It's not pretty, but at least it works.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 5, 2010

Jim Utter commented

The workaround does not work when the replacement needs the braces passed through.
For example:

properties:
var=$

wiring:
"${var}{foo}"

or even
var=${

"${var}foo}"

or finally
var=${foo}

"${var}"

still results in an error like:

Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'id' defined in class path resource [applicationContext.xml]: Could not resolve placeholder 'foo'
at org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.processProperties(PropertyPlaceholderConfigurer.java:268)

For me, I'd like to define concatenated strings like "${var1}-${var2}${var3}" etc.. where the variables would be internally replaced by velocity (requiring the braces when concatenated).

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 21, 2011

Joshua Caplan commented

The following blog post details a workaround that is available starting from Spring 3.0.x (or whenever SpEL was introduced):

http://jazzjuice.blogspot.com/2011/06/escaping-property-placeholders-in.html

I still agree that native escaping would be useful, though.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 8, 2012

Aleksandr Dubinsky commented

Indeed, #{'$'}{...} seems to be a valid escape sequence for ${...}.

However, it is too long (5 characters!). It is poorly documented. It exists by sheer accident.

It is really shocking that an escape sequence does not exist. Btw, the alternative of defining a different placeholder sequence is a really, really bad idea. That feature should NOT even be there. Allowing users to arbitrarily re-define the basic syntax of a language leads to confusion.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Apr 2, 2015

Michel Nolard commented

@Aleksandr Dubinsky: I agree to a 100% with you.

Interesting fact: there is a lot advices on the net to use your trick -- often without referencing your post properly, but this does not remove the need for this issue to be solved anyway !

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Dec 22, 2017

Jan Zidek commented

In YAML configuration files, # is the line comment sign, the rest of the line is ignored. If I escape it with backslah, so I use

\#{'$'}

then it is not ignored, but when the parameter is set by @ConfigurationProperties, the Java string simply contains the sequence as was written in YAML.

@spring-projects-issues spring-projects-issues added status: waiting-for-triage type: enhancement in: core has: votes-jira and removed type: enhancement labels Jan 11, 2019
@rstoyanchev rstoyanchev added status: bulk-closed and removed status: waiting-for-triage labels Jan 11, 2019
@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jan 12, 2019

Bulk closing outdated, unresolved issues. Please, reopen if still relevant.

@mar1ged
Copy link

@mar1ged mar1ged commented Jun 14, 2019

I really would welcome a "fix" for this.

In my app I externalized config into application.yml, this configuration contains ${var} entries which I later on fill in using PropertyPlaceholderHelper in my own code.

When I have ${var} in my application.yml the app does not load because the value of var will be filled in later and depends on user input.

I worked around this issue by putting @{var} into the YAML file and replacing @ with $ at runtime. But this is not very elegant because I have to do something like this:

	@Value("${my.app.var}")
	private String var;

	public String getVar() {
		return fixed(var);
	}

	private String fixed(String in) {
		return in.replace('@', '$');
	}

@sbrannen
Copy link
Member

@sbrannen sbrannen commented Jun 14, 2019

Interestingly enough, core support for ignoring nested properties appears to have been in place since Spring Framework 3.2 via the ConfigurablePropertyResolver.setIgnoreUnresolvableNestedPlaceholders(boolean) flag.

However, PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(ConfigurableListableBeanFactory) instantiates a PropertySourcesPropertyResolver (which is a subtype of ConfigurablePropertyResolver) without providing the option to set any flags in the property resolver.

Here's a JUnit Jupiter based test case for experimentation:

package example;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

import static org.assertj.core.api.Assertions.assertThat;

@SpringJUnitConfig
// Using the following SpEL hack allows the test to pass.
// @TestPropertySource(properties = "my.app.var = #{'$'}{var}")
@TestPropertySource(properties = "my.app.var = ${var}")
class IgnoredPlaceholderTests {

	@Value("${my.app.var}")
	String value;

	@Test
	void test() {
		assertThat(value).isEqualTo("${var}");
	}

	@Configuration
	static class Config {

		@Bean
		static PropertySourcesPlaceholderConfigurer pspc() {
			PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
			pspc.setIgnoreUnresolvablePlaceholders(true);
			return pspc;
		}

	}

}

@jhoeller, what do you think about either introducing support for escaping placeholders or providing a mechanism for configuring the PropertySourcesPropertyResolver used by PropertySourcesPlaceholderConfigurer?

@sbrannen sbrannen reopened this Jun 14, 2019
@sbrannen sbrannen added status: pending-design-work and removed status: bulk-closed labels Jun 14, 2019
@libinglong
Copy link

@libinglong libinglong commented Aug 2, 2020

it's amazing the issue lasts for more than ten years.

When I use sharding-jdbc which configuration also need '${xxx}', I faced this problem.

@unrec
Copy link

@unrec unrec commented Jul 14, 2021

Will it be fixed at all?

@honza-zidek
Copy link

@honza-zidek honza-zidek commented Jul 14, 2021

@jhoeller, @rstoyanchev, @sbrannen, @sdeleuze, @bclozel, @poutsma, @snicoll, @izeye - any idea if this may be fixed? :)
It has been opened for over 13 years without much attention, so I am trying to attract your eyes here...

@honza-zidek
Copy link

@honza-zidek honza-zidek commented Nov 9, 2021

Any progress? Any comment? :)

@sdeleuze sdeleuze added this to the Triage Queue milestone Dec 17, 2021
@sbrannen sbrannen self-assigned this Jan 18, 2022
@sbrannen sbrannen added the type: enhancement label Jan 18, 2022
@sbrannen sbrannen removed this from the Triage Queue milestone Jan 18, 2022
@sbrannen sbrannen added this to the 6.0.x milestone Jan 18, 2022
@sbrannen
Copy link
Member

@sbrannen sbrannen commented Jan 18, 2022

The team currently plans to look into escaping support in the 6.0.x timeline.

@sbrannen
Copy link
Member

@sbrannen sbrannen commented Jan 18, 2022

The team currently plans to look into escaping support in the 6.0.x timeline.

In the interim, you may find it useful to ignore unresolvable placeholders when using PropertySourcesPlaceholderConfigurer, and I just pushed a fix for ignoring unresolvable placeholders in @Value annotations in conjunction with #27947.

That fix will be available in 5.3.16.

@sbrannen sbrannen changed the title PropertyPlaceholderConfigurer should support 'escaping' property replacements [SPR-4953] Support escaping placeholder prefix in property placeholders [SPR-4953] Feb 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has: votes-jira in: core status: pending-design-work type: enhancement
Projects
None yet
Development

No branches or pull requests

8 participants