Spring Boot 2.0 Projects

By Mohamed Shazin Sadakath
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Introduction

About this book

Spring Boot is a lightweight framework that provides a set of tools to create production-grade applications and services. Spring Boot 2.0 Projects is a comprehensive project-based guide for those who are new to Spring, that will get you up to speed with building real-world projects. Complete with clear step-by-step instructions, these easy-to-follow tutorials demonstrate best practices and key insights into building efficient applications with Spring Boot.

The book starts off by teaching you how to develop a web application using Spring Boot, followed by giving you an understanding of creating a Spring Boot-based simple blog management system that uses Elasticsearch as the data store. Next, you’ll build a RESTful web services application using Kotlin and the Spring WebFlux framework - a new framework that enables you to create reactive applications in a functional way. Toward the last few chapters, you will build a taxi-hailing API with reactive microservices using Spring Boot, in addition to developing a Twitter clone with the help of a Spring Boot backend. To build on your knowledge further, you’ll also learn how to construct an asynchronous email formatter.

By the end of this book, you’ll have a firm foundation in Spring programming and understand how to build powerful, engaging applications in Java using the Spring Boot framework.

Publication date:
July 2018
Publisher
Packt
Pages
336
ISBN
9781789136159

 

Introduction

This chapter will introduce the reader to Spring Boot and explain how it stands out from other competing frameworks. It will begin by explaining how to get started developing applications using Spring Boot. Also, it will explain about Spring Boot 1.x and the improvements introduced in Spring Boot 2.0. Furthermore, it will walk through the most noticeable features and/or improvements of Spring Boot 2.0. Continuing on, it will explain progress with Spring Boot 2.0 and supply tips on migration from the older versions to Spring Boot 2.0.

This chapter covers the following topics:

  • Understanding Spring Boot
  • Generating Spring Boot Projects
  • Getting started with Spring Boot
  • Changes since Spring Boot 1.x
  • The next milestone
  • Migration
 

Technical requirements

Technical requirements for this chapter are as follows:

 

Generating Spring Boot Projects

In this book, we will be using http://start.spring.io, which is a convenient tool for generating Spring Projects with the required dependencies to get started. This tool supports multiple Spring Boot versions, programming languages (Java, Groovy, Kotlin), project types (Maven, Gradle), and dependencies. Learning to use this tool will help readers to get started quickly with Spring Projects. The following is a screenshot of the tool to help us get familiarized with it:

This tool allows the selection of a Project type (Maven Project, Gradle Project), programming language (Java, Groovy, Kotlin), Spring Boot version (2.0.*, 1.5.*), project artifact group, artifact name, and project dependencies. After selecting the correct options, click on Generate Project will download a ZIP file of the project.

The ZIP file needs to be extracted first before being used. The extracted ZIP file will have the following structure:

<Project Name>/
├── src/
├── pom.xml
├── mvnw
└── mvnw.bat

Opening the generated project with IntelliJ

To open the generated project with IntelliJ, we perform the following steps:

  1. Open IntelliJ IDE.
  2. Select File | Open from the menu bar as shown in the following screenshot:
  1. Navigate to the location where the extracted project is and click on OK after selecting the project, shown as follows:
  1. The IDE will show the opened project.

Opening the generated project with STS

To open the generated project the Spring Tool Suite, we perform the following steps:

  1. Open STS.
  2. Select File | Open Projects from File System... from the menu bar, as shown in the following screenshot:
  1. From the dialog box that launched, click on the Directory... button:
  1. Navigate to the extracted project location and Click on OK after selecting the project:
  1. Finally, click on Finish on the import projects dialog box.
  2. The IDE will show the opened project.

The source code for this chapter can be found at https://github.com/PacktPublishing/Spring-Boot-2.0-Projects-Fundamentals-of-Spring-Boot-2.0, in the Chapter01 directory.

 

Getting started with Spring Boot

This section will enable readers to get started with Spring Boot by explaining its features in detail. Furthermore, it will help you get started with Spring Boot application development by explaining the bare-bones of a Spring Boot application. Furthermore, it will explain the Spring Framework ecosystem and how it can be used in the Spring Boot application to harness the power of time-tested, industry-standard databases, messaging systems, and so on.

Learning about Spring Boot

Spring Boot is an application development framework for the Java virtual machine (JVM) that enables users to write stand-alone, production-grade, flexible, and extensible Spring-based applications with minimum code and configurations. This follows the Rapid application development (RAD) paradigm where the focus is on writing business logic that matters. With the introduction of cloud-based hosting services and microservice architectures, Spring Boot has been further elevated into a must-know technology platform. The following are some of its features:

  • Standalone: A Spring Boot application is self-contained and easily deployable. It can start with its own embedded Tomcat, Jetty, Undertow web container, or as a console application from a just standard file such as Java Archive (JAR) or Web Archive (WAR). An example of this would be an application that has spring-boot-starter-web as a dependency, which when run will by default inside an embedded Tomcat web container.
  • Production-grade: A Spring Boot application enables most of the features required for production, such as monitoring, connection pools, externalized configurations, and so on, out of the box, and ships with industry-standard, time-tested, and proven third-party applications such as Tomcat.
  • Flexible: A Spring Boot application will have most of its settings auto-configured with default settings based on the dependencies available in the classpath of the application. But the auto-configuration will step back whenever a custom configuration is made. An example for this would be when a Spring Boot application finds a MySQL JDBC driver in the classpath; it auto-configures DataSource, which connects to the host localhost and port 3306, as those will be the settings for a MySQL Server with a default installation.
  • Extensible: A Spring Boot application will have most core functionalities implemented out of the box, but also has a lot of Service Provider Interfaces (SPI), which are used by third-party developers to implement or modify functionality. An example of this would be when a requirement arises for a custom endpoint in Spring Boot Actuator; extending and overriding the AbstractEndpoint.invoke method in a Spring Bean will expose it as a new endpoint under Spring Boot Actuator.

