Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Spring 3 expression language interact with property placeholders?

Spring 3 has introduced a new expression language (SpEL) which can be used in bean definitions. The syntax itself is fairly well specified.

What isn't clear is how, if at all, SpEL interacts with the property placeholder syntax that was already present in prior versions. Does SpEL have support for property placeholders, or do I have to combine the syntax of both mechanisms and hope they combine?

Let me give a concrete example. I want to use the property syntax ${x.y.z}, but with the addition of "default value" syntax as provided by the elvis operator to handle cases where ${x.y.z} is undefined.

I've tried the following syntaxes without success:

  • #{x.y.z?:'defaultValue'}
  • #{${x.y.z}?:'defaultValue'}

The first one gives me

Field or property 'x' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext'

which suggests that SpEL doesn't recognise this as a property placeholder.

The second syntax throws an exception saying that the placeholder is not recognised, so the placeholder resolver is being invoked, but is failing as expected, since the property is not defined.

The docs make no mention of this interaction, so either such a thing is not possible, or it's undocumented.

Anyone managed to do this?


OK, I've come up with a small, self-contained test case for this. This all works as-is:

First, the bean definitions:

<?xml version="1.0" encoding="UTF-8"?>  <beans xmlns="http://www.springframework.org/schema/beans"            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"            xmlns:context="http://www.springframework.org/schema/context"            xmlns:util="http://www.springframework.org/schema/util"            xsi:schemaLocation="                 http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd                 http://www.springframework.org/schema/util    http://www.springframework.org/schema/util/spring-util.xsd            ">       <context:property-placeholder properties-ref="myProps"/>      <util:properties id="myProps">         <prop key="x.y.z">Value A</prop>     </util:properties>      <bean id="testBean" class="test.Bean">             <!-- here is where the magic is required -->         <property name="value" value="${x.y.z}"/>               <!-- I want something like this         <property name="value" value="${a.b.c}?:'Value B'"/>              -->      </bean>      </beans> 

Then, the trivial bean class:

package test;

public class Bean {      String value;      public void setValue(String value) {         this.value = value;     } } 

And lastly, the test case:

package test;  import static org.hamcrest.Matchers.*; import static org.junit.Assert.*;  import javax.annotation.Resource;  import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class PlaceholderTest {      private @Resource Bean testBean;      @Test     public void valueCheck() {         assertThat(testBean.value, is("Value A"));     } } 

The challenge - to come up with a SpEL expression in the beans file which allows me to specify a default value in cases where ${x.y.z} cannot be resolved, and this default must be specified as part of the expression, not externalized in another property set.

like image 344
skaffman Avatar asked Jan 11 '10 11:01

skaffman


People also ask

How does Spring expression language work?

The Spring Expression Language (SpEL for short) is a powerful expression language that supports querying and manipulating an object graph at runtime. The language syntax is similar to Unified EL but offers additional features, most notably method invocation and basic string templating functionality.

Which annotations uses SpEL expression language to access the property values?

SpEL expressions can be used with XML or annotation based configuration metadata for defining BeanDefinitions. In both cases the syntax to define the expression is of the form #{ <expression string> } .

Which of the following can be used to fetch the value of a SpEL expression @SpEL?

Using ExpressionParser. ExpressionParser is responsible for parsing expression strings. In this example, SpEL parser will simply evaluate the string 'Any String' as an expression.


2 Answers

To access property placeholder from SpEL expression, the following syntax can be used: #{'${x.y.z}'}. Hovewer, it can't solve your problem with elvis operator and default values, because it would throw an exception when ${x.y.z} cannot be resolved.

But you don't need SpEL to declare default values for properties:

<context:property-placeholder location="..." properties-ref="defaultValues"/>  <bean id = "defaultValues" class = "org.springframework.beans.factory.config.PropertiesFactoryBean">     <property name="properties">         <props>             <prop key="x.y.z">ZZZ</prop>         </props>     </property> </bean>  <bean ...>     <property name = "..." value = "${x.y.z}" /> </bean> 
like image 136
axtavt Avatar answered Oct 02 '22 20:10

axtavt


It seems you missed the colon:

#{ ${x.y.z} ?: 'defaultValue' } 
like image 36
Bozho Avatar answered Oct 02 '22 21:10

Bozho