The labs on this site need JavaScript to run. The same content is written out below.
Fundamentals › Spring
What is a configuration file, and how is it different from writing values in the code?
A configuration file is a text file kept separate from the code. In Spring Boot it is named application.properties, and you write "name=value" lines in it (shop.name=kim-shop). If you write values that differ between environments, such as a port number or a connection address, directly in the code, you have to change the code and compile it again every time a value changes. So you keep the value in this file, and the code writes only the name. If you write an @Value("${name}") line above a field that needs a value, then when Spring creates the object, it looks for the value of that name in the configuration file and puts it in the field. If you write a default value after a : in the form ${name:default}, that value is used when the settings have no such name. In this lab you change or delete the shop.name line of the configuration file, and add or remove a default value on @Value, and run the program with the java command, to see what value comes into the name field and whether the program starts properly.
Checked against real execution · Compiled the source for each of the six combinations on Spring Boot 4.1.1, ran it as a child java process, and checked against the standard output, exit code, and exception observed from outside the process
# application.properties
# Setting: a value written outside the code in the form name=value
shop.name=kim-shop
@Component
class ShopInfo {
// Receive: find the value of shop.name in the settings and put it in name
@Value("${shop.name}")
String name;
}
@SpringBootApplication
public class App {
public static void main(String[] args) {
// Start Spring. ctx is the place that keeps the objects Spring made
ApplicationContext ctx = SpringApplication.run(App.class, args);
ShopInfo info = ctx.getBean(ShopInfo.class);
System.out.println(info.name);
}
}
This is the result of running Spring Boot 4.1.1 (Spring Framework 7.0.9) on JDK 21.0.12.1. All six combinations were checked by compiling a source with the same structure as the code on the screen (ShopInfo and App in the package app, and application.properties in the same folder as the class files), running app.App from its main method as a new process with the java command, and comparing the results. What was checked is the three items of the result table. The value that came into name was decided from the text the process printed to the standard output, whether the startup succeeded from the exit code (0 and 1) and the standard output, and the error from the name and message of the exception on the standard error. In the combinations where the configuration file is deleted, only the shop.name line and the note line right above it were removed from the file, and the # application.properties line at the top was left. The facts that the step sentences rely on were also checked by execution. In the combinations with a configuration file, Spring reads application.properties on the class path as a source of settings (Config resource class path resource [application.properties]) and the shop.name value in it is in the Spring Environment. When SpringApplication.run ends, the ShopInfo object has already been made and the name field holds the value. Our source has no new ShopInfo() and no line that puts a value in name. When there is no shop.name line and no default value, an exception (BeanCreationException, whose cause is a PlaceholderResolutionException with Could not resolve placeholder 'shop.name' in value "${shop.name}") comes out of the SpringApplication.run line, main cannot go on to the next line and ends with exit code 1, and nothing is printed to the standard output. When only application.properties is changed from kim-shop to lee-shop and the program is run again from the same compile result (the hashes of the ShopInfo.class file and the App.class file are the same), lee-shop comes out without compiling. In the combination where the shop.name line is deleted and a default value is written, the file has no name=value line at all, and it was observed that application.properties does not appear in the list of setting sources of Spring. The step sentence says only as far as "the settings list does not have the name shop.name". For the class path, only the 21 jars that spring-boot-starter brings in were given, not the whole library folder (the same list as the Spring Boot Fundamentals lab, with no web library), and the working folder of the child process was an empty temporary folder (because Spring Boot also reads application.properties and the config folder in the working folder). The environment variables starting with SPRING_ and SHOP_ were removed from the child process. What the documentation defines comes from the section Externalized Configuration of the Spring Boot documentation (that when it starts, it finds and reads application.properties at the root of the class path, in the /config package of the class path, in the current folder, and in the config folder of the current folder; that settings are kept outside the code so that the same code can be used in different environments; and that in ${name:default}, what follows the : is the default value) and the section Using @Value of the Spring Framework documentation (that @Value("${...}") injects an external setting value; the default value syntax; that Spring Boot registers by default the PropertySourcesPlaceholderConfigurer that reads the values of application.properties; and that when this configurer is present, initialization fails if a ${} placeholder cannot be resolved). The documentation also says that if you use only Spring Framework and do not put this configurer in, the unresolved ${shop.name} text goes in as the value as it is, but this lab was run only on Spring Boot. That BeanCreationException and PlaceholderResolutionException come out when the value is missing is not defined by the documentation but is a behavior observed on this version. The code on the screen leaves out the package and import lines and assumes that ShopInfo and App are in the same package. In reality the two classes are in separate files, and application.properties is usually put in src/main/resources and copied next to the class files by the build (here it was put in that folder directly). What this lab does not cover is application.yml, the precedence when the same name is in several places, changing values with environment variables and run arguments, files for each profile, and @ConfigurationProperties. The precedence is covered in the in-depth lab "Configuration precedence", and Spring Boot making beans by itself after looking at the settings is covered in the in-depth lab "Spring Boot auto-configuration".
Previous lab: Controllers · Next lab: JDBC
Struck-through text was removed from the first version of the code; highlighted text was added.