➤ How to Code a Game
➤ Array Programs in Java
➤ Java Inline Thread Creation
➤ Java Custom Exception
➤ Hibernate vs JDBC
➤ Object Relational Mapping
➤ Check Oracle DB Size
➤ Check Oracle DB Version
➤ Generation of Computers
➤ XML Pros & Cons
➤ Git Analytics & Its Uses
➤ Top Skills for Cloud Professional
➤ How to Hire Best Candidates
➤ Scrum Master Roles & Work
➤ CyberSecurity in Python
➤ Protect from Cyber-Attack
➤ Solve App Development Challenges
➤ Top Chrome Extensions for Twitch Users
➤ Mistakes That Can Ruin Your Test Metric Program
Bulk Loading of Properties in Spring Boot | @Value annotation is used to read data from properties files i.e. from one key to one variable. If we have 20 variables in class then 20 times we have to write @Value which is not a good approach for multiple variables. In that case, we can use Bulk loading using @ConfigurationProperties.
@ConfigurationProperties is also called ‘Bulk Loading’ or reading multiple keys from properties files to our variables at a time.
Rules while working with @ConfigurationProperties:-
- Define the key name using the
prefix.variableName
in the properties file. - Provide that common prefix in our class using annotation
@ConfigurationProperties(prefix="")
. - Define variables in our class including setter & getter methods. You can also override the
toString()
method.
Create a spring starter project with Lombok dependency.
In application.properties file:-
know.app.id = 5
know.app.code = knowprogram
know.app.cost = 5000
package com.knowprogram.demo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Getter;
import lombok.Setter;
@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "know.app")
public class DataRunner implements CommandLineRunner {
private Integer id;
private String code;
private Double cost;
@Override
public void run(String... args) throws Exception {
System.out.println(this);
}
@Override
public String toString() {
return "DataRunner [id=" + id + ", code=" + code + ", cost=" + cost + "]";
}
}
In Console:-
DataRunner [id=5, code=knowprogram, cost=5000.0]
Case-1:- If the key is not present in the properties file and trying to read the same key, then what will happen?
#know.app.id = 5
know.app.code = knowprogram
know.app.cost = 5000
In the case of @Value, it is used to throw an IllegalArgumentException but in the case of @ConfigurationProperties, it gives the default value (null/0/0.0/false).
DataRunner [id=null, code=knowprogram, cost=5000.0]
Internally ConfigProps uses a set method. Logic looks like:- object.setVariable(key). Example:- ob.setCode(code); // auto parsing supported
Case-2:- What if the value and datatype do not match? For example in the properties file, id contains String but the data type of the variable is int.
know.app.id = program
know.app.code = knowprogram
know.app.cost = 5000
In that case, the application will fail to start and give this message:-
Failed to bind properties under 'know.app.id' to java.lang.Integer:
Property: know.app.id
Value: "program"
Origin: class path resource [application.properties] - 1:15
Reason: failed to convert java.lang.String to java.lang.Integer (caused by java.lang.NumberFormatException: For input string: "program")
Action:
Update your application's configuration
Case-3:- What if the properties file contains duplicate values?
know.app.id = 10
know.app.id = 20
know.app.id = 30
know.app.code = knowprogram
know.app.cost = 5000
Values are read from top to bottom and the last value will be taken.
Output:-
DataRunner [id=30, code=knowprogram, cost=5000.0]
Case-4:- What will happen if prefixes/variables do not match in bulk loading?
@ConfigurationProperties(prefix = "know.apps")
know.app.id = 10
knows.app.code = knowprogram
know.apps.cost = 5000
@ConfigurationProperties will never throw any error/exception. It will read only matching variables data. Other values are ignored, so it holds default for no-matching keys/variables.
Output:-
DataRunner [id=null, code=null, cost=5000.0]
@ConfigurationPropties with One-Dimensional Collections and Array
If we define a variable of type List/Set/Array then in the properties file we have to pass data using the below syntax:-
prefix.variableName[index]=value
Index numbers must start from zero, and should be given in order, else application will not be started. In application.properties:-
my.app.data[0]=A
my.app.data[1]=B
my.app.data[2]=C
my.app.data[3]=C
In Class, it can be read using one of the following:-
- List data
- Set data
- String[ ] data
Example:-
package com.knowprogram.demo;
import java.util.List;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Component
@Setter
@Getter
@ToString
@ConfigurationProperties(prefix = "my.app")
public class CollectionDataRunner implements CommandLineRunner {
private List<String> data;
@Override
public void run(String... args) throws Exception {
System.out.println(this);
}
}
Output:-
CollectionDataRunner(data=[A, B, C])
Case-1:- Properties with duplicate Value and Set
In application.properties:-
my.app.data[0]=A
my.app.data[1]=A
my.app.data[2]=A
my.app.data[3]=A
In Class:-
private Set<String> data;
// related Setter, Getter & toString methods
Output:-
CollectionDataRunner(data=[A])
But if we use the list or array then it will read those duplicate values also:-
private List<String> data;
// related Setter, Getter & toString methods
Output:-
CollectionDataRunner(data=[A, A, A, A])
Spring or Spring boot recommends us to use interface, at runtime implementation classes are auto-selected by Spring container:-
- List -> ArrayList
- Set -> LinkedHashSet
- Map -> LinkedHashMap
Due to ArrayList, LinkedHashSet, and LinkedHashMap order is preserved.
@Component
@Setter
@Getter
@ToString
@ConfigurationProperties(prefix = "my.app")
public class CollectionDataRunner implements CommandLineRunner {
private List<String> data;
@Override
public void run(String... args) throws Exception {
System.out.println(data.getClass().getName());
System.out.println(this);
}
}
In console:-
java.util.ArrayList
CollectionDataRunner(data=[A, A, A, A])
@ConfigurationProperties with Map
Syntax:- prefix.variable.mapKey=mapVal
In application.properties file:-
my.app.subjects.eng=85
my.app.subjects.mat=95
my.app.subjects.sci=90
In Class, We must declare the Key as String only, the value can be any type:- Map<String, Integer> subjects
@Component
@Setter
@Getter
@ToString
@ConfigurationProperties(prefix = "my.app")
public class CollectionDataRunner implements CommandLineRunner {
private Map<String, Integer> subjects;
@Override
public void run(String... args) throws Exception {
System.out.println(subjects.getClass().getName());
System.out.println(this);
}
}
Output:-
java.util.LinkedHashMap
CollectionDataRunner(subjects={eng=85, mat=95, sci=90})
If duplicate keys are present then the last one will be considered. In properties file:-
my.app.subjects.eng=85
my.app.subjects.mat=95
my.app.subjects.sci=90
my.app.subjects.sci=70
my.app.subjects.sci=50
Output:-
CollectionDataRunner(subjects={eng=85, mat=95, sci=50})
The keys are case-sensitive and considered different. In properties file:-
my.app.subjects.eng=85
my.app.subjects.mat=95
my.app.subjects.sci=90
my.app.subjects.SCI=70
Output:-
CollectionDataRunner(subjects={eng=85, mat=95, sci=90, SCI=90})
Notice that both sci and SCI hold 90 but in the application.properties file, it was different.
In Java, by default read data in the String representation and later type casting will be done.
my.app.subjects.eng=85
my.app.subjects.mat=95
my.app.subjects.sci=9.0
In this case, the application failed to start. Reason: failed to convert java.lang.String to java.lang.Integer (caused by java.lang.NumberFormatException: For input string: “9.0”)
@ConfigurationProperties With Class and Object
In this case, use the below syntax to define keys in properties:- prefix.hasAVariable.variable=<value>
In properties file:-
my.app.pob.pid=10
my.app.pob.pname=PEN
my.app.pob.pcost=200
Product.java:-
@Getter
@Setter
@ToString
public class Product {
private Integer pid;
private String pname;
private Double pcost;
}
ObjectConfigPropsRunner.java:-
@Component
@Getter
@Setter
@ToString
@ConfigurationProperties(prefix = "my.app")
public class ObjectConfigPropsRunner implements CommandLineRunner {
// variable name must be same as defined in properties file
private Product pob; // HAS-A
@Override
public void run(String... args) throws Exception {
System.out.println(this);
}
}
Output:-
ObjectConfigPropsRunner(pob=Product(pid=10, pname=PEN, pcost=200.0))
Example:- Perform the following tasks:-
- Define one CommandLine Runner.
- Create variables for student (sid, sname, sfee, subjects:List<String>, grade).
- Read data from properties files using @ConfigurationProperties.
In application.properties:-
my.app.student.sid=11
my.app.student.sname=Jerry
my.app.student.sfee=1000
my.app.student.subjects[0]=Math
my.app.student.subjects[1]=English
my.app.student.subjects[2]=Science
my.app.student.grade=A
In Student.java:-
package com.knowprogram.demo;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class Student {
private Integer sid;
private String sname;
private Double sfee;
private List<String> subjects;
private String grade;
}
In Runner class:-
package com.knowprogram.demo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Component
@Getter
@Setter
@ToString
@ConfigurationProperties(prefix = "my.app")
public class ObjectConfigPropsRunner implements CommandLineRunner {
private Student student; // HAS-A
@Override
public void run(String... args) throws Exception {
System.out.println(this);
}
}
Output:-
ObjectConfigPropsRunner(student=Student(sid=11, sname=Jerry, sfee=1000.0, subjects=[Math, English, Science], grade=A))
If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!