Spring Expression Language Example $ vs #

SpEL is abbreviation of Spring Expression Language which can be used to query property value from properties file (Use $), or manipulate java object and it’s attributes at runtime( Use #). Both of the two modifier ($ or # ) can be used in spring XML configuration file directly, or can be used in java source code with @Value annotation. This article will show you how to use them in spring with examples and what is the difference between them.

1. Difference Between $ and #.

1.1 Use ${key_name} To Read Property Value In Properties File.

  1. Get the value of the specified key in the external properties file.
  2. Can be used in XML configuration file or in java file with @Value annotation.
  3. Get spring context environment variables in pom.xml properties definition.

1.2 Use #{spring_expression} To Run The Spring Expression.

  1. Can run any spring expression (can manipulate any java object (spring bean) and it’s variables), support operator. Then return the expression calculated result value back or assign the value to @Value annotated java variable.
  2. Can be used in XML configuration file or in java file with @Value annotation.
  3. Can use ${key_name} as the expression (#{‘${jdbc.user_name}’}).
    @Value("#{'${jdbc.user_name}'}")
    private String jdbcUserName;

2. Use $ To Get Properties Environment Variable.

When you create a spring project with maven, you can define spring environment properties in the pom.xml like below.

<properties>
     <java.version>1.6</java.version>
     <spring-framework.version>3.2.3.RELEASE</spring-framework.version>
</properties>

Then you can use above defined property in later pom.xml content use $ modifier.

<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>${spring-framework.version}</version>
</dependency>

3. Use $ To Get Property Value From Multiple Properties File.

If you have multiple properties file in your spring application, you can read them all with following steps.

  1. Register multiple properties files in the spring bean context configuration java class use @PropertySource annotation.
    @PropertySource(value = {"classpath:department.properties", "classpath:title.properties"})
    //@PropertySource("classpath:department.properties")
    public class SpringAppContextConfig {
          ......
    }
  2. Them you can use ${key_name} to get all the properties value from those properties file.

4. Run Spring Expressions Programmatically.

Besides you can use # modifier to run spring expression with @Value annotation, you can also use SpelExpressionParser and StandardEvaluationContext class to run spring expression programmatically to get or set related java object instance variable value. Below is the steps.

4.1 Get ( Set ) SpEL Value From ( To ) Java Object.

  1. Create a new ExpressionParser object.
    ExpressionParser expressionParser = new SpelExpressionParser();
  2. Create a new EvaluationContext object, pass the target java object to it, the spring expression will be executed on that object.
    EvaluationContext evaluateContext = new StandardEvaluationContext(userRichardDto);
  3. Use ExpressionParser to parse spring expression ( a variable name in this example, you can also pass complex expression such as “userName + title” etc) and return Expression object.
    Expression expression = expressionParser.parseExpression("userName");
  4. Invoke Expression getValue method to get the expression value.

    String userName = (String) expression.getValue(evaluateContext);
  5. Invoke Expression setValue method to set the value to the expression( generally a java variable ).
    expression.setValue(evaluateContext, 666666666);
    

5. Spring Expression Language Example.

spring read multiple properties file example source files

In this example UserJerryDTO and UserRichardDTO will use ${} to read the property values saved in both department.properties and title.properties file. The two DTO will also use #{} to read instance variable value from UserAccountDTO class’s String, List and Map variables.

READ :   Spring MVC Full Java Based Configuration Example

5.1 Example Spring Bean Java Configuration File.

SpringAppContextConfig.java

package com.dev2qa.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@ComponentScan(basePackages = {"com.dev2qa"})
@Configuration
// Register multiple properties file.
@PropertySource(value = {"classpath:department.properties", "classpath:title.properties"})
//@PropertySource("classpath:department.properties")
public class SpringAppContextConfig {

    /* This bean is used by spring framework to parse out the multiple properties file content
     * and set those content in spring context environment, 
     * then you can use ${key_name} to retrieve related property value in those file. */
    @Bean
    public static PropertySourcesPlaceholderConfigurer getPropertySourcePlaceholderConfig() {
        PropertySourcesPlaceholderConfigurer ret = new PropertySourcesPlaceholderConfigurer();
        return ret;
    }

}

5.2 UserAccountDTO Spring Bean.

This java class contains user name list and related salary map object.

UserAccountDTO.java

package com.dev2qa.dto;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;

@Component("userAccount")
public class UserAccountDTO {

    public final String USERNAME_JERRY = "Jerry";

    public final String USERNAME_RICHARD = "Richard";

    public final String USERNAME_JACKIE = "Jackie";

    public List<String> userNameList = null;

    public Map<String, Integer> userSalaryMap = null;

    public UserAccountDTO() {

        if(userNameList == null)
        {
            userNameList = new ArrayList<String>();
            userNameList.add(USERNAME_JERRY);
            userNameList.add(USERNAME_RICHARD);
            userNameList.add(USERNAME_JACKIE);
        }

        if(userSalaryMap == null)
        {
            userSalaryMap = new HashMap<String, Integer>();
            userSalaryMap.put(USERNAME_JERRY, 100000);
            userSalaryMap.put(USERNAME_RICHARD, 80000);
            userSalaryMap.put(USERNAME_JACKIE, 50000);
        }
    }
}

5.3 UserJerryDTO.

This spring bean will read user jerry’s title and department value from the two properties file. It will also read jerry’s user name from UserAccountDTO spring bean.

package com.dev2qa.dto;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("userJerry")
public class UserJerryDTO {

    @Value("#{userAccount.USERNAME_JERRY}")
    private String userName;

    @Value("#{userAccount.userSalaryMap['Jerry']}")
    private int salary;

    @Value("${dept1}")
    private String department;

    @Value("${title1}")
    private String title;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

5.4 UserRichardDTO.

Similar to UserJerryDTO, the difference is it will read user name from UserAccountDTO user name list.

package com.dev2qa.dto;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("userRichard")
public class UserRichardDTO {

    @Value("#{userAccount.userNameList[1]}")
    private String userName;

    @Value("#{userAccount.userSalaryMap['Richard']}")
    private int salary;

    @Value("${dept5}")
    private String department;

    @Value("${title2}")
    private String title;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

5.5 Example Main Class.

Test.java

package com.dev2qa.test;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import com.dev2qa.config.SpringAppContextConfig;
import com.dev2qa.dto.UserJerryDTO;
import com.dev2qa.dto.UserRichardDTO;

public class Test {

    public static void main(String[] args) {

        // Initialize spring bean context object. 
        ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(SpringAppContextConfig.class);

        // Get userJerry bean.
        UserJerryDTO userJerryDto = (UserJerryDTO)context.getBean("userJerry");

        // Print jerry's user data in console.
        printUserData(userJerryDto.getUserName(), userJerryDto.getTitle(), userJerryDto.getDepartment(), userJerryDto.getSalary());

        // Print richard user data in console.
        getRichardInfoProgramatically(context);

        // Set jerry's new salary data.
        setJerryInfoProgramatically(context);

    }

    /* Get user richard dto property value with spring expression language programmatically. */
    private static void getRichardInfoProgramatically(ConfigurableApplicationContext context) {

        // Get userRichard spring bean,
        UserRichardDTO userRichardDto = (UserRichardDTO)context.getBean("userRichard");

        // Create an ExpressionParser instance. 
        ExpressionParser expressionParser = new SpelExpressionParser();

        // Create an EvaluationContext instance, specify userRichardDto as the target object.
        EvaluationContext evaluateContext = new StandardEvaluationContext(userRichardDto);
      
      /* Run expression on the evaluated context object (userRichard bean) to get related value. 
       * The expression is constructed by plus multiple UserRichardDTO instance variable.
       * */
        Expression expression = expressionParser.parseExpression("userName + ', ' + title+ ', ' + department+ ', ' + salary");
        String userRicharData = (String) expression.getValue(evaluateContext);

        System.out.println(userRicharData);
    }

    /* Set user jerry dto property value with spring expression language programmatically. */
    private static void setJerryInfoProgramatically(ConfigurableApplicationContext context) {

        // Get userJerry spring bean,
        UserJerryDTO userJerryDto = (UserJerryDTO)context.getBean("userJerry");

        // Create an ExpressionParser instance. 
        ExpressionParser expressionParser = new SpelExpressionParser();

        // Create an EvaluationContext instance, specify userJerryDto as the target object.
        EvaluationContext evaluateContext = new StandardEvaluationContext(userJerryDto);

        // Run expression on the evaluated context object (userRichard bean) to set new salary value.
        Expression expression = expressionParser.parseExpression("salary");
        expression.setValue(evaluateContext, 666666666);

        printUserData(userJerryDto.getUserName(), userJerryDto.getTitle(), userJerryDto.getDepartment(), userJerryDto.getSalary());
    }

    private static void printUserData(String userName, String title, String department, int salary) {

        StringBuffer strBuf = new StringBuffer();
        strBuf.append("UserName : ");
        strBuf.append(userName);

        strBuf.append(", title : ");
        strBuf.append(title);

        strBuf.append(", department : ");
        strBuf.append(department);

        strBuf.append(", salary : ");
        strBuf.append(salary);

        System.out.println(strBuf.toString());
    }

}

5.6 department.properties.

dept1=Development
dept2=Testing
dept3=Market
dept4=Sales
dept5=Financial
dept6=Technical Support
dept7=Facility

5.7 title.properties.

title1=CEO
title2=CTO
title3=CFO
title4=Manager
title5=Director

5.8 pom.xml File.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework.samples</groupId>
    <artifactId>ReadMultiplePropertiesFile</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <spring-framework.version>3.2.3.RELEASE</spring-framework.version>
    </properties>

    <dependencies>

        <!-- Spring depend jar. -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>

    </dependencies>
</project>

5.9 Example Console Output.

UserName : Jerry, title : CEO, department : Development, salary : 100000
Richard, CTO, Financial, 80000
UserName : Jerry, title : CEO, department : Development, salary : 666666666
(Visited 32 times, 2 visits today)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.