Spring Boot Features:
Spring Boot makes creating and running Spring-based applications simple and
fast. Some of the key features are:
- Auto-Configuration: Spring Boot automatically sets up the beans and
settings required based on the dependencies and properties in your project.
For example, if you have Spring MVC on your classpath Spring Boot sets
up a web application with embedded Tomcat server SpringTemplateEngine and
other web-related beans. You can also change or turn off the
auto-configuration using annotations or properties.
- Dependency Management: Spring Boot offers a set of starter
dependencies that contain the common libraries and frameworks for different
types of applications.
For example, spring-boot-starter-web contains
Spring MVC Tomcat Jackson and other web-related dependencies. You can also
remove or modify the starter dependencies using Maven or Gradle.
- Starters: Spring Boot offers a number of starter projects that help
you quickly start a new application with the dependencies and configuration
you need. You can use Spring Initializr or Spring Tool Suite (STS) to
generate a starter project based on your preferences and needs.
For
example, you can select the web data security actuator and other starters
for your project.
- Actuator: Spring Boot offers a set of endpoints that show information
about the running application such as health metrics mappings beans env etc.
You can access these endpoints using HTTP or JMX. You can also customize or
extend the actuator endpoints using annotations or properties.
- Testing: Spring Boot makes testing your application easy using
various tools and frameworks such as JUnit TestNG Mockito etc.
You can use annotations like
@SpringBootTest
@WebMvcTest
@DataJpaTest etc.
To test different
parts and layers of your application. You can also use TestRestTemplate or
WebTestClient to test your web endpoints.
Let’s see how to use these
features in our example.
Auto-configuration
To show the auto-configuration feature of Spring Boot let’s make a simple web
application that returns a greeting message.
First, we need to add the spring-boot-starter-web dependency to our pom.xml
file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Next, we need to create a controller class that handles the HTTP requests:
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
@GetMapping("/")
public String hello() {
return "Hello, Spring Boot!";
}
}
Finally, we need to create an application class that runs our application:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
We use the @SpringBootApplication annotation on our application class. This
annotation makes Spring Boot do a lot of things for us automatically. It
imports the @EnableAutoConfiguration annotation, which tells Spring Boot to
configure everything based on our dependencies and properties. It also imports
the @ComponentScan and @EnableConfigurationProperties annotations, which
enable Spring Boot to scan for components and load configuration properties.
Now we can run our application and open the http://localhost:8080/ URL in our
browser. We should see a message that says “Hello, Spring Boot!”.
That’s all we need to do! We have built a web application with Spring Boot
without writing any XML configuration or setting up any web server. Spring
Boot has taken care of everything for us.
Adding more features
Let’s make our web application more interesting by adding some more features.
Let’s say we want to use Thymeleaf as our template engine and H2 as our
in-memory database.
First, we need to add two more dependencies to our pom.xml file:
spring-boot-starter-thymeleaf and spring-boot-starter-data-jpa. These
dependencies will bring in Thymeleaf and H2 along with other useful libraries.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Next, we need to create an entity class that represents a user in our
database:
package com.example.demo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String email;
// standard constructors / setters / getters / toString
}
Next, we need to create a repository interface that extends JpaRepository and
provides CRUD methods for the User entity:
package com.example.demo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
Finally, we need to create a view template that displays a list of users in a
table. We will use Thymeleaf as our template engine and place the template
file under src/main/resources/templates/users.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Users</title>
</head>
<body>
<h1>Users</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.email}"></td>
</tr>
</tbody>
</table>
</body>
</html>
We use the Thymeleaf namespace and attributes to connect the data from the
model to the view. We also use the ${users} expression to get the list of
users that we will send from the controller.
Now we can run our application and open the http://localhost:8080/users URL in
our browser. We should see a table with some users that are already created by
Spring Boot using H2 database.
That’s all we need to do! We have added some more features to our web
application with Spring Boot without writing any SQL queries or configuration
files. Spring Boot has taken care of everything for us based on our pom.xml
file and properties.
Starters:
Let’s make a new project using Spring Initializr. Spring Initializr is a web
tool that helps you create a starter project with the dependencies and
configuration that you want.
First, we need to go to the Spring Initializr website and enter some basic
information about our project, such as group, artifact, name, description,
etc.
Next, we need to pick the dependencies that we want to use in our project. For
example, let’s say we want to make a web application with RESTful services,
security, actuator, and H2 database. We can choose the following starters from
the list:
• Spring Web
• Spring Security
• Spring Boot Actuator
• Spring Data JPA
• H2 Database
Finally, we need to click on the Generate button and download the zip file that has our starter project. We can then open the project in our IDE and start writing code.
Notice that our pom.xml file has only the starter dependencies that we have
picked. We don’t need to mention the versions or manage the transitive
dependencies of these starters. Spring Boot will do that for us.
Also notice that our application.properties file has some default properties
for our application, such as server port, logging level, security username and
password, etc. We can modify these properties or add more properties as per
our needs.
Now we can run our application and open some of the endpoints that are given
by the starters.
For example:
That’s all we need to do! We have made a new project with Spring Boot using
Spring Initializr without writing any boilerplate code or configuration files.
Spring Boot has given us a ready-to-use starter project with the dependencies
and configuration that we want.
Using Actuator
Let’s use the same project that we have made using Spring Initializr.
First, we need to add the spring-boot-starter-actuator dependency to our
pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Next, we need to turn on the actuator endpoints that we want to show. By
default, only the health and info endpoints are available over HTTP. We can
use the management.endpoints.web.exposure.include property to give a list of
endpoints that we want to show.
For example, let’s show all the endpoints:
management.endpoints.web.exposure.include=* We can also use the management.endpoints.web.exposure.exclude property to specify a list of endpoints that we want to hide. For example, let’s hide the env endpoint:
management.endpoints.web.exposure.exclude=env
Finally, we need to access the actuator endpoints using HTTP or JMX. The base path for the HTTP endpoints is /actuator by default. We can change it using the
management.endpoints.web.base-path property.
For example, let’s change it to /manage:
management.endpoints.web.base-path=/manage
Now we can run our application and open some of the actuator endpoints using
curl or a browser.
For example:
• http://localhost:8080/manage/beans - The beans endpoint that tells the
beans and their dependencies in the application context. We can also open
some of the actuator endpoints using JMX.
For example, we can use jconsole or jvisualvm to connect to our application
and look at the org.springframework.boot domain. We should see a list of
MBeans that match the actuator endpoints.
That’s all we need to do! We have added some production-ready features to
our application with Spring Boot without writing any code or configuration
files. Spring Boot has given us a set of endpoints that show information
about our application and its environment.
Testing:
We can write unit tests for our application using the JUnit framework and
the Mockito library. We can also use the spring-boot-starter-test dependency
that has both of them along with other useful libraries. And can use some
annotations such as @SpringBootTest, @WebMvcTest, @DataJpaTest, etc. to
easily test different layers and components of your application. You can
also use TestRestTemplate or WebTestClient to test your web endpoints.
Unit tests are tests that check the functionality of a single class or
method. They are usually fast and isolated from other components or
dependencies. Let’s see some examples of how to write unit tests for our
application using Spring Boot.
First, we need to add the spring-boot-starter-test dependency to our pom.xml
file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Next, we need to create a test class that uses the @RunWith and
@SpringBootTest annotations to enable the Spring Boot features in our tests:
package com.example.demo;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Test
public void contextLoads() {
}
}
The @RunWith annotation tells JUnit to use the SpringRunner class as the
test runner. The SpringRunner class is another name for the
SpringJUnit4ClassRunner class that provides integration between Spring
Boot and JUnit.
The @SpringBootTest annotation tells Spring Boot to make an application
context with all the beans and configuration that we want for our tests.
We can also give some properties or classes for our application context
using this annotation.
Now we can write some unit tests for our controller class using the
@MockBean and @Autowired annotations:
package com.example.demo;import static org.hamcrest.Matchers.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
@RunWith(SpringRunner.class)
@WebMvcTest(GreetingController.class)
public class GreetingControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private GreetingService service;
@Test
public void givenEmployees_whenGetEmployees_thenReturnJsonArray()
throws Exception {
Greeting alex = new Greeting("Hello, Alex!");
List<Greeting> allGreetings = Arrays.asList(alex);
given(service.getAllGreetings()).willReturn(allGreetings);
mvc.perform(get("/greetings").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].content", is(alex.getContent())));
}
}
The @MockBean annotation tells Spring Boot to make a mock object for the
GreetingService class and put it in the application context. The mock
object will replace any existing bean of the same type in the application
context.
The @Autowired annotation tells Spring Boot to inject the mock object into
our test class. We can then use the mock object to set the behavior of the
service methods using Mockito.
The MockMvc class is a helper class that lets us send HTTP requests and
check the responses. We can use it to test our web layer without actually
starting a server.
We can then write some unit tests for our service class using the
@DataJpaTest and @TestEntityManager annotations:
Test class that uses the @DataJpaTest annotation to test the persistence
layer:
package com.example.demo;import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataJpaTest
public class EmployeeRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private EmployeeRepository repository;
@Test
public void whenFindByName_thenReturnEmployee() {
// given
Employee bob = new Employee("Bob", "bob@example.com");
entityManager.persistAndFlush(bob);
// when
Employee found = repository.findByName(bob.getName());
// then
assertThat(found.getName()).isEqualTo(bob.getName());
}
@Test
public void whenInvalidName_thenReturnNull() {
// when
Employee fromDb = repository.findByName("doesNotExist");
// then
assertThat(fromDb).isNull();
}
@Test
public void whenFindAll_thenReturnAllEmployees() {
// given
Employee bob = new Employee("Bob", "bob@example.com");
Employee alice = new Employee("Alice", "alice@example.com");
entityManager.persist(bob);
entityManager.persist(alice);
entityManager.flush();
// when
List<Employee> allEmployees = repository.findAll();
// then
assertThat(allEmployees).hasSize(2).extracting(Employee::getName)
.containsOnly(bob.getName(), alice.getName());
}
}
The @DataJpaTest annotation tells Spring Boot to make a test context with
only the beans needed for testing JPA repositories. It also sets up an
in-memory database and sets Hibernate to create-drop mode.
The TestEntityManager class is a helper class that lets us persist and find
entities using JPA. We can use it to set up the data for our tests.
The EmployeeRepository interface extends JpaRepository and has some methods
for querying employees. We can use it to check the results of our tests.
Testing the web layer
We can write web tests for our application using the MockMvc or
WebTestClient classes. We can also use the @WebMvcTest or @WebFluxTest
annotations to test only the web layer of our application.
First, we need to add the spring-boot-starter-web dependency to our pom.xml
file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Next, we need to create a test class that uses the @WebMvcTest annotation to
test our controller class using MockMvc:
package com.example.demo;
import static org.hamcrest.Matchers.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
@RunWith(SpringRunner.class)
@WebMvcTest(GreetingController.class)
public class GreetingControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private GreetingService service;
@Test
public void givenGreetings_whenGetGreetings_thenReturnJsonArray()
throws Exception {
Greeting alex = new Greeting("Hello, Alex!");
List<Greeting> allGreetings = Arrays.asList(alex);
given(service.getAllGreetings()).willReturn(allGreetings);
mvc.perform(get("/greetings")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].content", is(alex.getContent())));
}
}
The @WebMvcTest annotation tells Spring Boot to create a test context with
only the beans required for testing the web layer. It also configures MockMvc
for us.
MockMvc:
The MockMvc class is a helper class that lets us send HTTP requests and
check the responses. We can use it to test our web layer without actually
starting a server.
We can use the @Autowired annotation to inject a MockMvc instance into our
test class. We can also use the @MockBean annotation to make and inject mock
objects for the services or repositories that are used by our controller.
We can use the MockMvcRequestBuilders class to make requests for different
HTTP methods and URIs. We can also give request parameters headers content
type and body.
We can use the MockMvcResultMatchers class to assert the results of the
requests. We can check the status code content type headers and body of the
response. We can also use JSONPath expressions to check specific parts of
the JSON response.
We can use the MockMvcResultHandlers class to print or log the results of
the requests. This can be helpful for debugging or troubleshooting purposes.
Using WebTestClient:
We can write web tests for our application using WebFlux using the
WebTestClient class. We can also use the @WebFluxTest annotation to test
only the web layer of our reactive application.
First, we need to add the spring-boot-starter-webflux dependency to our
pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Next, we need to create a test class that uses the @WebFluxTest annotation
to test our reactive controller class using WebTestClient:
package com.example.demo;import static org.mockito.BDDMockito.given;
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
@RunWith(SpringRunner.class)
@WebFluxTest(GreetingController.class)
public class GreetingControllerTest {
@Autowired
private WebTestClient webClient;
@MockBean
private GreetingService service;
@Test
public void givenGreetings_whenGetGreetings_thenReturnJsonArray() {
// given
Greeting alex = new Greeting("Hello, Alex!");
List<Greeting> allGreetings = Arrays.asList(alex);
given(service.getAllGreetings()).willReturn(allGreetings);
// when/then
webClient.get().uri("/greetings")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBodyList(Greeting.class)
.contains(alex);
}
@Test
public void givenNewGreeting_whenPostGreeting_thenCreateGreeting() {
// given
Greeting bob = new Greeting("Hello, Bob!");
given(service.createGreeting(bob)).willReturn(bob);
// when/then
webClient.post().uri("/greetings")
.contentType(MediaType.APPLICATION_JSON)
.body(fromValue(bob))
.exchange()
.expectStatus().isCreated()
.expectBody(Greeting.class)
.isEqualTo(bob);
}
}
The @WebFluxTest annotation tells Spring Boot to make a test context with
only the beans needed for testing the web layer. It also sets up
WebTestClient for us.
The WebTestClient class is a reactive web client that lets us send HTTP
requests and check the responses. We can use it to test our web layer
without actually starting a server.
We can use the @Autowired annotation to inject a WebTestClient instance into
our test class. We can also use the @MockBean annotation to make and inject
mock objects for the services or repositories that are used by our
controller.
We can use the WebTestClient methods to make requests for different HTTP
methods and URIs. We can also give request parameters headers content type
and body.
We can use the WebTestClient.ResponseSpec methods to assert the results of
the requests. We can check the status code content type headers and body of
the response. We can also use JSONPath expressions or custom matchers to
check specific parts of the JSON response.
Conclusion:
The ends of our section on Spring Boot Features. We have learned how to use
some of the main features of Spring Boot such as auto-configuration dependency
management starters actuator and testing. We have also seen some examples of
how to make and run Spring Boot applications with these features.