(This post has been updated at blog.hcf.dev with a later version of Spring Boot.)
This series of articles will examine Spring Boot features. This first article will look at the minimum Spring Boot application, Spring Boot Devtools, and the Spring Boot Actuator. There are already a wealth of resources for Spring Boot including the Spring Initializr; these articles do not intend to replace these resources but instead provide a collection of skeletal projects which may be quickly and easily used to experiment with specific Spring Boot features.
Complete source code for the series and for this part are available on Github.
Minimum Web Server Project
The minimum web server project consists of a Maven POM, a "Launcher" class with static main
function, and an applications.properties
file. The web server will be launched from Maven by invoking the spring-boot:run
plug-in.
The minimum POM for the server is:
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ball</groupId>
<artifactId>spring-boot-web-server</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.0.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies verbose="true">
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
This POM:
Specifies the parent POM as
org.springframework.boot:spring-boot-dependencies
,1Sets the
${project.build.sourceEncoding}
property toUTF-8
avoid Maven warnings,Specifies the one required Spring Boot dependency,
org.springframework.boot:spring-boot-starter-web
, and,Provides the
org.projectlombok:lombok
artifact
The last is not strictly required but it saves on writing the Java "boilerplate" required by the implementation beans.
A static, annotated main
function must be provided:
package application;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@NoArgsConstructor @ToString @Log4j2
public class Launcher {
public static void main(String[] argv) throws Exception {
SpringApplication application = new SpringApplication(Launcher.class);
application.run(argv);
}
}
And an empty ${project.basedir}/src/main/resources/application.properties
:
# application.properties
Executing mvn -B spring-boot:run
in the project directory gives the log output:
which indicates Tomcat has been started listening on port 8080. (Note the ASCII-art banner and color in the log lines.) However, browsing to http://localhost:8080/ shows:
This is to be expected! This project has not yet defined any content (static or dynamic) to be served.2
Spring Boot Devtools
The org.springframework.boot:spring-boot-devtools
artifact may be added to the classpath to provide developer tools. There are a number of features documented at docs.spring.io including automatic restart and live reload but this article will examine features for setting application properties in a development environment.
The changes to the POM are encapsulated in the spring-boot:run
<profile/>
:
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>spring-boot:run</id>
<properties>
<maven.source.skip>true</maven.source.skip>
<maven.javadoc.skip>true</maven.javadoc.skip>
<maven.test.skip>true</maven.test.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean spring-boot:run</defaultGoal>
</build>
</profile>
</profiles>
...
</project>
This profile:
Sets Maven properties to skip source generation, javadoc generation, and running test.
Sets the Maven default goal(s) to "
clean
" and "spring-boot:run
".
The Spring Boot Reference Documentation Externalized Configuration section discusses in detail how, where, and when property values may be overridden. Notably ${user.home}/.config/spring-boot/spring-boot-devtools.properties
may be used to store a developer's default settings for all projects and ${project.basedir}/application.properties
(typically outside source control) may be used to store properties used for development such as database authentication details.
This author includes the following in his ${user.home}/.config/spring-boot/spring-boot-devtools.properties
to reduce log output during testing:
spring.main.banner-mode: OFF
spring.main.headless: false
spring.main.log-startup-info: false
spring.output.ansi.enabled: NEVER
and executing the application with devtools through the new profile (mvn -B -Pspring-boot:run
) gives the following shorter and less colorful output.
Spring Boot Actuator
The Spring Boot Actuator provides monitoring and management features. All that is required to enable it is to include its "starter" as a dependency which has been added to the spring-boot:run
<profile/>
:
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>spring-boot:run</id>
...
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<scope>runtime</scope>
</dependency>
...
</dependencies>
...
</profile>
</profiles>
...
</project>
The Spring Boot Actuator also needs to be configured by setting application properties (e.g., in ${user.home}/.config/spring-boot/spring-boot-devtools.properties
).
management.server.address: 127.0.0.1
management.server.port: 8081
management.endpoints.web.exposure.include: *
management.endpoints.enabled-by-default: true
management.endpoint.shutdown.enabled: true
Executing mvn -B -Pspring-boot:run
gives the following log output:
Which indicates Tomcat is listening on ports 8080 and 8081. http://localhost:8081/actuator returns the following JSON which lists the available endpoints:
{
"_links": {
"self": {
"href": "http://localhost:8081/actuator",
"templated": false
},
"beans": {
"href": "http://localhost:8081/actuator/beans",
"templated": false
},
"caches": {
"href": "http://localhost:8081/actuator/caches",
"templated": false
},
"caches-cache": {
"href": "http://localhost:8081/actuator/caches/{cache}",
"templated": true
},
"health": {
"href": "http://localhost:8081/actuator/health",
"templated": false
},
"health-path": {
"href": "http://localhost:8081/actuator/health/{*path}",
"templated": true
},
"info": {
"href": "http://localhost:8081/actuator/info",
"templated": false
},
"conditions": {
"href": "http://localhost:8081/actuator/conditions",
"templated": false
},
"shutdown": {
"href": "http://localhost:8081/actuator/shutdown",
"templated": false
},
"configprops": {
"href": "http://localhost:8081/actuator/configprops",
"templated": false
},
"env": {
"href": "http://localhost:8081/actuator/env",
"templated": false
},
"env-toMatch": {
"href": "http://localhost:8081/actuator/env/{toMatch}",
"templated": true
},
"loggers": {
"href": "http://localhost:8081/actuator/loggers",
"templated": false
},
"loggers-name": {
"href": "http://localhost:8081/actuator/loggers/{name}",
"templated": true
},
"heapdump": {
"href": "http://localhost:8081/actuator/heapdump",
"templated": false
},
"threaddump": {
"href": "http://localhost:8081/actuator/threaddump",
"templated": false
},
"metrics": {
"href": "http://localhost:8081/actuator/metrics",
"templated": false
},
"metrics-requiredMetricName": {
"href": "http://localhost:8081/actuator/metrics/{requiredMetricName}",
"templated": true
},
"scheduledtasks": {
"href": "http://localhost:8081/actuator/scheduledtasks",
"templated": false
},
"mappings": {
"href": "http://localhost:8081/actuator/mappings",
"templated": false
}
}
}
For example, http://localhost:8081/actuator/metrics returns:
{
"names": [
"jvm.memory.max",
"jvm.threads.states",
"process.files.max",
"jvm.gc.memory.promoted",
"system.load.average.1m",
"jvm.memory.used",
"jvm.gc.max.data.size",
"jvm.memory.committed",
"system.cpu.count",
"logback.events",
"jvm.buffer.memory.used",
"tomcat.sessions.created",
"jvm.threads.daemon",
"system.cpu.usage",
"jvm.gc.memory.allocated",
"tomcat.sessions.expired",
"jvm.threads.live",
"jvm.threads.peak",
"process.uptime",
"tomcat.sessions.rejected",
"process.cpu.usage",
"jvm.classes.loaded",
"jvm.classes.unloaded",
"tomcat.sessions.active.current",
"tomcat.sessions.alive.max",
"jvm.gc.live.data.size",
"process.files.open",
"jvm.buffer.count",
"jvm.buffer.total.capacity",
"tomcat.sessions.active.max",
"process.start.time"
]
}
And "process start time" can be retrieved through http://localhost:8081/actuator/metrics/process.start.time which returns something like:
{
"name": "process.start.time",
"description": "Start time of the process since unix epoch.",
"baseUnit": "seconds",
"measurements": [
{
"statistic": "VALUE",
"value": 1573860137.896
}
],
"availableTags": []
}
Spring Boot Properties Migrator
Spring Boot relies on numerous properties whose names may change from release to release. The spring-boot-properties-migrator
is configured in the spring-boot:run
<profile/>
:
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>spring-boot:run</id>
...
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
...
</dependencies>
...
</profile>
</profiles>
...
</project>
In the event that a property name changes it will be noted in the log output:
Summary
This article demonstrates the use of the spring-boot-starter-web
, the use of spring-boot-devtools
,3 and the integration of spring-boot-starter-actuator
. The POM defines a spring-boot:run
<profile/>
which can be used for testing the application. The projects described in subsequent articles in this series will benefit by having both Spring Boot Devtools and the Spring Boot Actuator activated during development runs of the application.
Part 2 of this series demonstrates how static resources may be added to be served by the web server.
[1] This author prefers this specific method if only because versions of provided dependencies may be updated simply by updating the corresponding property value in the project POM. ↩
[2] In fact, serving content is not covered here and will be the subject of subsequent articles in this series. ↩
[3] With spring-boot-properties-migrator
. ↩
Top comments (2)
This is a great resource. Thanks for writing it, Allen!
I am glad you like it -- thanks for the compliment!