Spring Boot does not do any code generation and does not require any XML files to be configured in order to run. Spring Boot is ideal for on-premise and cloud-based deployments with a quick boot-up time and a good memory footprint. The uniqueness of Spring Boot comes from its ecosystem of Spring modules, which covers security, data persistence, batch processing, and so on and from the highly active, competent community of developers who keep on improving the Spring Boot Framework.

Anatomy of a Spring Boot application

The anatomy of a Spring Boot application will be that it will be inheriting from a spring-boot-starter-parent project that will in return have all the common dependencies available for a Spring Boot application. Apart from this, there will be one or more spring-boot-starter POM such as spring-boot-starter-web, spring-boot-starter-jpa, and so on. The following example excerpt from pom.xml shows the basic dependencies of a Spring Boot application:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
...
</dependencies>

The minimum bootstrapping point of a Spring Boot application will be a class with a main method that will be annotated with a @SpringBootApplication annotation along with the main method body, which calls the SpringApplication.run static method, for which a configuration class (a class with @Configuration annotation—the @SpringBootApplication annotation transitively has one) needs to be passed, along with a String array of arguments. The following code shows the minimum bootstrapping point of a Spring Boot application:

import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class SpringBootIntroApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBootIntroApplication.class, args);
}

@Bean
public ApplicationRunner applicationRunner() {
return args -> {
System.out.println("Hello, World!");
};
}
}

By running the preceding class, a Spring Boot application can be provisioned and executed. There are several ways to run a Spring Boot application; some of them are mentioned here:

  • Running the Spring Boot application main class using an IDE.
  • Building a JAR or WAR file using the following Maven command and then running:
$ mvn clean install
$ java -jar target/<package-name>.[jar|war]
  • Run this using the Spring Boot Maven plugin:
$ mvn clean spring-boot:run

The @SpringBootApplication annotation comprises of @EnableAutoConfiguration and @ComponentScan annotations that do the heavy lifting of auto-configuring the Spring Boot application with the default settings and scanning the packages for any Spring-specific components such as services, components, repositories, and so on.

Supporting the Spring Framework ecosystem in Spring Boot

What made the Spring Boot application development framework stand out from other competing alternatives is the fact that it has a lot of supporting frameworks for easing development, with starter dependencies that cover industry-standard, enterprise-grade methodologies and tools such as Web MVC, JPA, MongoDB, Elasticsearch, Redis, and many more.

This makes Spring Boot a unique solution for day-to-day programming needs. By including a starter dependency, a Spring Boot application will have all the necessary dependencies and auto-configurations included in the application without any developer intervention.

This makes the life of a developer easy and enables us to focus on the business logic of the application instead of configurations and dependency management. At the time of writing, there are more than thirty of these starters available to be used in a Spring Boot application. The complete list can be found at https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters.

Spring Boot is a powerful framework as it has a very gradual learning curve and is built on the basis of the ability to write applications that just run with minimal effort. Having said that, Spring Boot should not be mistaken for a silver-bullet solution for all problems. In the areas of memory utilization, optimization, latency reduction, and many more, work may be needed, so developer commitment and effort are still required. But all in all, Spring Boot can be considered as a very good solution as it enables users to develop a minimum viable product (MVP) that is production-ready within maybe a couple of days or hours.

 

Changes since Spring Boot 1.x

The last released version of Spring Boot 1.x was 1.5.10.RELEASE, after which Spring Boot 2.0 was released in early 2018. As Spring Boot 2.0 is a major release it has JVM level, platform level, application programming interface (API) level, and dependencies level changes, which must be taken into account when developing applications with Spring Boot 2.0.

The major changes from Spring Boot 1.x to Spring Boot 2.0 are listed as follows:

  • Java 8 is the baseline and Java 9 is supported: This means the minimum JVM version on which a Spring Boot 2.0 application can be run is now Java 8 because the framework is modified to use many features introduced in Java 8. Furthermore, Spring Boot 2.0 is fully supported to run on Java 9, which means all the dependency JARs shipped will have module descriptors to support the Java 9 module system.
  • Third-party libraries upgraded: Spring Boot 2.0 requires Spring Framework 5.0 along with Tomcat 8.5, Flyway 5, Hibernate 5.2, and Thymeleaf 3.
  • Reactive Spring supported: Supports the development of functional, non-blocking, and asynchronous applications out of the box. Reactive Spring will be explained and used extensively in upcoming chapters.
  • Micrometer Framework introduced for metrics: Uses Micrometer instead of its own API for metrics. A micrometer is a third-party framework that allows dimensional metrics.
  • Spring Boot Actuator changed: Spring Boot Actuator endpoints are now placed inside the context path /actuator instead of being mapped directly to root, to avoid path collisions. Additionally, a new set of endpoint annotations have been introduced to write custom endpoints for Spring Boot Actuator.
  • Configuration property binding: Improved relaxed binding of properties, property origins, converter support, and a new Binder API.
  • Kotlin language supported: Supports Kotlin, a new concise and interoperable programming language introduced by IDEA. Kotlin will be explained in detail in Chapter 04, Introduction to Kotlin.
  • HikariCP shipped out of the box instead of Tomcat Connection Pool: HikariCP is the most efficient, high-performing database connection pool available for the JVM and it is shipped by default with Spring Boot 2.0.
  • A new way to dynamically register Spring Bean with ApplicationContextInitializer: Adds to previous methods of registering a Spring Bean by providing the means to define it in an XML file, annotate @Bean on a method that returns an object, annotate with @Component, @Service, @Repository annotations, and so on. Spring Framework 5 has introduced ApplicationContextInitializer, which can do dynamic registering.
  • HTTP/2 supports out of the box: HTTP/2 is the latest version of the widely used Hypertext Transfer Protocol (HTTP), which has a lot of performance gains when compared to older versions.
  • Newly added event ApplicationStartedEvent: An ApplicationStartedEvent will be sent right after the application context is refreshed but before any command line runners run. ApplicationReadyEvent will, however, be sent right after the application context is refreshed and any command-line runners run. This means the application is in a ready state to accept and process requests.

