spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.64k stars 38.14k forks source link

Provide a way to disable nested resolution of property placeholders [SPR-9931] #14564

Closed spring-projects-issues closed 9 years ago

spring-projects-issues commented 12 years ago

Mickaël LEDUQUE opened SPR-9931 and commented

There should be a way to use <context:property-placeholder /> to bind a value without trying to evaluate nested values.

For example, I'd like to bind a value that contains a MessageFormat pattern like this one:

my.property={0}#{1}

(very simple case that shows the problem)

This # is a separator between the first argument {0} and the second one, {1}. Of course, #{1} have no value in my context.

Then, I do :

<context:property-placeholder location="..." />
<bean id="myBean" class="my.class">
    <property name="myProp" value="${my.property}" />
</bean>

I need the property evaluation to not to try to be smart and just replace ${my.property} with it's value.

Instead it blows up, replacing #{1} by its value "".


Affects: 3.1.2

spring-projects-issues commented 12 years ago

Chris Beams commented

If it's #{...}, then it's SpEL expression parsing kicking in here. Phil, could you take a look here at various options for disabling SpEL expression parsing during property placeholder replacement? One option could be allowing the user to customize the "#{" expression prefix in the same way we do with customizing "${" and "}" for placeholder identification. I'm not sure at glance, however, whether the SpelExpressionParser and friends allow for this, though.

spring-projects-issues commented 12 years ago

Mickaël LEDUQUE commented

I don't really expect a solution or a fix so early, of course, but if I could have a workaround of an idea of where the problem really lies, that would greatly help.

spring-projects-issues commented 12 years ago

Phil Webb commented

Hi Mickaël,

Would it be possible for you to submit a pull request containing a simple sample application that replicates the problem. Instructions for this are available on GitHub.

Taking a quick look though the Spring codebase I wonder if you might be able to work around the problem by using a custom StandardBeanExpressionResolver bean. This bean has a setExpressionPrefix property that you could change to something that does not clash. It looks like StandardBeanExpressionResolvers are currently automatically registered (see the AbstractApplicationContext.prepareBeanFactory class). You can probably register your own variant by writing a BeanFactoryPostProcessor bean that calls beanFactory.setBeanExpressionResolver in the postProcessBeanFactory method.

The sample app would certainly help me confirm the above.

Cheers, Phil.

spring-projects-issues commented 11 years ago

Mickaël LEDUQUE commented

I will make a pull request as soon as I'm not behind a stupid corporate gateway. It's mostly ready (nothing really hard here) but there are some constraints outside my power.

spring-projects-issues commented 11 years ago

Chris Beams commented

pull request submitted: https://github.com/SpringSource/spring-framework-issues/pull/39

Thanks, Mickaël.

spring-projects-issues commented 11 years ago

Phil Webb commented

Hi Mickaël,

Thanks for the pull request. I would like to find a better solution but for now you can use the following work-around to change the SpEL prefix to something other than '#{' (in this case '#$#{'). Just register this class as a bean in you ApplicationContext.

public class ExpressionResolverFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        StandardBeanExpressionResolver expressionResolver = new StandardBeanExpressionResolver();
        expressionResolver.setExpressionPrefix("#$#{");
        beanFactory.setBeanExpressionResolver(expressionResolver);
    }
}

Hope it helps.

Cheers, Phil.

spring-projects-issues commented 11 years ago

Mickaël LEDUQUE commented

OK, thanks, that seems to work. I'll use it, unless I discover that I can't globally change the prefix (but I think that'll work for me).