Evaluating expressions using Spring Expression Language (SpEL)

Evaluating expressions using Spring Expression Language (SpEL)

The Spring Expression Language (SpEL for short) is a powerful expression language that supports querying and manipulating an object graph at runtime as well as evaluating logical and mathematical expressions and many other features. Have a look at the SpEL page for a list of these. SpEL can be used independent regardless your application makes use of the Spring application framework or not.

In this post we will be using SpEL for a number of use cases to explore the capabilities of this library. We will be covering the following topics.

  1. Getting SpEL
  2. Evaluating Literal Expressions
  3. Performing Method Invocations on Literals
  4. Accessing Object Properties and Methods
  5. Operators
  6. Using Multiple Objects and Variables
  7. Functions

Getting SpEL

If you are using maven, add the following dependency in your pom file.


<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>4.0.0.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-expression</artifactId>
	<version>3.1.0.RELEASE</version>
</dependency>

Otherwise, you can download the jar from here and add it to your classpath.

Prior to calling any of the functions below, initialize a class level attribute SpelExpression parser as follows


public class Main {
	private ExpressionParser parser;
	
	public Main(){
		this.parser = new SpelExpressionParser();
        }
...

 

Evaluating Literal Expressions

SpEL can render literal values in their correct type.


/**
* A function that tests literal expressions.
*/
private void evaluateLiteralExpresssions() {
	//A string literal
	Expression exp = parser.parseExpression("'Hello World'");
	String message = (String) exp.getValue();
	System.out.println(message);

	//An integer literal
	exp = parser.parseExpression("6");
	Integer value = exp.getValue(Integer.class);
	System.out.println(value*2);	
}

Performing Method Invocations on Literals

SpEL can be used to perform methods on literals. For example, call the substring method on a string.


/**
* A function that tests method invocation on literals
*/
private void methodInvocationOnLiterals() {
	Expression exp = parser.parseExpression("'Hello World'.concat('!')");
	String message = (String) exp.getValue();
	System.out.println(message);

	exp = parser.parseExpression("'Hello World'.length()");
	Integer size = exp.getValue(Integer.class);
	System.out.println(size);

	exp = parser.parseExpression("'Hello World'.split(' ')[0]");
	message = (String)exp.getValue();
	System.out.println(message);		
}

 

Accessing Object Properties and Methods

An expression can directly use values of a particular property of a class (by simply using the property name). Similarly, a function can be called in an expression (by using functionName())


/**A function that tests accessing properties of objects**/
private void accessingObjectProperties() {
	User user = new User("John", "Doe", "[email protected]", true, 30);

	Expression exp = parser.parseExpression("firstName");
	System.out.println((String)exp.getValue(user));

	exp = parser.parseExpression("isAdmin()==false");
	boolean isAdmin = exp.getValue(user, Boolean.class);
	System.out.println(isAdmin);

        exp = parser.parseExpression("emailAddress.split('@')[0]");
	String emailId = exp.getValue(user, String.class);
	System.out.println(emailId);
}

Operators

SpEL supports the following mathematical, logical and relational operators.

Relational Operators: ==, !=, <, <=, >, >=

Logical Operators: and, or, not

Mathematical Operators: +, -, /, *, %, ^


private void operators() {
	User user = new User("John", "Doe", "[email protected]", true, 30);

	Expression exp = parser.parseExpression("age > 18");
	System.out.println(exp.getValue(user,Boolean.class));

	exp = parser.parseExpression("age < 18 and isAdmin()");
	System.out.println(exp.getValue(user,Boolean.class));
}

Using Multiple Objects and Variables

An expression need not only refer to one object as we can use multiple objects of different types in an expression. You add all objects you want to use in a context as key-value pairs and then refer to the object in the expression.


private void variables() {
	User user = new User("John", "Doe", "[email protected]", true, 30);
	Application app = new Application("Facebook", false);

        StandardEvaluationContext context = new StandardEvaluationContext();
	context.setVariable("user", user);
	context.setVariable("app", app);

        Expression exp = parser.parseExpression("#user.isAdmin() and #app.isActive()");
	boolean result = exp.getValue(context,Boolean.class);
	System.out.print(result);
}

Functions

In SpEL, you can define your own functions and call them from within your expression.


private void customFunctions() {
    try {
	StandardEvaluationContext context = new StandardEvaluationContext();
	context.registerFunction("isURLValid", Function.class
              .getDeclaredMethod("isValid", new Class[] { String.class }));

	String expression = "#isURLValid('http://google.com')";

	boolean isURLValid = parser.parseExpression(expression).getValue(context,Boolean.class);	System.out.println(isURLValid);
        } catch (Exception e) {
	    System.out.println(e);
       } 
}