These are the most notable changes, but there are so many more, as with any major release. Other changes can be seen in the Spring Boot 2.0 release notes, found at https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes.

Let's have a look at some of the notable features of Spring Boot 2.0 with some hands-on examples.

Registering a Spring Bean using ApplicationContextInitializer

Spring Boot allows Builder to create customized Spring Boot application bootstrapping with a tool called SpringApplicationBuilder. This can be used as follows to customize the Spring Boot application and register a Spring Bean dynamically:

public static void main(String[] args) {
new SpringApplicationBuilder(SpringBoot2IntroApplication.class)
.bannerMode(Banner.Mode.OFF)
.initializers((GenericApplicationContext
genericApplicationContext) -> {
genericApplicationContext.registerBean
("internet",
InternetHealthIndicator.class);
})

         .run(args);
}

In this code, a new instance of SpringApplicationBuilder is instantiated with a configuration class. By invoking the bannerMode(Banner.Mode.OFF) method, the banner shown in the console at the Spring Boot Bootstrap is switched off.

By invoking the initializers() method with a lambda function (learn about lambda functions in the reference documentation at https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) for ApplicationContextInitializer, the GenericApplicationContext.registerBean method is used to register a Spring Bean called internet and with class type InternetHealthIndicator.

Configuration property binding

Configuration properties are a great feature of Spring Boot for reading properties with type safety. This section will explain the concept with the following DemoApplicationProperties class file:

@ConfigurationProperties(prefix = "demo")
public class DemoApplicationProperties {

private Integer number;

private String username;

private String telephoneNumber;

private List<String> emailAddresses =
Arrays.asList("[email protected]");

private String firstName;

private String lastName;

private Duration workingTime;

// Getters and Setters
}

The application.yml has the following configuration properties:

demo:
number: 10
user-Name: shazin
firstName: Shazin
lAsTNamE: Sadakath
telephone_number: "0094777329939"
workingTime: 8h
EMAILADDRESSES:
- [email protected]
- [email protected]
addresses:
- number: "B 22 2/3"
city: Colombo
street: "Ramya Place"
country: "Sri Lanka"
zipCode: "01000"
- number: "123"
city: Kandy
street: "Dalada Weediya"
country: "Sri Lanka"
zipCode: "01332"

For configuration properties, an application.properties file also can be used over an application.yml file. Lately, YML files are becoming famous among developers because they can provide a structure with indentations, the ability to use collections, and so on. Spring Boot supports both at the moment.

New property binding API

Spring Boot 2.0 introduces a new binding API for configuration properties. The most notable change in Spring Boot 2.0 related to configuration property binding is the introduction of a new binding API with the following Address Plain Old Java Object (POJO):

public class Address {
private String number;
private String street;
private String city;
private String country;
private String zipCode;
// Getters, Setters, Equals, Hashcode
}

The following Binder fluent API can be used to map properties directly into the Address POJO.

This code can be written inside any initializing code such as CommandLineRunner, ApplicationRunner, and so on. In the application this code is available inside the SpringBoot2IntroApplication.runner method:

List<Address> addresses = Binder.get(environment)
.bind("demo.addresses", Bindable.listOf(Address.class))
.orElseThrow(IllegalStateException::new);

The preceding code will create a Binder instance from the given Environment instance and bind the property for a list of Address classes. If it fails to bind the property then it will throw IllegalStateException.

Property origin

Another notable addition to configuration property binding is exposing the origins of a property. This is a useful feature because many developers have struggled in the past because they had configured the wrong file and ran an application to just see unexpected results. Now, the origin of a property is shown along with the file, line number, and column number:

"demo.user-Name": {  
"value":"shazin",
"origin":"class path resource [application.yml]:5:14"
}

Tightened rules for governing relaxed property binding

Relaxed property binding rules have the following changes:

  1. Kebab-case format (lower-case, hyphen-separated) must be used for prefixes. Examples of this are demo and demo-config.
  2. Property names can use kebab-case, camel-case, or snake-case. Examples of this are user-Name, firstName, and telephone_number.
  3. The upper case underscore format that is usually used for environment variables should be followed, where the underscore should only be used to separate parts of the key. The upper case underscore format is usually used for environment variables. The underscore is used to separate parts of the key. An example of this would be DEMO_ENV_1.

