Spring Expression Language Example $ vs #

SpEL is an abbreviation of Spring Expression Language which can be used to query property value from a properties file (Use $), or manipulate java objects and it’s attributes at runtime( Use #). Both of the two modifiers ($ or # ) can be used in the spring XML configuration files directly or can be used in java source code with the @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 the @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.

  1. 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>
  2. Then you can use the above defined property in later pom.xml content use the $ 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.

  1. If you have multiple properties file in your spring application, you can read them all with the following steps.
  2. 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 {
          ......
    }
  3. Then you can use ${key_name} to get all the properties values from those properties files.

4. Run Spring Expressions Programmatically.

  1. Besides you can use the # modifier to run spring expression with the @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 are 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 expressions such as “userName + title” etc) and return Expression object.
    Expression expression = expressionParser.parseExpression("userName");
  4. Invoke the Expression object’s getValue method to get the expression value.

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

5. Spring Expression Language Example.

  1. Below is the example project files list.
    D:\WORK\DEV2QA.COM-EXAMPLE-CODE\SPRINGBOOT\READMULTIPLEPROPERTIESFILE
    │  .classpath
    │  .project
    │  .springBeans
    │  pom.xml
    │
    ├─.settings
    │      org.eclipse.core.resources.prefs
    │      org.eclipse.jdt.core.prefs
    │      org.eclipse.m2e.core.prefs
    │
    ├─src
    │  └─main
    │      ├─java
    │      │  └─com
    │      │      └─dev2qa
    │      │          ├─config
    │      │          │      SpringAppContextConfig.java
    │      │          │
    │      │          ├─dto
    │      │          │      UserAccountDTO.java
    │      │          │      UserJerryDTO.java
    │      │          │      UserRichardDTO.java
    │      │          │
    │      │          └─test
    │      │                  Test.java
    │      │
    │      └─resources
    │              department.properties
    │              title.properties
  2. In this example, UserJerryDTO and UserRichardDTO will use ${} to read the property values saved in both department.properties and title.properties file.
  3. The two DTO will also use #{} to read instance variable value from UserAccountDTO class’s String, List, and Map type variables.

5.1 Example Spring Bean Java Configuration File.

  1. 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.

  1. This java class contains a user name list and related salary map object.
  2. 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.

  1. This spring bean will read user jerry’s title and department value from the two properties file.
  2. 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.

  1. Similar to UserJerryDTO, the difference is that it will read user name from the 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.

  1. 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.

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

5.7 title.properties.

  1. title.properties
    title1=CEO
    title2=CTO
    title3=CFO
    title4=Manager
    title5=Director

5.8 pom.xml File.

  1. pom.xml
    <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.

  1. Example console output.
    UserName : Jerry, title : CEO, department : Development, salary : 100000
    Richard, CTO, Financial, 80000
    UserName : Jerry, title : CEO, department : Development, salary : 666666666

Leave a Comment

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.