Search code examples
springspring-el

SPEL (Spring Expression Language) Collection Selection calling methods/functions in selection


I am trying to write simple validation rules with SpEL

I want to be able to say something like, "Do any elements in the List have a value greater then x". Simple case works fine, but I wanted to extend it to get the absolute value first and then do the greater than test

If I try to call methods or functions as part of the criteria to select from a collection. it seems to loose the context that I am working with an item in the collection

import java.util.Arrays;
import java.util.List;

public class BeanClass {

    private final List<ListOf> list;

    public BeanClass(ListOf... list){
        this.list = Arrays.asList(list);
    }

    public List<ListOf> getList(){
        return list;
    }
}

public class ListOf {
    private final double value;

    public ListOf(double v) {
        this.value = v;
    }

    public double getValue() {
        return value;
    }
}

import org.junit.Test;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import static org.junit.Assert.assertTrue;

public class SpelTest {

    @Test
    public void test(){
        ExpressionParser parser = new SpelExpressionParser();

        // works as expected
        Expression expression1 = parser.parseExpression("list.?[ value>2 ].size()!=0");
        assertTrue(expression1.getValue(new BeanClass(new ListOf(1.1), new ListOf(2.2)), Boolean.class));

        Expression expression2 = parser.parseExpression("list.?[ T(java.lang.Math).abs(value) > 2 ].size()!=0");

        // get this error:
        //org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 5): Property or field 'value' cannot be found on object of type 'BeanClass' - maybe not public?
        assertTrue(expression2.getValue(new BeanClass(new ListOf(1.1), new ListOf(-2.2)), Boolean.class));
    }
}

I have played with defining my own function and registering it

Experimented with #this as well


Solution

  • Looks like an issue, though: https://jira.spring.io/browse/SPR-12035

    As a cunclusion: you can't use method invocation within selectionExpression for items.