The complete set of rules for relaxed bindings can be seen in the Spring Boot documentation at https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-relaxed-binding.

Environment variables with indices

Furthermore, environment variables with indices can be mapped to names with array syntax and indices, shown as follows:

DEMO_ENV_1 = demo.env[1]
DEMO_ENV_1_2 = demo.env[1][2]

So, the DEMO_ENV_1 environment variable can be read in the application as follows:

System.out.printf("Demo Env 1 : %s\n", environment.getProperty("demo.env[1]"));

Direct binding of property type java.time.Duration in the ISO-8601 form

Another notable change is the ability to specify time duration in days (d), hours (h), minutes (m), seconds (s), milliseconds (ms), and nanoseconds (ns), which will be correctly mapped to a java.time.Duration object in the configuration property. In the example workingTime: 8h, the property will be mapped to the java.time.Duration workingTime property correctly. Values such as 8m, 8s, 8d can also be specified to define duration.

Custom endpoints for Spring Boot Actuator using annotations

In Spring Boot 1.x, in order to write a custom endpoint for Spring Boot Actuator, AbstractEndpoint had to be extended and its invoke method has been overridden with custom logic. Spring Boot Actuator is a production-ready feature for monitoring and managing a Spring Boot application using HTTP endpoints or JMX. Auditing metrics such as health could also be gathered using this feature. Finally, it had to be injected into the Spring Context as a Bean. This endpoint was technologically agnostic, in the sense that it could be invoked using JMX as well as with web requests.

If a custom behavior was required for a particular technology, such as JMX or the web, then AbstractEndpointMvcAdapter or EndpointMBean had to be extended respectively and had to be injected as a Spring Bean. This is cumbersome, and Spring Boot 2.0 has introduced technology-specific annotations such as @Endpoint, @WebEndpoint, and @JmxEndpoint; technology-independent operation annotations such as @ReadOperation, @WriteOperation, and @DeleteOperation; and technology-specific extension annotations such as @EndpointWebExtension and @EndpointJmxExtension, to ease this process.

By default, only the /info and /health endpoints are exposed. The management.endpoints.web.exposure.include=* property must be set to expose other endpoints, including custom ones.

Exposing a custom Spring Boot Actuator endpoint

The @ReadOperation annotation will expose the Getter for the custom endpoint and the @WriteOperation will expose the Setter for the custom endpoint. The endpoint will be mapped under the http://<host>:<port>/actuator/custom URL (the default host is localhost, and the default port is 8080 unless configured otherwise) and also exposed as a JMX Management bean:

@Component
@Endpoint(id = "custom")
public class CustomEndpoint {

private final static Logger LOGGER =
LoggerFactory.getLogger(CustomEndpoint.class);

@ReadOperation
public String get() {
return "Custom Endpoint";
}

@WriteOperation
public void set(String message) {
LOGGER.info("Custom Endpoint Message {}", message);
}
}

Extending a custom endpoint with a specialized implementation for the web

The following extension class, which uses @EndpointWebExtension to extend CustomEndpoint for custom behavior for web technology and for JMX technology, will not be changed:

@Component
@EndpointWebExtension(endpoint = CustomEndpoint.class)
public class CustomEndpointWebExtension {
...

@ReadOperation
public WebEndpointResponse<String> getWeb() {
...
return new WebEndpointResponse<>("Custom Web
Extension Hello, World!"
, 200);
}
}

The @EndpointWebExtension annotation will make the CustomEndpointWebExtension a web extension for CustomEndpoint with its endpoint property. The method with the @ReadOperation annotation will be the overridden Getter. Accessing http://<host>:<port>/actuator/custom (the default host is localhost, and the default port is 8080 unless configured otherwise) and a URL using a browser will prompt for the username (specify sysuser) and password (specify password) and when logged in will return the following:

Custom Web Extension Hello, World!

Connecting to a custom endpoint using monitoring and management tools

Running the Spring Boot application with the following VM arguments will enable it to be connected using jconsole remotely, and the exposed CustomEndpoint JMX Bean can be accessed using monitoring and management tools such as jconsole, which is shipped with the JDK installation:

-Djavax.management.builder.initial=      
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8855
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Run jconsole with the following command:

$ jconsole

Making a remote process connected with it to <host>:8855 will list all the MBeans from the Spring Boot application under MBeans tab. When the Custom.get operation is executed from jconsole it will show the return from CustomEndpoint.get as expected, as shown in the following screenshot:

Custom metrics using Micrometer

With the introduction of Micrometer to Spring Boot Actuator in Spring Boot 2.0, metrics can be customized easily. The following code snippet from CustomEndpointWebExtension shows how to make use of io.micrometer.core.instrument.MeterRegistry to maintain a counter with the name custom.endpoint.calls, which will be incremented every time CustomEndpointWebExtension is invoked:

public static final String CUSTOM_ENDPOINT_CALLS = "custom.endpoint.calls";

private final MeterRegistry meterRegistry;

public CustomEndpointWebExtension(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}

@ReadOperation
public WebEndpointResponse<String> getWeb() {
meterRegistry.counter(CUSTOM_ENDPOINT_CALLS).increment();
return new WebEndpointResponse<>("Custom Web Extension Hello, World!", 200);
}

The preceding code injects MeterRegistry from the Micrometer Framework, which is used to create and retrieve a counter named custom.endpoint.calls and increment it during each read operation of the custom web endpoint extension.

