[JAVA] Dynamically access the property specified by the string in Spring BeanWrapper

1.First of all

This time, I would like to introduce how to dynamically access the property specified by the character string by using BeanWrapper of Spring Framework. A brief description of BeanWrapper is" API for setting and getting property values without using Setters and Getters ". When you think of a library that dynamically accesses properties, you might think of "Apache Commons BeanUtils", but for the same purpose. It is a function of.

1.1. What is BeanWrapper?

Spring Framework (Core) Official Guidelines "3.4. Bean manipulation and the Bean Wrapper" But it is well introduced. The basic usage is as follows.

The rules for specifying properties (Expressions) are also included in the official guidelines.

Table 11. Examples of properties

Expression Explanation
name Indicates the property name corresponding to the methods getName() or isName() and setName(..)
account.name Indicates the nested property name of the property account corresponding e.g. to the methods getAccount().setName() or getAccount().getName()
account[2] Indicates the third element of the indexed property account. Indexed properties can be of type array, list or other naturally ordered collection
account[COMPANYNAME] Indicates the value of the map entry indexed by the key COMPANYNAME of the Map property account

The basic usage is explained, but unfortunately there is no sample for manipulating collections (ʻaccount [2] and ʻaccount [COMPANYNAME]). This time I would like to explain a sample of this collection.

2.1. How to use BeanWrapper

When manipulating collection properties, the usage depends on the depth of manipulating. This time, I would like to explain the following two patterns.

BeanWrapperDemo.java


package demo;

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

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

public class BeanWrapperDemo {

	public static void main(String[] args) {
		//Set the elements to be stored in the collection
		test01();
		//Set values for the properties of the elements stored in the collection
		test02();
	}

	//★ Point 1
	private static void setPropertyValues(Object target, Map<String, Object> input) {
		BeanWrapper wrapper = new BeanWrapperImpl(target);
		for (String key : input.keySet()) {
			wrapper.setPropertyValue(key, input.get(key));
		}
	}
	
	//Set the elements to be stored in the collection
	private static void test01() {
		try {
			//★ Point 2
			Team team = new Team();
			List<Member> memberList = new ArrayList<>();
			Map<String, Item> items = new HashMap<>();
			team.setMemberList(memberList);
			team.setItems(items);
			
			Member taro = new Member();
			taro.setMail("[email protected]");
			taro.setName("TARO YAMADA");
			Member hanako = new Member();
			hanako.setMail("[email protected]");
			hanako.setName("HANAKO TOYOSU");
			
			Item notepc = new Item();
			notepc.setItemName("Laptop");
			notepc.setPrice(100000);
			Item book = new Item();
			book.setItemName("A thorough introduction to Spring");
			book.setPrice(4000);
			
			Map<String, Object> input = new HashMap<>();
			input.put("teamId", "01234");
			input.put("teamName", "HelloWorld");
			input.put("point", 100);
			//★ Point 3
			input.put("memberList[0]", taro);
			input.put("memberList[1]", hanako);
			input.put("items[A01]", notepc);
			input.put("items[A02]", book);
			
			setPropertyValues(team, input);
			System.out.println(team);
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	//Set values for the properties of the elements stored in the collection
	private static void test02() {
		try {
			//★ Point 4
			Team team = new Team();
			List<Member> memberList = new ArrayList<>();
			memberList.add(new Member());
			memberList.add(new Member());
			Map<String, Item> items = new HashMap<>();
			items.put("A01", new Item());
			items.put("A02", new Item());

			team.setMemberList(memberList);
			team.setItems(items);
			
			Map<String, Object> input = new HashMap<>();
			input.put("teamId", "01234");
			input.put("teamName", "HelloWorld");
			input.put("point", 100);
			//★ Point 5
			input.put("memberList[0].mail", "[email protected]");
			input.put("memberList[0].name", "TARO YAMADA");
			input.put("memberList[1].mail", "[email protected]");
			input.put("memberList[1].name", "HANAKO TOYOSU");
			input.put("items[A01].itemName", "Laptop");
			input.put("items[A01].price", 100000);
			input.put("items[A02].itemName", "A thorough introduction to Spring");
			input.put("items[A02].price", 4000);
			
			setPropertyValues(team, input);
			System.out.println(team);
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

}

** ★ Point 1 ** Create an instance of BeanWrapper. ʻOrg.springframework.beans.BeanWrapper is an interface. The implementation class is ʻorg.springframework.beans.BeanWrapperImpl, and there are several constructors, but this time we will use the one that takes an object as an argument. Use the setPropertyValue method to set the value. The first argument is the rule (Expression) that specifies the property, and the second argument is the value you want to set. See the Javadoc for more details.

** ★ Point 2 ** When "Set the elements to be stored in the collection", the target collection must be instantiated. The contents of the collection are unnecessary.

** ★ Point 3 ** To set the elements to be stored in the collection, use [] to specify the position of the elements in the collection.

** ★ Point 4 ** When "Set a value to the property of an element stored in a collection", that element of the target collection must be instantiated.

** ★ Point 5 ** After specifying the position of the collection with [], specify the property to be set with .property name. An exception will be thrown if the elements of the target collection are not instantiated. Therefore, it is necessary to instantiate the element to be operated at point 4 in advance.

2.2. (Reference) Definition of model class (POJO)

For reference, I'll list the model classes so you can see the nested collection.

Team.java


package demo;

import java.util.List;
import java.util.Map;

public class Team {
	private String teamId;
	private String teamName;
	private int point;
	private List<Member> memberList;
	private Map<String, Item> items;

	// setter,getter omitted
	// override toString generated by eclipse
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Team [teamId=");
		builder.append(teamId);
		builder.append(", teamName=");
		builder.append(teamName);
		builder.append(", point=");
		builder.append(point);
		builder.append(", memberList=");
		builder.append(memberList);
		builder.append(", items=");
		builder.append(items);
		builder.append("]");
		return builder.toString();
	}
}

Member.java


package demo;

import java.util.Map;

public class Member {
	private String mail;
	private String name;
	private Map<String, String> memo;

	// setter,getter omitted
	// override toString generated by eclipse
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Member [mail=");
		builder.append(mail);
		builder.append(", name=");
		builder.append(name);
		builder.append(", memo=");
		builder.append(memo);
		builder.append("]");
		return builder.toString();
	}
}

Item.java


package demo;

public class Item {
	private String itemName;
	private int price;

	// setter,getter omitted
	// override toString generated by eclipse
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Item [itemName=");
		builder.append(itemName);
		builder.append(", price=");
		builder.append(price);
		builder.append("]");
		return builder.toString();
	}
}

3. Finally

This time, I explained how to dynamically access the property specified by the character string using BeanWrapper of Spring Framework. ** It is a convenient BeanWrapper, but of course it is better to use ordinary'Setter, Getter' for processing performance. ** ** I think that the usage of BeanWrapper is (1) general-purpose processing that requires dynamic access, and (2) setting input values in the test class by taking advantage of the convenience of being able to specify properties with character strings.

Recommended Posts

Dynamically access the property specified by the string in Spring BeanWrapper
Put the file in the properties of string in spring xml configuration
Access the network interface in Java
Procedure to make the value of the property file visible in Spring Boot
How to get the setting value (property value) from the database in Spring Framework
[Java] Divide a character string by a specified character
Spring Autowired is written in the constructor
Static file access priority in Spring boot
Deletes after the specified character from the character string
Switching beans by profile annotation in Spring
Sort by multiple fields in the class
[Spring Boot] How to get properties dynamically from a string contained in a URL
Parse the date and time string formatted by the C asctime function in Java