![]() |
Spring Boot Tutorials Part #2: Spring Boot Features |
Spring Boot Features:
Spring Boot makes creating and running Spring-based applications simple and fast. Some of the key features are:- Dependency Management: Spring Boot offers a set of starter dependencies that contain the common libraries and frameworks for different types of applications.
@SpringBootTest
@WebMvcTest
@DataJpaTest etc.
Auto-configuration
To show the auto-configuration feature of Spring Boot let’s make a simple web application that returns a greeting message.<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);
}
}
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
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> {
}
<!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>
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.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>
For example, let’s show all the endpoints:
management.endpoints.web.exposure.include=*Testing:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
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)@SpringBootTestpublic class DemoApplicationTests {@Testpublic void contextLoads() {}}
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 {@Autowiredprivate MockMvc mvc;@MockBeanprivate GreetingService service;@Testpublic 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())));}}
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)@DataJpaTestpublic class EmployeeRepositoryTest {@Autowiredprivate TestEntityManager entityManager;@Autowiredprivate EmployeeRepository repository;@Testpublic void whenFindByName_thenReturnEmployee() {// givenEmployee bob = new Employee("Bob", "bob@example.com");entityManager.persistAndFlush(bob);// whenEmployee found = repository.findByName(bob.getName());// thenassertThat(found.getName()).isEqualTo(bob.getName());}@Testpublic void whenInvalidName_thenReturnNull() {// whenEmployee fromDb = repository.findByName("doesNotExist");// thenassertThat(fromDb).isNull();}@Testpublic void whenFindAll_thenReturnAllEmployees() {// givenEmployee bob = new Employee("Bob", "bob@example.com"); Employee alice = new Employee("Alice", "alice@example.com");entityManager.persist(bob);entityManager.persist(alice);entityManager.flush();// whenList<Employee> allEmployees = repository.findAll();// thenassertThat(allEmployees).hasSize(2).extracting(Employee::getName) .containsOnly(bob.getName(), alice.getName());}}
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
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 {@Autowiredprivate MockMvc mvc;@MockBeanprivate GreetingService service;@Testpublic 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())));}}
MockMvc:
Using WebTestClient:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>
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 {@Autowiredprivate WebTestClient webClient;@MockBeanprivate GreetingService service;@Testpublic void givenGreetings_whenGetGreetings_thenReturnJsonArray() {// givenGreeting alex = new Greeting("Hello, Alex!");List<Greeting> allGreetings = Arrays.asList(alex);given(service.getAllGreetings()).willReturn(allGreetings);// when/thenwebClient.get().uri("/greetings").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBodyList(Greeting.class) .contains(alex);}@Testpublic void givenNewGreeting_whenPostGreeting_thenCreateGreeting() {// givenGreeting bob = new Greeting("Hello, Bob!"); given(service.createGreeting(bob)).willReturn(bob);// when/thenwebClient.post().uri("/greetings").contentType(MediaType.APPLICATION_JSON).body(fromValue(bob)).exchange().expectStatus().isCreated() .expectBody(Greeting.class).isEqualTo(bob);}}