Spring Boot 3: A simple tutorial with example

Spring Boot is a popular Java-based framework used to build web and stand-alone applications. It is built on top of the Spring framework and makes it easy to create stand-alone, production-grade Spring-based applications with minimal effort. In this tutorial, we will be discussing Spring Boot version 3 and how to get started with it.

What is new in Spring Boot 3.0 ?

Spring Boot 3.0 includes several new features and improvements. Some of the notable changes in Spring Boot 3.0 include:

  1. Java 16 support: Spring Boot 3.0 supports Java 16 and provides full support for the new features in Java 16, including the new JEPs (Java Enhancement Proposals).
  2. Spring Framework 5.3 support: Spring Boot 3.0 is built on top of the Spring Framework 5.3 and includes all the new features and improvements introduced in Spring Framework 5.3.
  3. Improved support for Kotlin: Spring Boot 3.0 includes improved support for Kotlin, including Kotlin DSL support for configuration and testing.
  4. Deprecation of XML configuration: Spring Boot 3.0 deprecates XML-based configuration in favor of annotation-based configuration.
  5. Improved testing support: Spring Boot 3.0 includes several new features to improve testing support, including the ability to use the @WebMvcTest annotation to test web controllers, and the ability to use the @MockBean annotation to mock beans in the application context.
  6. Improved security: Spring Boot 3.0 includes several security improvements, including the ability to use OAuth 2.0 for authorization and support for encrypted HTTP headers.
  7. New metrics and monitoring features: Spring Boot 3.0 includes new metrics and monitoring features, including support for Micrometer and the ability to use the HealthIndicator interface to implement custom health checks.

To test some of these new features, we will create a sample application using the Spring Boot Initializr.

Initialize a Spring Boot 3 application

Firstly, we will create a Maven project to boostrap our application. Head to the Spring Boot Initializr: https://start.spring.io/

From the Initializr choose Spring Boot 3.0. Then, add the project dependencies. To test the basic features we will need at minimum the Spring Web Dependencies.

Next, unzip the project in a folder of your Hard Drive. We will be adding some content in it.

Coding the application

Firstly, we will add a Model for our application. For this purpose we will add the following Record Type:

public record Customer(String name, String address) {}

Java Records are a new type of type-safe data carrier class. They can provide a concise and easy-to-use way to represent simple data structures, such as data transfer objects (DTOs) or domain objects.

The Service Class that will store the Customer records is the following CustomerService, which uses a JdbcTemplate to query the Customer objects:

@Service
public class CustomerService implements CustomerRepository {
    private final JdbcTemplate jdbcTemplate;

    public CustomerService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    private final RowMapper<Customer>  rowMapper = (rs, rowNum) -> new Customer(rs.getString("name"),rs.getString("address"));

    @Override
    public List<Customer> findAll() {
        String findAllStates = """
                select * from Customers
                """;
        return jdbcTemplate.query(findAllStates, rowMapper);
    }

    @Override
    public String findByName(String name) {
        String findByName = """
                select address from Customers where name = ?;
                """;
        return jdbcTemplate.queryForObject(findByName, String.class, name);
    }
}

JEP 378 in Spring Boot 3

Please notice the definition of String objects. They use multi-line text blocks to concatenate strings on line breaks

Next, we will add a Controller to access the application from REST Clients:

@RestController
public class CustomerController {
    private final CustomerService customerService;

    public CustomerController(CustomerService customerService) {
        this.customerService = customerService;
    }

    @GetMapping("/customers")
    private List<Customer> getAllCustomers() {
        return customerService.findAll();
    }

    @GetMapping(value = "/customer")
    private String getCustomer(@RequestParam(required = false, name = "name", defaultValue = "Maharashtra") String name) {
        return customerService.findByName(name);
    }
}

Finally, we will add a Repository Interface which wraps the two built-in finder methods available in this application:

public interface CustomerRepository {
    List<Customer> findAll();
    String findByName(String name);
}

The Application Class does not contain anything except for the @SpringBootApplication declaration:

@SpringBootApplication
public class Application {

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

Adding a Test Class

Next step will be adding a JUnit 5 Test Class. The following Class will test the /customers endpoint checking the Response Status Code and the number of customers. We will assume that two customers are in the List as our application will init the DB with a data.sql script.

Here is the CustomerTest Class:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class CustomerTest {

	@Autowired
	private TestRestTemplate restTemplate;

	@Test
	@DisplayName("GET /customers works")
	void testGetUsers_whenValidJWTProvided_returnsUsers() throws Exception {

		HttpHeaders headers = new HttpHeaders();
		headers.set("accept", "application/json");
		
		HttpEntity requestEntity = new HttpEntity<>(null, headers);
		ResponseEntity<List<Customer>> response = restTemplate.exchange("/customers",
				HttpMethod.GET,
				requestEntity,
				new ParameterizedTypeReference<List<Customer>>() {
				});
		List<Customer> customers = response.getBody();

		// Assert
		assertTrue(response.getStatusCode().is2xxSuccessful(), "HTTP Response status code should be 200");
		assertTrue(customers.size() == 2, "There should be exactly 2 customers in the list");
	}

}

Finally, we will include the following SQL scripts to init the DB. This is resources/schema.sql:

 DROP TABLE Customers IF EXISTS;
 CREATE TABLE Customers(name VARCHAR(255), address VARCHAR(255));

Then, this is data.sql:

INSERT INTO Customers VALUES ('John Smith','New York');
INSERT INTO Customers VALUES ('Heino Herrmann','Berlin');

Testing the application

In order to test our application, make sure you have a JDK 17 environment available as, by default, Spring Boot 3 uses Java 17:

<properties>
   <java.version>17</java.version>
</properties>

For example:

export JAVA_HOME=/home/user1/java/jdk-17.0.2/

Next, test the application:

mvn install

Finally, you can run the application:

mvn spring-boot:run

You can test the application with any tool. For example with curl:

spring boot 3.0 tutorial

Conclusion

This article was a quickstart to Spring Boot using some features which are available with a newer version of Java.

Related articles: Using the JDBC Template with Spring Boot applications

Source code: https://github.com/fmarchioni/masterspringboot/tree/master/rest/demo-rest-spring3

Found the article helpful? if so please follow us on Socials
Twitter Icon       Facebook Icon       LinkedIn Icon       Mastodon Icon