Stephane
Stephane

Reputation: 245

Escape property reference in Spring property file

I want to escape my Spring propeties file in order to get in my bean property: ${ROOTPATH}/relativePath

I have a simple Spring config file that contains:

<context:property-placeholder location="classpath:myprops.properties" />

<bean id="myBean" class="spring.MyBean">
    <property name="myProperty" value="${myproperty}" />
</bean> 

The myprops.properties contains:

myproperty=\${ROOTPATH}/relativePath

The above setup returns: Could not resolve placeholder 'ROOTPATH'. I tried a lot of possible syntaxes but was not able to find the right one.

Upvotes: 19

Views: 11099

Answers (4)

SatheeshJM
SatheeshJM

Reputation: 3633

Although it works, escaping the placeholder is super-ugly.

I achieved this my overriding PropertySourcesPlaceholderConfigurer.doProcessProperties and using a custom StringValueResolver

 public static class CustomPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer {

    @Override
    protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess, StringValueResolver valueResolver) {
        StringValueResolver customValueResolver = strVal -> {
            if(strVal.startsWith("${something.")) {
                PropertySourcesPropertyResolver customPropertySourcesPropertyResolver = new PropertySourcesPropertyResolver(this.getAppliedPropertySources());
                String resolvedText = customPropertySourcesPropertyResolver.resolvePlaceholders(strVal);

                //remove the below check if you are okay with the property not being present (i.e remove if the property is optional)
                if(resolvedText.equals(strVal)) {
                    throw new RuntimeException("placeholder " + strVal + " not found");
                }
                return resolvedText;
            }
            else {
                //default behaviour
                return valueResolver.resolveStringValue(strVal);
            }
        };
        super.doProcessProperties(beanFactoryToProcess, customValueResolver);
    }
}

plugging it into the app

@Configuration
public class PlaceHolderResolverConfig
{
  @Bean
  public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
     PropertySourcesPlaceholderConfigurer placeHolderConfigurer = new CustomPropertySourcesPlaceholderConfigurer();
     placeHolderConfigurer.setLocation(new ClassPathResource("application.properties"));
    
     return placeHolderConfigurer;
  }
}

In the above example, for all properties starting with something.* nested placeholders wont be resolved.. remove the if(strVal.startsWith("${something.")) check if you want the behaviour for all properties

Upvotes: 0

Christian
Christian

Reputation: 14061

Here is a Spring ticket which asks for escaping support (still unresolved at the time of writing).

The workaround of using

$=$
myproperty=${$}{ROOTPATH}/relativePath

does provide a solution, but looks quite dirty.

Using SPEL expressions like #{'$'} did not work for me with Spring Boot 1.5.7.

Upvotes: 3

Allen Ai
Allen Ai

Reputation: 69

Seems so far, that is no way to escape the ${}, however you can try below configuration to solve the problem

dollar=$

myproperty=${dollar}{myproperty}

Result for myproperty will be ${myproperty} after evaluation.

Upvotes: 6

user2428804
user2428804

Reputation: 697

Instead of ${myproperty} use #{'$'}{myproperty}. Simply replace $ with #{'$'}.

Upvotes: 19

Related Questions