Introduction
The article Introduction to Spring Expression Language (SpEL) will provide introductory details in writing expression languages using Spring's Expression framework. The reader is expected to having a basic understanding on the core concepts of Spring before reading this article (Read: Introduction to Spring Framework). This article explains the usage of Spring's Expression API for writing and parsing expressions. This article includes plenty of code samples for illustrating the concepts of expressions by explaining how to write custom functions and custom bean resolvers, accesing java methods etc. Later on, the article provides details about writing expressions pertaining to collections and modifying variables. The miscellaneous section of the article explains the usage of T operator and null-safe operator.
Spring Framework Articles & Books
- Spring Articles
- Spring Books
- Introduction to Spring Framework
- Introduction to Spring Web Flow (SWF)
- Introduction to Spring Batch
- Introduction to Spring JDBC Framework
What is Spring Expression Language (SpEL)?
SpEL is powerful expression language created by Spring framework community to work with all the Spring framework products. There are several existing expression languages like MVEL, OGNL and JBoss EL. Every EL is developed with some purpose in mind. SpEL is created to help the Spring porfolio products. The syntax used for the SpEL is same like Unified EL. But, it has lot of powerful features that are missing in the Unified EL.
Another advantage of SpEL is it can work independently without depending on the Spring environment. In the following sections, you will read the complete details on how tto write and use the Spring Expression Language.
Download Spring Expression Language (SpEL) Example
Writing Spring Expressions
In this section we will write a simple program which illustrates the usage of Spring Expression. Refer the sample code given below. To start with, we have constructed an expression parser object capable of parsing expressions fed into it. One concrete expression parser object that comes with Spring Expression is the SpelExpressionParser class which stands for Spring Expression Language Parser. An instance of Expression object can be obtained by calling the parseExpression() method which is defined on the Parser object.
package net.javabeat.articles.spring3.el;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class ExpressionTest {
public static void main(String[] args) {
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("'Testing Spring Expression Framework'");
String message = (String) expression.getValue();
System.out.println("Message is " + message);
}
}
The value passed to this method must be a valid expression string. During the course of this article, we will cover in-depth details with respect to the various applicable syntax that can be passed to this method. A call to getValue() defined on the Expression object will resolve and return the desired result. In the above example, the expression passed is expected to return an instance of String.
Using user-defined functions in Expressions
In the last section, we saw how to write a simple program using Spring's Expression API. In this example, we will see two more new concepts. The first one is how to make use of Spring's EvaluationContext which serves as a context object for storing various objects and that can be later used while parsing expressions. The second is to write Custom functions and to register it so that such functions can be used as part of expressions.
Have a look at the below utility method which finds out the maximum elements from a collection and returns it. Later on in this section, we will use this class for illustration purpose.
package net.javabeat.articles.spring3.el.utils;
import java.util.Collection;
import java.util.Iterator;
public class CollectionUtils {
public static Integer maxElement(Collectioncollection){
Integer maxElement = null;
Iteratoriterator = collection.iterator();
while (iterator.hasNext()){
Integer integer = iterator.next();
if (maxElement == null){
maxElement = integer;
}else{
if (integer.intValue() > maxElement.intValue()){
maxElement = integer;
}
}
}
return maxElement;
}
}
One more utility class which determines if a given number is prime or not is given below.
package net.javabeat.articles.spring3.el.utils;
public class MathUtils {
public static boolean isPrime(Integer number){
if (number == 0){
return false;
}
for (int index = 2; index < number; index ++){
if (number %index == 0){
return false;
}else{
continue;
}
}
return true;
}
}
In the below code, we have initialized an instance of EvaluationContext object whose concrete implementation happens to be the class StandardEvaluationContext. A context evaluation object can be used for storing any number of objects which can be used later in the expressions for retrieving the values. We will see examples for this scenario later in this article. Other than this usage, an evaluation context can also be used for registering user-defined functions which can later be referenced in functions.
package net.javabeat.articles.spring3.el;
import java.lang.reflect.Method;
import java.util.Collection;
import net.javabeat.articles.spring3.el.utils.CollectionUtils;
import net.javabeat.articles.spring3.el.utils.MathUtils;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class FunctionsTest {
public static void main(String[] args) throws Exception{
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
Method method = null;
Expression expression = null;
Boolean value = null;
// Register the method isPrime()
method = MathUtils.class.getMethod("isPrime", Integer.class);
context.registerFunction("prime", method);
expression = parser.parseExpression("#prime(10)");
value = expression.getValue(context, Boolean.class);
System.out.println("Number 10 is prime: " + value);
expression = parser.parseExpression("#prime(37)");
value = expression.getValue(context, Boolean.class);
System.out.println("Number 37 is prime: " + value);
// Register the method maxElement()
method = CollectionUtils.class.getMethod("maxElement", Collection.class);
context.registerFunction("max", method);
expression = parser.parseExpression("#max({10, 43, 45, 98, 32, 1})");
Integer maxElement = expression.getValue(context, Integer.class);
System.out.println("Max element in the list is : " + maxElement);
}
}
The argument to the registerFunction() method which can be used for registering user-defined function is the name of the function and a method object. For example for registering the MathUtils.isPrime() method we have obtained an instance of the method object by calling the standard reflection APIs. Note that it is not necessary that the Java method name must match the name of the function that is passed to the registerFunction() method. In this case, even though the java method name is isPrime(), this method is registered and available under the name 'prime'. Once the method is registered, it can be used in expressions as '#functionName(arguments)'. Note that the method MathUtils.isPrime() takes one argument and hence the expression language used for accessing the function is '#prime(10)'.
Similarly the java method CollectionUtils.maxElement() is registered under the name 'max'. Note that this method accepts a collection object as its argument and to suit this we have created a list object using the list '{element1, element2}'.
Accessing Methods in Spring Expression
In this section, we will see how to access methods defined in Java language. Have a look at the below code.
package net.javabeat.articles.spring3.el;
import java.util.List;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class MethodAccessTest {
public static void main(String[] args) {
test1();
test2();
test3();
}
private static void test1(){
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("new java.lang.String('Hello')");
String stringObject = expression.getValue(String.class);
System.out.println("String object is " + stringObject);
}
private static void test2(){
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("'Find me'.charAt(3)");
Character character = expression.getValue(Character.class);
System.out.println("Character at position 3 is " + character);
}
private static void test3(){
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("new java.util.ArrayList()");
@SuppressWarnings("unchecked")
Listnumbers = expression.getValue(List.class);
System.out.println("Numbers list is " + numbers);
}
}
In the first test method, we have used 'new ClassName()' for creating an instance of the class and the same is later referenced in the getValue() object. Note that getValue() method is overloaded, if the caller for sure knows the return type of the evaluated expression, the the overloaded version getVerion(Class
Resolving Bean objects
We have seen in the last few sections that an evaluation context object can be used for storing objects as well as for registering user-defined objects. Other use cases for defining a evaluation context object is to define a custom bean resolver object for resolving bean references.
package net.javabeat.articles.spring3.el;
import net.javabeat.articles.spring3.el.utils.SimpleBeanResolver;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class BeanReferencingTest {
public static void main(String[] args) {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
SimpleBeanResolver beanResolver = new SimpleBeanResolver();
context.setBeanResolver(beanResolver);
Expression expression = null;
expression = parser.parseExpression("@string");
String strResult = expression.getValue(context, String.class);
System.out.println("Result is " + strResult);
expression = parser.parseExpression("@float");
Float floatResult = expression.getValue(context, Float.class);
System.out.println("Result is " + floatResult);
}
}
Bean objects can be referenced in expressions with the syntax '@BeanName'. Such expressions that involve defining bean names have to resolved by attaching a custom bean resolver in the evaluation context object. In the above code sample, we have defined a custom bean resolver object by calling the method 'setBeanResolver()' method. Note that we have kept the implementation of the custom bean resolver as simple as possible by returning a pre-defined well object java object after checking the name of the bean.
The above implementation checks for the parameter name and returns the java object accordingly. Hence, when the expression '@string' is used, the second parameter will hold the bean name which is 'string' and accordingly an appropriate object type is returned to the callerpackage net.javabeat.articles.spring3.el.utils;
import org.springframework.expression.AccessException;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.EvaluationContext;
public class SimpleBeanResolver implements BeanResolver {
@Override
public Object resolve(EvaluationContext context, String param) throws AccessException {
if (param.equals("string")){
return new String("TEST");
}else if (param.equals("integer")){
return new Integer(100);
}else if (param.equals("float")){
return new Float(10.34);
}else{
return null;
}
}
SOURCE:http://www.javabeat.net/articles/246-introduction-to-spring-expression-language-spel-1.html
}
0 comments:
Post a Comment