This metric will be available under the http://<host>:<port>/actuator/metrics/custom.endpoint.calls URL, which will show a result similar to the following:

{  
"name":"custom.endpoint.calls",
"measurements":[
{
"statistic":"COUNT",
"value":3.0
}
],
"availableTags":[ ]
}

Custom health indicator

Spring Boot Actuator's health endpoint is really helpful for checking the status of Spring Boot application and dependent systems such as databases, message queues, and so on. Spring Boot ships out of the box with many standard HealthIndicator implementations such as DiskSpaceHealthIndicator, DataSourceHealthIndicator, and MailHealthIndicator, which can all be used in Spring Boot applications with Spring Boot Actuator. Furthermore, custom health indicators can also be implemented if required:

public class InternetHealthIndicator implements HealthIndicator {

private static final Logger LOGGER = LoggerFactory.getLogger(InternetHealthIndicator.class);

public static final String UNIVERAL_INTERNET_CONNECTIVITY_CHECKING_URL = "https://www.google.com";

private final RestTemplate restTemplate;

public InternetHealthIndicator(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}

@Override
public Health health() {
try {
ResponseEntity<String> response = restTemplate.getForEntity(UNIVERAL_INTERNET_CONNECTIVITY_CHECKING_URL, String.class);
LOGGER.info("Internet Health Response Code {}",
response.getStatusCode());
if (response.getStatusCode().is2xxSuccessful()) {
return Health.up().build();
}
} catch (Exception e) {
LOGGER.error("Error occurred while checking
internet connectivity"
, e);
return Health.down(e).build();
}

return Health.down().build();
}
}

The preceding InternetHealthIndicator is intended to show the status of internet connectivity from within Spring Boot applications to the outside world. It will send a request to www.google.com to check whether it sends a successful HTTP response code, and based on that the health status of this indicator will be set to up or down. This was injected as a Spring Bean using an ApplicationContextInitializer earlier. Invoking the http://<host>:<port>/actuator/health URL will return the internet status as in the following:

{  
"status":"UP",
"details":{
"internet":{
"status":"UP"
},
"diskSpace":{
"status":"UP",
"details":{
"total":399268376576,
"free":232285409280,
"threshold":10485760
}
}
}
}

Using the HTTP/2 protocol

HTTP was invented by Tim Berners-Lee in 1989 while he was working at CERN. It was designed as a way to share scientific findings among coworkers and is almost three decades old. When HTTP was invented, it was never intended to be the backbone of today's low-latency, high-traffic web, used by millions if not billions of people. So HTTP 1-and HTTP 1.1-based web applications had to have a lot of workarounds to cater to the high demands of the modern web. The following are some of those workarounds:

  • Concurrent resources are download by the browser since HTTP 1.x can download only one resource at a time, and Domain Sharding is used to tackle limitations on the maximum number of connections per domain
  • Combining multiple resources such as CSS/Javascript files together with complex server-side logic and downloading them all in one go
  • Multiple image sprites in a single resource to reduce the number of image file downloads
  • Inlining static resources in an HTML file itself

But HTTP/2 is designed from the ground up to tackle these pain points. Compared to HTTP 1.x, HTTP/2 doesn't use text to communicate between the client and server. It uses binary data frames, which makes it much more efficient and reduces the text-to-binary and binary-to-text conversion overhead in the servers. Furthermore, it has the following features introduced:

  • HTTP/2 multiplexing: This multiplexing feature allows opening one connection to a server and downloading multiple resources using that connection:
  • HTTP/2 push: This will send resources to clients even before resources are requested:

  • HTTP/2 header compression: Eliminates the repeating of the same headers across multiple requests by maintaining an HTTP header table, thus reducing request bandwidth

Spring Boot 2 supports HTTP/2 out of the box for server Undertow, and, with minor dependencies at https://docs.spring.io/spring-boot/docs/2.0.x-SNAPSHOT/reference/htmlsingle/#howto-configure-http2, also supports Tomcat and Jetty servers. But Spring Boot 2 doesn't support the clear text version of HTTP/2, so Secure Socket Layer (SSL) is a must. It requires the following dependencies in pom.xml :

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
...
</dependencies>

The configuration properties in application.yml configure both SSL and HTTP/2:

 server:
port: 8443
ssl:
key-store: keystore.p12
key-store-password: sslcert123
keyStoreType: PKCS12
keyAlias: sslcert

http2:
enabled: true

In this configuration SSL key-store, key-store-password, keyStoreType, and keyAlias are configured along with the port for HTTPs. The key was generated using keytool, which is a utility shipped with the JDK release with the following command, and fills in the necessary details when prompted by the utility tool:

$ keytool -genkey -alias sslcert -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
This key-store is not recommended for production as it is not generated by a Trusted Certificate Authority. A proper SSL Certificate must be used in production.

Now when the https://<localhost>:8443/actuator/custom URL is accessed it will be served over HTTP/2.

Securing applications with Spring Security

Spring Boot 2.0 has introduced updated support for Spring Security with Spring Framework 5.0 and Reactive support for Spring Security, providing simplified default configurations and ease of customization for Spring Security. As opposed to having multiple auto-configurations for Spring Security, Spring Boot 2.0 has introduced a single behavior that can be overridden easily and can be customized easily with a WebSecurityConfigurerAdapter such as the following:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and()
.authorizeRequests()
.requestMatchers(EndpointRequest.to("info", "health")).permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("SYSTEM")
.antMatchers("/**").hasRole("USER");

}

