Stephen
Stephen

Reputation: 71

Spring 3: disable SpEL evaluation of a bean property value?

We're in the process of updating our apps from Spring 2.5 to 3.0 and we've hit a problem with the new SpEL evaluation of bean properties.

We've been using an in-house templating syntax in one module which unfortunately uses the same "#{xyz}" markup as SpEL. We have a few beans which take string's containing these expressions as properties but spring assumes they are SpEL expressions and throws a SpelEvaluationException when it tries to instantiate the bean.

e.g.

<bean id="templatingEngine" class="com.foo.TemplatingEngine">
   <property name="barTemplate" value="user=#{uid}&country=#{cty}"/>
</bean>

Is it possible to disable SpEL evaluation, ideally per-bean, but alternatively for the whole application context?

Alternatively is there a way to escape the values?

Thanks, Stephen

Upvotes: 5

Views: 3862

Answers (3)

Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 298838

Well what you could do is re-define the expression language delimiters.

I would say the way to do this is through a special bean that implements BeanFactoryPostProcessor (thanks to inspiration by Jim Huang):

public class ExpressionTokensRedefiner implements BeanFactoryPostProcessor{

    private BeanExpressionResolver beanExpressionResolver;

    public void setBeanExpressionResolver(
        final BeanExpressionResolver beanExpressionResolver){
        this.beanExpressionResolver = beanExpressionResolver;
    }

    @Override
    public void postProcessBeanFactory(
        final ConfigurableListableBeanFactory beanFactory)
        throws BeansException{
        beanFactory.setBeanExpressionResolver(createResolver());
    }

    private String expressionPrefix = "${";
    private String expressionSuffix = "}";

    public void setExpressionPrefix(final String expressionPrefix){
        this.expressionPrefix = expressionPrefix;
    }
    public void setExpressionSuffix(final String expressionSuffix){
        this.expressionSuffix = expressionSuffix;
    }

    private BeanExpressionResolver createResolver(){
        if(beanExpressionResolver == null){
            final StandardBeanExpressionResolver resolver =
                new StandardBeanExpressionResolver();
            resolver.setExpressionPrefix(expressionPrefix);
            resolver.setExpressionSuffix(expressionSuffix);
            return resolver;
        } else{
            return beanExpressionResolver;
        }
    }

}

Define it as a bean like this:

<bean class="foo.bar.ExpressionTokensRedefiner">
    <property name="expressionPrefix" value="[[" />
    <property name="expressionSuffix" value="]]" />
</bean>

or like this:

<!-- this will use the default tokens ${ and } -->
<bean class="foo.bar.ExpressionTokensRedefiner" />

or use a custom resolver:

<bean class="foo.bar.ExpressionTokensRedefiner">
    <property name="beanExpressionResolver">
        <bean class="foo.bar.CustomExpressionResolver" />
    </property>
</bean>

Now you can leave your definitions untouched and if you want to use SpEL, use the new delimiters.

EDIT: now I did test it and it actually works.

<bean class="foo.bar.ExpressionTokensRedefiner">
    <property name="expressionPrefix" value="[[" />
    <property name="expressionSuffix" value="]]" />
</bean>


<bean class="foo.bar.FooFritz">
    <property name="fizz" value="[[ systemProperties['user.home'] ]]"></property>
    <property name="fozz" value="[[ systemProperties['java.io.tmpdir'] ]]"></property>
            <!-- this is what it would normally choke on -->
    <property name="fazz" value="#{ boom() }"></property>
</bean>

Test code:

final ConfigurableApplicationContext context =
    new ClassPathXmlApplicationContext("classpath:foo/bar/ctx.xml");
context.refresh();
final FooFritz fooFritz = context.getBean(FooFritz.class);
System.out.println(fooFritz.getFizz());
System.out.println(fooFritz.getFozz());
System.out.println(fooFritz.getFazz());

Output:

/home/seanizer
/tmp
#{ boom() }

Upvotes: 3

Chin Huang
Chin Huang

Reputation: 13800

Completely disable SpEL evaluation by calling the bean factory setBeanExpressionResolver method passing in null. You can define a BeanFactoryPostProcessor to do this.

public class DisableSpel implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(
        ConfigurableListableBeanFactory beanFactory)
        throws BeansException
    {
        beanFactory.setBeanExpressionResolver(null);
    }
}

Then define this bean in the application context.

<bean class="com.example.spel.DisableSpel"/>

Upvotes: 5

Anton K.
Anton K.

Reputation: 963

I am not a dab, but this mighbe of help.

https://issues.apache.org/jira/browse/CAMEL-2599

Upvotes: 0

Related Questions