In this tutorial, we are going to learn about Spring Expression Language (SpEL) with annotations.
Spring Expression Language is a powerful language to query from Object graph and manipulate data in Object graph during run time. SpEL can be used both with XML and annotation-based configuration.
Syntax:
#{<expression_string>}
There are many expression languages available such as:
- JSP EL
- MVEL
- JBOSS EL
- OGNL.
Spring provides extended support compared with other expression languages with template engine functionality and method invocation capability
While configuring beans, in the configuration file, we can use SpEL for setting values, that can be evaluated during run time and values will be set.
Example :
<bean id="id1" class="A">
<property name="x" value="50"/>
</bean>
<bean id="id2" class="B">
<property name="y" value="#{id1.x * 10}"/>
</bean>
If we take above example, we can notice SpEL statement #{id1.x * 10}, which means getX() is called to get x value of variable present in object id1, and the return value is multiplied by 10. So if you convert the above SpEL expression into Java code, it will look like:
id2.setY(id1.getX()*10);
SpEL to read Static Methods :
By using Spring Expression Language, you can call static methods or access static variables of both predefined Java classes as well as user defined ones. To access a static method of class java.lang.Math, you have to surround the class name with T() and then call our required method. So the syntax of SpEL expression to call static method will be like
Example :
<bean id="id1" class="A">
<property name="x" value="#{T(java.lang.Math).pow(3,2)}"/>
<property name="y" value="#{T(java.lang.Math).PI}"/>
</bean>
Here we are calling the static method of java.lang.Math i.e., pow and static variable PI
Handling the null values in SpEL :
In a normal programming language, it is easy to handle NullPointerExceptions, with proper null checks on the variables. When it comes to SpEL expression, there comes special null safe operator (?.).
This should be used when you are using a reference variable to execute a method or while accessing a variable in it so that you can verify whether it is null or not before using it at runtime. If you use this safe operator, it will just return null if the reference is null, instead of throwing NullPointerException.
Example :
ExpressionParser parser = new SpelExpressionParser();
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);
System.out.println(city); // Smiljan
tesla.setPlaceOfBirth(null);
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);
System.out.println(city); // null - does not throw NullPointerException!!!
If you take the above example, at line 3, we have set the place of birth to an object having Smiljan city, and when we called PlaceOfBirth?.City, it return safely Smiljan.
But when we nullified the place of a birth reference object in Tesla, at line 7, and when we called PlaceOfBirth?.City, though PlaceOfBirth is null and we are accessing city from Null reference, it won’t throw NullPointerException instead just return null.
Example for Spring Expression Language :
SpEL Dependencies (pom.xml)
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
Here we are adding just the core spring jars, and it will download Spring Expression Language dependencies by itself and no need to explicitly specify them. This is how Maven helps you to develop projects easily.
Spring Beans :
Book.java
Author.java
package com.onlinetutorialspoint.beans;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Author {
@Value("#{book.title?.toUpperCase()}")
private String bookTitle;
@Value("Rod Johnson")
private String authorName;
@Value("#{T(java.lang.Math).PI}")
private double x;
public void show() {
System.out.println("Book Title : " + bookTitle);
System.out.println("Author Name : " + authorName);
System.out.println("PI Value : " + x);
}
}
Here, if you notice we have mentioned on top of variable bookTitle
in Author class, a SpEL expression #{book.title?.toUpperCase()}
, with logic that if book.title is not equal to null convert it to upper case.
Expression is equivalent to:
String title = book.getTitle();
If(title != null) {
return title.toUpperCase();
}
In the same way, we are accessing the static variable of Math class PI and setting it to variable x.
Spring Bean Configuration :
applicationcontext.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.onlinetutorialspoint.beans" />
<context:annotation-config />
</beans>
Here we have used <context:component-scan base-package="com.onlinetutorialspoint.beans" />
, to inform the spring container to parse the base package mentioned and look for annotated classes to create a bean by itself and autowire when required.
We specified <context:annotation-config />
, to inform the spring container that configuration is annotation based.
To Run the Application :
Main.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.onlinetutorialspoint.beans.Author;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.onlinetutorialspoint.beans.Author;
public class Main {
public static void main(String args[]){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");
Author author= (Author)context.getBean("author");
author.show();
}
}
Output :
Book Title : SPRING
Author Name : Rod Johnson
PI Value : 3.141592653589793
Here though we did set the value of the book title as spring (in lower letters) when printed it, we got SPRING (all in capital letters), because of SpEL.
Happy Learning 🙂