@Override
protected void configure(AuthenticationManagerBuilder
auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(new
MessageDigestPasswordEncoder("SHA-256"))
.withUser("user")
.password("5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8")
.roles("USER")
.and()
.withUser("sysuser")
.password("5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8")
.roles("SYSTEM");
}

}

One thing to note here is the introduction of the EndpointRequest helper class, which makes it easier to protect endpoints.

 

The next milestone

Spring Boot is a highly active project with contributors from all around the World. At the time of writing, the Spring Boot 2.1.0 milestone is set and is under active development. The following are some of the features proposed for that Spring Boot minor-version release:

  • Support for embedding Tomcat 9: Tomcat 9 has introduced a lot of features, but Spring Boot 2.0 still only supports up to Tomcat 8 by default. With this support, Spring Boot 2.0 will be able to offer features such as Servlet 4.0 API, JSP 2.4, WebSocket 2.0, and so on.
  • Auto-configuration of JettyMetrics: Micrometer has metrics support for Jetty, which is planned to be included in the next release of Spring Boot 2.0.
  • Support for embedding Undertow 2.0: Undertow 2.0 has a lot of features, such as Servlet 4.0, but is not yet supported by Spring Boot 2.0.
  • Support for Hibernate 5.3.0 and JPA 2.2: Hibernate 5.3.0 and JPA 2.2 are the latest releases for the persistence layer, which needs to be incorporated into Spring Boot 2.0.
  • Actuator endpoint for listing and clearing cache: The actuator endpoint is intended to return caches per context and provides a delete operation to clear the cache.
  • Allowing @ConfigurationProperties binding on interfaces: At the moment only a class can be used to bind properties from a configuration properties file with a @ConfigurationProperties annotation. This feature will allow interfaces with methods with property names to be mapped to their corresponding property.
  • Having consistent auto-configuration behavior for default connection of data sources: Currently, behavior for default connection auto-configurations differs from data sources as such as MongoDB, Couchbase, and so on. This proposed change will make it consistent.

However, these enhancements and features are still under active evaluation and debate and can be further improved or reduced based on the collective decisions of the Spring Boot developer community.

 

Migration

Spring Boot 2.0 is a major release; it will require care when migrating from Spring Boot 1.x, as a lot has changed. Migration is unavoidable, as existing applications require the use of new features and enhancements available in the latest Spring Boot 2.0 release. The official migration guide can be read at https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide and in this section, the most notable migration tips will be discussed.

Using the correct JDK and JVM

Spring Boot 2.0 doesn't support Java 6 or Java 7, which are still widely used in many production environments. So the first thing that needs to be done is to upgrade both development environments and runtime environments to at least Java 8 or above.

Running on Java 9

Since Java 9 was a major release and has one of the most complex enhancement modifications made to Java since its inception (the modular system), special care needs to be taken when running the Spring Boot 2.0 application on it. The following tips will help you get started.

Tackling JAXBException

The following exception can be expected as soon as a Spring Boot 2.0 application is run on Java 9:

java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

This is because Hibernate requires JAXB, which is not shipped by default in Java 9. The following dependency needs to be added in pom.xml to include it:

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>

Instead, you can add the java.xml.bind module to Java 9 directly to get rid of this exception.

Using the correct AspectJ version

Java 9 requires AspectJ version 1.9 (currently in Release Candidate version) if JDK weaving of classes is required. Spring Boot 2.0, however, can work with the lower version 1.8 that is shipped by default.

Being aware of limitations on Apache Cassandra drivers

Apache Cassandra drivers that run on Spring Boot 2.0 are not fully supported by Java 9 at the time of writing this book, so if a Spring Boot 2.0 application uses these then it must be properly tested. The issue can be followed at https://github.com/spring-projects/spring-boot/issues/10453 for more updates.

Being aware of issues with the Maven Surefire Plugin

Maven Surefire Plugin version 2.20.1 has re-introduced a bug that was fixed on other Java versions and only raised when running tests on Java 9. In order to fix this, the Maven Surefire Plugin has to be downgraded to 2.20.0 or the java.se.ee module needs to be excluded from the runtime while running tests.

Using the upgraded Spring Framework 5.0

Spring Boot 2.0 by default uses and supports Spring Framework 5.0. Thus, any change to it will affect migration to Spring Boot 2.0. Some notable changes are explained in the following topics.

Modified CORS support behavior

The @CrossOrigin annotations property allowCredentials now has the default value false. This means that it needs to be explicitly set if cookies or authentication are required.

Removed packages, classes, and methods

The following packages, classes, and methods are no longer supported in the Spring Framework 5.0 release:

  • The beans.factory.access package, including the class SpringBeanAutowiringInterceptor.
  • The jdbc.support.nativejdbc package, which is replaced by JDBC 4 implementation.
  • The mock.staticmock package, with which AnnotationDrivenStaticEntityMockingControl is no longer supported.
  • The web.views.tiles2 package, with the minimum version requirement for tiles being version 3.
  • The orm.hibernate3/hibernate4 packages, with the minimum version requirement for Hibernate being version 5.
  • Most of the deprecated classes in the previous version have been removed.
  • Some methods in JSP Standard Tag Library (JSTL) have been removed. For example, FormTag commandName is no longer available.

Dropped support for frameworks

