Spring Expression Language (SpEL) Primer

Spring Expression Language, abbreviated SpEL, is a powerful expression language, in the newly released Spring 3, that supports a plethora of ways of interacting with object graphs at runtime. It is intended to be a fully featured expression language for reuse across all products in the Spring Portfolio. This article explores all the various features of SpEL by example.

There will be the smallest possible prerequisite object model to minimise the learning curve prior to getting into the examples. Each example will be fully self contained with the exception of those that make use of the object model defined at the outset. The examples themselves have been constructed as unit tests to be able to easily visualise the outcome of executing the code and also so that they can be taken away and easily run as standalone tests. Finally, as always, as has been proven to be popular, the entire code will be made available for download (as an eclipse maven project).

The article and the examples grew while learning SpEL from the official documentation which is excellent. However it is hoped that this offers some value in terms of complete self contained and varied examples for reference over the official content. It also features as a modest test suite for the API which in itself has highlighted one or two issues relating to one possible bug (collection selection of last entry matching a predicate) and certain API questions all of which have already been raised on the forums and are awaiting answers.


The model simply consists of the following User object.

package spring.examples.spel.model;

public class User {
    private String name;

    public User(String user) {
        this.name = user;

    public String getName() {
        return name;

    public void setName(String user) {
        this.name = user;

The User only has one property called name which obeys the javabean naming convention. The examples which don’t use the model use the JDK classes to minimise the learning curve.



The spel parser is thread safe and reusable and as such can be created once and cached as follows.

package spring.examples.spel;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

public class TestParser {

    public final static ExpressionParser PARSER = new SpelExpressionParser();


The parser can then used to parse any given expression at runtime. An expression can also be accompanied by a ParserContext which determines the prefix and suffix of an expression and an EvaluationContext which can hold state in terms of root objects, variables and functions that are relevant to the expressions to be subsequently parsed. In the following examples the parser instance will be referred as the static variable PARSER.


    public void testStringLiteral() {
        Expression exp = PARSER.parseExpression("'foo'");
        String value = exp.getValue(String.class);
        assertEquals("foo", value);

The above example shows the equivalent of a hello world example. The PARSER instance has been constructed as previously mentioned. The parser then parses an expression and from the expression instance we can extract the end result. Here in the expression is provided a string literal enclosed in single quotes. Note the generic getValue() methods that allow you to retrieve strongly typed objects without the need to cast.


Primitive literals are supported as expected. Watch out for primitive literal junit oddities though.

    public void testPrimitives() {
        assertTrue(0 == PARSER.parseExpression("0").getValue(byte.class));
        assertTrue(0 == PARSER.parseExpression("0").getValue(short.class));
        assertTrue(0 == PARSER.parseExpression("0").getValue(int.class));
        assertTrue(0L == PARSER.parseExpression("0L").getValue(long.class));
        assertTrue(0.1F == PARSER.parseExpression("0.1F").getValue(float.class));
        assertTrue(0.1D == PARSER.parseExpression("0.1D").getValue(double.class));
        assertTrue('c' == PARSER.parseExpression("'c'").getValue(char.class));

State and behaviour registration

The evaluation context can be provided with state or behaviour to take into account when the parser parses the expression.

Variable registration

Here a variable is registered with the evaluation context and is referred to in the expression with a hash prefix.

    public void testStateRegistration() {
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariable("foo", "bar");
        String bar = PARSER.parseExpression("#foo").getValue(context, String.class);
        assertEquals("bar", bar);

Note that this is not the only way to supply state to the context. One can register a root variable either as a constructor argument to the context or by calling the public void setRootObject(Object rootObject) method. It is also possible to refer to intermediate local variables during iteration when performing a ‘Collection selection’ which is illustrated later.

Function registration

Similarly here a function is registered with the context and referred to in the same way.

    public void testBehaviourRegistration() throws SecurityException, NoSuchMethodException {
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariable("foo", "bar");
        context.registerFunction("quote", StringUtils.class.getDeclaredMethod("quote", String.class));
        String bar = PARSER.parseExpression("#quote(#foo)").getValue(context, String.class);
        assertEquals("'bar'", bar);

Admittedly requiring the use of reflection here as an argument to the public API is less than ideal and questionable. An alternative would be to require the client code to implement an interface (which would of course couple the client code to SpEL). In due time it would be interesting to register closures/lambda expressions in jdk7.

Function registration 2

Here follows a slightly different application of function registration where one of the classes of the JDK is registered with SpEL.

    public void testRegisterFunction2() throws SecurityException, NoSuchMethodException {
        List<Integer> list = new ArrayList<Integer>(Arrays.asList(0, 1));
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.registerFunction("max", Collections.class.getDeclaredMethod("max", new Class[] { Collection.class }));
        Integer max = PARSER.parseExpression("#max(#root)").getValue(context, Integer.class);
        assertSame(1, max);

The use of a root object is also demonstrated above and when a root object is used there is no need to pass any variable within the getValue() call although one can do so if the root object is changing over time.

Behaviour invocation

Behaviour invocation allows interaction with an object graph in virtually every way you’d expect from the java language itself. Constructors, instance methods, static methods, javabean properties and nested properties are all supported. Each of the examples below are expected to be self explanatory and are therefore not necessarily elaborated upon.

Constructor invocation

    public void testConstructorInvocation() {
        Expression exp = PARSER.parseExpression("new String('foo')");
        String value = exp.getValue(String.class);
        assertEquals("foo", value);

Method invocation

    public void testMethodInvocation() {
        Expression exp = PARSER.parseExpression("'foo'.concat('!')");
        String value = exp.getValue(String.class);
        assertEquals("foo!", value);

Static invocation

Static invocations are slightly different. The T qualifier is necessary to tell the parser that a static Class instance is required there. Here T(Math) is resolved to Math.class and the static method is invoked on it.

    public void testStaticInvocation() {
        Expression exp = PARSER.parseExpression("T(Math).random() * 100.0");
        double value = exp.getValue(double.class);

Note that since the Math class is in the java.lang package there is no need to fully qualify it’s name. SpEL just like Java has an understanding of this default package.

Javabean property

Java bean properties are automatically supported in a scripting like style which is nice.

    public void testJavaBeanProperty() {
        Expression exp = PARSER.parseExpression("'foo'.bytes");
        byte[] bytes = exp.getValue(byte[].class);
        assertTrue(Arrays.equals("foo".getBytes(), bytes));

Nested property

Nested property support is analogous to method changing in Java and works as you’d expected. The example below accesses initially one java bean property but then chains to a public variable.

    public void testNestedProperties() {
        Expression exp = PARSER.parseExpression("'foo'.bytes.length");
        int length = exp.getValue(int.class);
        assertSame("foo".getBytes().length, length);

Unchanging root object

When using the parser with an object one has the option of either supplying that object as the root object to the context or to register it as variable or to supply it on every invocation of the parseExpression method. Here the first of those is demonstrated.

    public void testQueryUnchangingRootObjectProperty() {
        Expression exp = PARSER.parseExpression("name");
        EvaluationContext context = new StandardEvaluationContext(new User("foo"));
        String name = exp.getValue(context, String.class);
        assertEquals("foo", name);

In the above usage the root object is not changing with every invocation of the parser so it can be supplied once and parsing of expressions can be performed multiple times.

Changing root object

In the opposite scenario if the root object is expected to be changing between expression parse invocations then it can be supplied to the parser when parsing the expression itself. This is the concurrent option.

    public void testQueryChangingRootObjectProperty() {
        Expression exp = PARSER.parseExpression("name");
        String name = exp.getValue(new User("foo"), String.class);
        assertEquals("foo", name);

Changing root object with cached context

The need for caching the evaluation context arises from the fact that the construction of the context is actually quite expensive. As a result here the context is created only once with a root object and is reused for parsing various expressions.

    public void testQueryChangingRootObjectPropertyWithCachedContext() {
        Expression exp = PARSER.parseExpression("name");
        EvaluationContext context = new StandardEvaluationContext(new User("foo"));
        assertEquals("foo", exp.getValue(context, String.class));
        String bar = exp.getValue(context, new User("bar"), String.class);
        String baz = exp.getValue(context, new User("baz"), String.class);
        assertEquals("bar", bar);
        assertEquals("baz", baz);

Note however that although in the first value extraction we make use of the root object in the context with name ‘foo’ – in the latter two value extractions we override the root object with new ones named ‘bar’ and ‘baz’ respectively. Note also that when we override the root objects we still reuse the evaluation context since it is already constructed negating the need for SpEL to create one itself.


There are a number of ways of mutating properties illustrated below.

Mutate typed property

Here a list element is flipped from true to false.

    public void mutateTypedProperty() {
        List<Boolean> list = new ArrayList<Boolean>(Arrays.asList(true));
        EvaluationContext context = new StandardEvaluationContext(list);
        PARSER.parseExpression("#root[0]").setValue(context, "false");

Note that false is recognised as a boolean and converted as such by SpEL and also that array/list elements can be accessed using indices just like in the language itself.

Assignment on root object

The parser provides mutative methods that can be used to set specific properties of a root object to designated values.

    public void testAssignmentOnRootObjectDirectly() {
        Calendar calendar = Calendar.getInstance();
        PARSER.parseExpression("timeInMillis").setValue(calendar, 0);
        assertTrue(0 == calendar.getTimeInMillis());

Above a calendar property is set directly without using an evaluation context.

Assignment on evaluation context

Alternatively an evaluation context can be constructed with the calendar as the root object and then the property mutated.

    public void testAssignmentOnContext() {
        Calendar calendar = Calendar.getInstance();
        EvaluationContext context = new StandardEvaluationContext(calendar);
        PARSER.parseExpression("timeInMillis").setValue(context, 0);
        assertTrue(0 == calendar.getTimeInMillis());

Assignment within expression

Mutations can also be done via accessor methods within the expression itself.

    public void testAssignmentInExpression() {
        Calendar calendar = Calendar.getInstance();
        long value = PARSER.parseExpression("timeInMillis = 0").getValue(calendar, long.class);
        assertTrue(0 == value);

The assignment operator above works exactly as in the language itself.


SpEL supports the basic relational, logical and mathematical operators that one would expect. However in addition it also supports conditional operators in the form of ternary, elvis and safe navigation operators discussed below.

Relational operators

    public void testRelationalOperators() {

Logical operators

    public void testLogicalOperators() {
        assertTrue(PARSER.parseExpression("true and true").getValue(boolean.class));
        assertTrue(PARSER.parseExpression("true or true").getValue(boolean.class));
        assertTrue(PARSER.parseExpression("not false").getValue(boolean.class));
        assertTrue(PARSER.parseExpression("true and not false").getValue(boolean.class));

Mathematical operators

    public void testMathematicalOperators() {
        assertSame(2, PARSER.parseExpression("1+1").getValue(int.class));
        assertSame(0, PARSER.parseExpression("1-1").getValue(int.class));
        assertSame(1, PARSER.parseExpression("1/1").getValue(int.class));
        assertSame(1, PARSER.parseExpression("1*1").getValue(int.class));
        assertSame(1, PARSER.parseExpression("1^1").getValue(int.class));
        assertTrue(1D == PARSER.parseExpression("1e0").getValue(double.class));
        assertEquals("foobar", PARSER.parseExpression("'foo'+'bar'").getValue(String.class));

Ternary, Elvis and Safe Navigation operators

The ternary operator will be familiar to all from Java. However the elvis and safe navigation operator are powerful yet succinct additions to the SpEL language as demonstrated below.

    public void testTernaryElvisAndSafeNavigationOperators() {
        assertEquals("foo", PARSER.parseExpression("true ? 'foo' : 'bar'").getValue(String.class));
        assertEquals("null", PARSER.parseExpression("null?:'null'").getValue(String.class));
        assertEquals(null, PARSER.parseExpression("null?.foo").getValue(String.class));

The Elvis operator is a more succinct form of the ternary operator requiring only one half of the statement to be specified. The safe navigation operator performs a safe null dereference by returning null rather than throwing a NullPointerException.


A few utility applications of SpEL lie below.

System properties

System property access is reported to be supported in SpEL. In the tests written it was noted that it’s not supported in programmatic usage of SpEL. One can only assume that it is only supported when using SpEL through the application context. Below is a weak emulation of using system properties in conjunction with SpEL although the author accedes this would be of no practical use whatsoever.

    public void testGetSystemProperty() {
        System.setProperty("foo", "bar");
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("systemProperties", System.getProperties());
        Expression exp = PARSER.parseExpression("#systemProperties['foo']");
        String value = exp.getValue(context, String.class);
        assertEquals("bar", value);

Date parsing

SpEL has an understanding of dates and is able to add dates together as well using the ‘+’ operator.

    public void testDateParsing() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(2010, 11, 25, 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        assertEquals(calendar.getTime(), PARSER.parseExpression("'2010/12/25'").getValue(Date.class));


The instanceof ‘keyword’ is supported exactly as in Java but the right hand side argument must be provided as an instance of Class by using the T() qualification.

    public void testInstanceOfCheck() {
        assertTrue(PARSER.parseExpression("0 instanceof T(Integer)").getValue(boolean.class));


The ‘matches’ keyword supports regular expression matching but in a far more terse way than Java itself which is nice.

    public void testRegularExpressionMatch() {
        assertTrue(PARSER.parseExpression("-0.1e-4 matches '^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$'").getValue(

Expression templating

SpEL supports String templating. However to do this, rather oddly in the author’s opinion, the client code must supply a ParserContext implementation which contains the expression prefix and suffix. It’s odd because there isn’t such an implementation provided by SpEL already and also because a more succinct way of specifying prefix and suffix isn’t available.

    public void testExpressionTemplating() {
        String fooBarBaz = PARSER.parseExpression("foo ${'foobar'.substring(3)} ${'barbaz'.substring(3)}",
                new ParserContext() {
                    public String getExpressionPrefix() {
                        return "${";

                    public String getExpressionSuffix() {
                        return "}";

                    public boolean isTemplate() {
                        return true;
        assertEquals("foo bar baz", fooBarBaz);

Predicate based extractions

Predicate based extractions are by far the most interesting feature area in SpEL. With merely a few characters one is able to do predicate based selection and projection similar to that in functional programming languages. Magic variables exist that allow the expression access to intermediate stack variables just as you would have in a for loop.

Collection selection

List selection

The example below selects all integer elements in the given list that are even.

    public void testListSelection() {
        List<Integer> list = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("list", list);
        List<?> evenNumberList = PARSER.parseExpression("#list.?[#this%2==0]").getValue(context, List.class);
        assertEquals(Arrays.asList(0, 2, 4, 6, 8), evenNumberList);

Note that the variable named #this refers to the current list element accessible within that particular iteration over the list.

Simple map selection

Similarly map values can be accessed in the same way that you would access an array or list element in SpEL – that is by providing a key within square brackets.

    public void testMapSelectionSimple() {
        Map<String, String> map = new HashMap<String, String>();
        map.put("foo", "bar");
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("map", map);
        Expression exp = PARSER.parseExpression("#map['foo']");
        String value = exp.getValue(context, String.class);
        assertEquals("bar", value);

Advanced predicate based map selection

In the slightly more involved three step example of map selection the first expression selects all map entries with value less than three. The second and third expressions select the first and last map entry with value less than three respectively.

    public void testSelectionFromMapAdvanced() {
        Map<Integer, Integer> map = new TreeMap<Integer, Integer>();
        map.put(1, 1);
        map.put(2, 2);
        map.put(3, 3);
         * NOTE: select all map entries with value less than 3
        Map<Integer, Integer> all = (Map<Integer, Integer>) PARSER.parseExpression("#root.?[value<3]").getValue(map);
        assertTrue(all.size() == 2);
        Iterator<Integer> iterator = all.keySet().iterator();
        assertTrue(iterator.next() == 1);
        assertTrue(iterator.next() == 2);
         * NOTE: select first entry with value less than 3
        Map<Integer, Integer> first = (Map<Integer, Integer>) PARSER.parseExpression("#root.^[value<3]").getValue(map);
        assertTrue(first.keySet().iterator().next() == 1);
         * NOTE: select last entry with value less than 3
        Map<Integer, Integer> last = (Map<Integer, Integer>) PARSER.parseExpression("#root.$[value<3]").getValue(map);
        // assertTrue(last.keySet().iterator().next() == 2);
        assertTrue(last.size() == 1);

Note that the final assertion isn’t like those that precede it. It has been simplified considerably. This is because the commented out assertion above it actually fails. It isn’t clear why this fails to work as the others do and this issue has been raised by the author on the forums. Update: It seems there is a bug open on this issue already.

Collection projection

Collection projection is a fascinating feature of SpEL. It essentially takes as input objects and returns a cross section of those objects in the form of their properties after having operated on their properties.

    public void testCollectionProjection() {
        List<User> list = new ArrayList<User>(Arrays.asList(new User("foo"), new User("bar"), new User("baz")));
        List<String> names = (List<String>) PARSER.parseExpression("#root.![name]").getValue(list);
        assertEquals(Arrays.asList("foo", "bar", "baz"), names);

Above the parser is provided three User objects and is instructed to extract the name property from all those objects. Admittedly this is a very simple case but it illustrates the use of projection.

Application context

The vast majority of the use of SpEL is likely to be as part of the Spring application context either through its use in xml or within annotations.

XML based configuration

Here are examples of how SpEL may be used in XML.

<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/<
<property name="defaultLocale" value="#{ systemProperties['user.region'] }"/<
<property name="myOtherBeanProperty" value="#{ myOtherBean.property }"/>

Annotation based configuration

Alternatively expressions can be used within the @Value annotation.

@Value("#{ systemProperties['userName'] }")


For the author the Spring Expression Language has proved to be by far the most interesting feature addition to Spring 3. The expression language is incredibly terse and incredibly powerful inspired often by the Groovy scripting grammar. What’s also incredibly gratifying is that it incorporates certain syntax that was proposed for Java but failed to be incorporated. Overall it is an excellent feature addition and it will be interesting to see how SpEL is used over time within Spring and in other Spring portfolio projects for which it was intended.

There are already reports of Spring Integration being enhanced greatly with the addition of SpEL which will manifest in version 2. It would be nice to see SpEL becoming more pervasive in Spring and associated portfolio projects than simply being used to look up configuration within the application context. Naturally there will be the consideration of the expressions becoming unwieldy and perhaps unmaintainable over time in any given code base but the considerations of misuse and complexity apply to any language.

11 thoughts on “Spring Expression Language (SpEL) Primer”

  1. Does reference of this form in an SpEL expression

    @Value(“#{ systemProperties[‘user.region’] }”)

    still use PropertyPlaceholderConfigurer to retrieve the property values?


  2. Well well documented stuff, appreciate this.

    I have a problem –

    How to set a property’s value (using setValue or assignment) on List of object in one go ? I would hate to iterate over the List to do the assigment .


  3. Can you take projection a step further. I have some JAXB generated classes which contain collections which again contain collections etc.

    At the moment I have to iterate through each level to the bottom of the tree to call a getName() method. Its all very simple code but extremely verbose. Ideally I’d like to something similar to XPATH and in just one line specify the tree structure, and get it to call getName() on each item on the bottom level of the tree, returning a List of all matching items.

    I hope that makes sense.



  4. I have a problem, my bean definitions must to have dots in his names

    Field or property ‘java’ cannot be found on object of type ‘org.springframework.beans.factory.config.BeanExpressionContext’

    Please confirm that dot are not allowed in bean name while using Spring expression language.

  5. Hi Dhruba.
    How navigate array in array with SpEL?
    public class Tree {
    private List childTs;
    public List getChildTs() {return this.childTs; }
    org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 8): Field or property ‘childTs’ cannot be found on object of type ‘org.hibernate.collection.PersistentBag’
    “childTs[0].childTs” it’s OK
    1042E:(pos 8): Problem parsing right operand

Leave a Reply