Spring Framework 5.0 no longer supports the following frameworks:

  • Google Guava
  • Velocity
  • XMLBeans
  • JDO
  • Portlet
  • JasperReports

Using the updated configuration properties

A lot of configuration properties have been renamed/replaced from Spring Boot 1.x to Spring Boot 2.0. So these changes must be incorporated in the application.yml/application.properties file to do a successful migration. To ease this process, Spring Boot has released the spring-boot-properties-migrator properties migrator, which can be used in the Maven configuration as follows:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-properties-migrator</artifactId>
        <scope>runtime</scope>
</dependency>

When this dependency is used, it will analyze the application environment, print out any diagnostics at startup, and even temporarily migrate properties at runtime.

This dependency is only required during migration and could/should be removed when the migration is complete.

Using the changed servlet-specific server properties

With the introduction of Reactive Web Programming out of the box in Spring Boot 2.0, there needs to be a differentiation between properties for a servlet stack and properties for a reactive stack, so that previous properties such as server.*, which was related to the server ServletContext path, is not changed to server.servlet.* , avoiding verbosity in property naming.

Using the modified template engine extension handling

In Spring Boot 2.0 the file extension for the mustache template engine has been changed from .html to .mustache. With the spring.mustache.suffix configuration property this behavior can be overridden if required.

Using the changed actuator configuration properties

The following changes have been introduced in the Spring Boot Actuator configuration properties in Spring Boot 2.0:

  • endpoints.* properties have been moved under management.*
  • management.* properties have been moved under management.server.*
  • endpoints.<id>.* properties have been moved under management.endpoint.<id>.*
  • Shutdown endpoint must be explicitly enabled by setting the management.endpoint.shutdown.enabled configuration property to true

These changes have the potential to break existing code, and so must be changed accordingly when migrating.

Using the changed actuator base path

Now, the /actuator path contains all Spring Boot Actuator-related endpoints. In order to get the previous version's behavior, the management.endpoints.web.base-path=/ configuration property needs to be set. Another change is the addition of a new purpose for management.server.servlet.context-path, which is the counterpart of server.servlet.context-path related to Spring Boot Actuator endpoints.

As an example, if management.server.servlet.context-path=/actuator is set, along with management.endpoints.web.base-path=/application, then the endpoints will be accessible under the /actuator/application/<endpoint> path.

Using the renamed actuator endpoints

The following Spring Boot Actuator endpoints have been changed:

  • /autoconfig has been renamed to /conditions
  • /trace has been renamed to /httptrace

Applications depending on these endpoints need to be changed to use the renamed endpoints.

Using the changed Embedded Container Configuration

EmbeddedServletContainer is changed to WebServer. Also, the org.springframework.boot.context.embedded package is refactored to org.springframework.boot.web.embedded. If TomcatEmbeddedServletContainerFactory was used to configure an embedded Tomcat with a custom port in an application as in the following, then it will need to be changed:

@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(9090);
tomcat.addAdditionalTomcatConnectors(connector);
return tomcat;
}

It must be changed to use TomcatServletWebServerFactory instead, as in the following:

@Bean
public TomcatServletWebServerFactory webServer() {
TomcatServletWebServerFactory tomcat = new
TomcatServletWebServerFactory(9090);
return tomcat;
}

Using the changed default behavior for path mapping

The default behavior of map extensions such as .json and .xml to existing controller request mappings has changed in Spring Boot 2.0. Consider the following URL mapping:

@GetMapping("/users")

If it is expected to cater to the /users.json URL in a Spring Boot 1.x application, then it won't be supported in Spring Boot 2.0. This means new mappings need to be added as necessary.

Using the changed default dispatcher types for the servlet filter

The default dispatcher type for the servlet filter in Spring Boot 2.0 is DispatcherType.REQUEST. This is changed to be in line with the default in the servlet specification. If other dispatcher types are required then a FilterRegistrationBean must be used to register the filter.

Using the modified transitive dependency to spring-boot-web-starter

Spring Boot 1.x had the transitive dependency spring-boot-starter-web whenever one of the following template engine starters was used:

  • spring-boot-starter-freemarker
  • spring-boot-starter-thymeleaf
  • spring-boot-starter-mustache

This was done because Spring Web MVC was running on top of the Servlet API, which is the only web application framework that was available at that time.

Now, with the introduction of the Spring Reactive Web starter spring-boot-starter-webflux, which is completely independent of the Servlet API, transitive dependencies from those template engine starters have been removed. This means that, when a template engine starter dependency is added, a developer needs to manually add a dependency to either Spring Web MVC starter or Spring Web Flux starter based on the requirement.

Using the changed default proxying strategy

Spring Boot 2.0 uses CGLIB as the default proxying strategy including for aspect-oriented programming (AOP). If proxy based proxying is required, the following configuration property needs to be set:

spring.aop.proxy-target-class=false.

Using the modified configuration location strategy

With Spring Boot 2.0, the spring.config.location configuration will no longer append to the list of configurations; instead, it will replace it. So, if append logic is required, then spring.config.additional-location must be used.

Using the changed Jackson/JSON support

With Spring Boot 2.0, Jackson's configuration was modified to write JSR-310 dates as ISO-8601 strings. For its previous behavior, the property spring.jackson.serialization.write-dates-as-timestamps=true needs to be set.

Using the changed Spring Boot Actuator security

The separate security auto-configuration for actuators has been removed in Spring Boot 2.0; thus, management.security.* properties are no longer supported. The endpoints.<id>.sensitive flag for each endpoint is no longer available, and if an application is dependent on this behavior then it must use a custom configuration for Spring Security to permit or restrict access to those endpoints.

Using the changed HikariCP default connection pool for JPA

With Spring Boot 2.0, the default connection pool for JPA has been changed from Tomcat to HikariCP. Thus it is no longer required to use the configuration property spring.datasource.type as an override to use HikariCP. Using the following dependency will by default use HikariCP:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Using the changed default database initialization strategy

With Spring Boot 2.0, the default basic DataSource initialization is only enabled for embedded databases and will be disabled as soon as a production database is used. The configuration property spring.datasource.initialization-mode (with values always or never), which replaces the old spring.datasource.initialize configuration property, can be used for more control.

Using the changed database schema creation strategy

The default behavior for embedded databases used with a schema manager such as Liquibase, Flyway, and so on will be dropping existing tables and creating a new one, which is similar to create-drop for the configuration property spring.jpa.hibernate.ddl-auto .If no schema manager is used then the default behavior is to do nothing, which is similar to setting none for the aforementioned configuration property.

Using the changed testing support

The following test annotations are no longer supported for Mockito 1.x:

  • @MockBean
  • @SpyBean

If testing needs to be done using the aforementioned annotations then Spring Boot 2.0 spring-boot-starter-test must be used or Mockito 2.x must be used explicitly.

Using the revised Spring Security

There are some Spring Security-related changes made for Spring Boot 2.0's release, which need to be incorporated when migrating. Some of the most notable ones are explained in the following sections.

Using the changed default security auto-configuration strategy

Spring Security has changed its auto-configuration strategy to make use of defaults in most cases instead of enabling multiple configuration options. Notable cases are when Spring Security authorization with content negotiation is used.

Spring Security OAuth2 is migrated to Spring Security core

The OAuth2 project is now part of the Spring Security core project and released out of the box. Thus dependencies for OAuth2 will not be maintained separately as of Spring Security 5.0. If a Spring Boot application makes use of a non-migrated feature then dependencies for those need to be added explicitly.

Using the AuthenticationManager bean

Exposing a custom AuthenticationManager bean can now be done with an overriding WebSecurityConfigurerAdapter.authenticationManagerBean method annotated with a @Bean annotation.

Understanding removed features

Some features that were available in Spring Boot 1.x but are no longer supported in Spring Boot 2.0 are as follows:

  • Disabled CRaSH support—Spring Boot 1.x had an integrated Java shell that was used to SSH and Telnet in a Spring Boot application. This is no longer available and the spring-boot-starter-remote-shell dependency can no longer provide support in monitoring and manage Spring Boot applications.
  • Removed auto-configuration support for Spring Mobile.
  • Removed auto-configuration support for Spring Social.
  • Removed dependency management support for commons-digester.
 

Summary

Congratulations on completing the first chapter. This chapter talked about what Spring Boot is, and explained its unique characteristics in depth by talking about Spring Boot's standalone, production-grade, flexible, and extensible capabilities in detail with examples.

Also, it talked about how to get started with Spring Boot application development by going through the anatomy of a Spring Boot application. It explained what makes a Spring Boot application different from a standard Maven Java application. Also, it talked about the ways a Spring Boot application can be run.

Next, it talked about what has changed from Spring Boot 1.x to Spring Boot 2.0, as it is a major version release, and how to successfully migrate from Spring Boot 1.x to Spring Boot 2.0 by going through each change and explaining how it affects an existing Spring Boot application. It also covered how to mitigate any adverse effects successfully without breaking the application.

Furthermore, it talked about what is in the pipeline for the next minor release of Spring Boot 2.0. These are enhancements that are proposed and discussed by the Spring Boot community, which they deem necessary for the next minor release. These features, along with more features, enhancements, and bug fixes, can be expected in the next minor release, Spring Boot 2.1.0.

This chapter has set the pace for coming chapters, which contain more exciting, hands-on Spring Boot 2.0 applications. The contents of this chapter will help greatly in upcoming chapters when it comes to understanding what makes a Spring Boot application work. This chapter also touched on different parts of the Spring Framework ecosystem such as Spring Security, Spring Data JPA, and so on, which will be covered in detail in coming chapters. This chapter has enabled us to write Spring Boot 2.0 applications that just run easily and effectively.

 

Questions

Please answer the following questions to see whether you have successfully mastered this chapter:

  1. What is Spring Boot?
  2. What is the bare minimum code to start a Spring Boot application?
  3. What is the minimum platform required to run a Spring Boot 2.0 application?
  4. What is HTTP/2?
  5. What is the default dispatcher type for a Spring Boot 2.0 servlet filter?
  6. What is the next minor release version of Spring Boot 2.0?
  7. What is the name of the default connection pool framework for a Spring Boot 2.0 application with the JPA starter?
 

Further reading

About the Author

  • Mohamed Shazin Sadakath

    Mohamed Shazin Sadakath is an experienced software engineer with over 9 years of software development experience in J2SE-, J2EE-, and Spring-based applications. He is a BSc (Hons) software engineering graduate, having achieved first class honors. He has worked in different domains, ranging from telecommunications to real estate. In his spare time, he contributes to open source projects, such as Spring Security, and writes technical articles for blogs. He is a Stack Overflow Moderator and loves answering Java-related questions.

    Browse publications by this author
Spring Boot 2.0 Projects
Unlock this book and the full library for FREE
Start free trial