Book Image

Learning Spring Boot 3.0 - Third Edition

By : Greg L. Turnquist
Book Image

Learning Spring Boot 3.0 - Third Edition

By: Greg L. Turnquist

Overview of this book

Spring Boot 3 brings more than just the powerful ability to build secure web apps on top of a rock-solid database. It delivers new options for testing, deployment, Docker support, and native images for GraalVM, along with ways to squeeze out more efficient usage of existing resources. This third edition of the bestseller starts off by helping you build a simple app, and then shows you how to secure, test, bundle, and deploy it to production. Next, you’ll familiarize yourself with the ability to go “native” and release using GraalVM. As you advance, you’ll explore reactive programming and get a taste of scalable web controllers and data operations. The book goes into detail about GraalVM native images and deployment, teaching you how to secure your application using both routes and method-based rules and enabling you to apply the lessons you’ve learned to any problem. If you want to gain a thorough understanding of building robust applications using the core functionality of Spring Boot, then this is the book for you. By the end of this Spring Boot book, you’ll be able to build an entire suite of web applications using Spring Boot and deploy them to any platform you need.
Table of Contents (17 chapters)
1
Part 1: The Basics of Spring Boot
3
Part 2: Creating an Application with Spring Boot
8
Part 3: Releasing an Application with Spring Boot
12
Part 4: Scaling an Application with Spring Boot

Autoconfiguring Spring beans

Spring Boot comes with many features. But the most well-known one, by far, is autoconfiguration.

In essence, when a Spring Boot application starts up, it examines many parts of our application, including classpath. Based on what the application sees, it automatically adds additional Spring beans to the application context.

Understanding application context

If you’re new to Spring, then it’s important to understand what we’re talking about when you hear application context.

Whenever a Spring Framework application starts up, whether or not Spring Boot is involved, it creates a container of sorts. Various Java beans that are registered with Spring Framework’s application context are known as Spring beans.

Tip

What’s a Java bean? Java beans are objects that follow a specific pattern: all the fields are private; they provide access to their fields through getters and setters, they have a no-argument constructor, and they implement the Serializable interface.

For example, an object of the Video type with name and location fields would set those two fields to private and offer getName(), getLocation(), setName(), and setLocation() as the ways to mutate the state of this bean. On top of that, it would have a no-argument Video() constructor call. It’s mostly a convention. Many tools provide property support by leveraging the getters and setters. The requirement to implement the Serializable interface, though, is not as tightly enforced.

Spring Framework has a deep-seated concept known as dependency injection (DI), where a Spring bean can express its need for a bean of some other type. For example, a BookRepository bean may require a DataSource bean:

@Bean
public BookRepository bookRepository(DataSource dataSource) {
  return new BookRepository(dataSource);
}

This preceding Java configuration, when seen by the Spring Framework, will cause the following flow of actions:

  1. bookRepository needs a DataSource.
  2. Ask the application context for a DataSource.
  3. The application context either has it or will go create one and return it.
  4. bookRepository executes its code while referencing the app context’s DataSource.
  5. BookRepository is registered in the application context under the name bookRepository.

The application context will ensure all Spring beans needed by the application are created and properly injected into each other. This is known as wiring.

Why all this instead of a handful of new operations in various class definitions? Simple. For the standard situation of powering up our app, all the beans are wired together as expected.

For a test case, it’s possible to override certain beans and switch to stubbed or mocked beans.

For cloud environments, it’s easy to find all DataSource and replace them with beans that link to bound data services.

By removing the new operation from our example BookRepository, and delegating that responsibility to the application context, we open the door to flexible options that make the whole life cycle of application development and maintenance much easier.

We’ll explore how Spring Boot heavily leverages the Spring Framework’s ability to inject beans based on various circumstances throughout this book. It is important to realize that Spring Boot doesn’t replace the Spring Framework but rather highly leverages it.

Now that you know what an application context is, it is time to dive into the many ways Spring Boot makes use of it through autoconfiguration.

Exploring autoconfiguration policies in Spring Boot

Spring Boot comes with a fistful of autoconfiguration policies. These are classes that contain @Bean definitions that are only registered based on certain conditional circumstances. Perhaps an example is in order?

If Spring Boot detects the class definition of DataSource somewhere on the classpath, a class found inside any Java Database Connectivity (JDBC) driver, it will activate its DataSourceAutoConfiguration. This policy will fashion some version of a DataSource bean. This is driven by the @ConditionalOnClass({ DataSource.class }) annotation found on that policy.

Inside DataSourceAutoConfiguration are inner classes, each driven by various factors. For example, some classes will discern whether or not we have used an embedded database such as H2 compared to a pooled JDBC asset such as HikariCP.

And just like that, the need for us to configure an H2 DataSource is removed. A small piece of infrastructure that is often the same across a multitude of applications is taken off our plate and instead managed by Spring Boot. And we can move more quickly toward writing business code that uses it.

Spring Boot autoconfiguration also has smart ordering built in, ensuring beans are added properly. Don’t worry! Using Spring Boot doesn’t depend on us having to know this level of detail.

Most of the time, we don’t have to know what Spring Boot is up to. It’s designed to do the right thing when various things are added to the build configuration.

The point is that many features, such as servlet handlers, view resolvers, data repositories, security filters, and more are activated, simply based on what dependencies we add to the build file.

And do you know what’s even better than automagically adding Spring beans? Backing off.

Some beans are created based on the classpath settings. But if a certain bean definition is detected inside our code, the autoconfiguration won’t kick in.

Continuing with the example from earlier, if we put something such as H2 in our classpath but define a DataSource bean and register it in the application context, Spring Boot will accept our DataSource bean over theirs.

No special hooks. No need to tell Spring Boot about it. Just create your own bean as you see fit, and Spring Boot will pick it up and run with it!

This may sound low-level, but Spring Boot’s autoconfiguration feature is transformational. If we focus on adding all the dependencies our project needs, Spring Boot will, as stated earlier, do what’s right.

Some of the autoconfiguration policies baked into Spring Boot extend across these areas:

  • Spring AMQP: Communicate asynchronously using an Advanced Message Queueing Protocol (AMQP) message broker
  • Spring AOP: Apply advice to code using Aspect-Oriented Programming
  • Spring Batch: Process large volumes of content using batched jobs
  • Spring Cache: Ease the load on services by caching results
  • Data store connections (Apache Cassandra, Elasticsearch, Hazelcast, InfluxDB, JPA, MongoDB, Neo4j, Solr)
  • Spring Data (Apache Cassandra, Couchbase, Elasticsearch, JDBC, JPA, LDAP, MongoDB, Neo4j, R2DBC, Redis, REST): Simplify data access
  • Flyway: Database schema management
  • Templating engines (Freemarker, Groovy, Mustache, Thymeleaf)
  • Serialization/deserialization (Gson and Jackson)
  • Spring HATEOAS: Add Hypermedia as the Engine of Application State (HATEOAS) or hypermedia to web services
  • Spring Integration: Support integration rules
  • Spring JDBC: Simplify accessing databases through JDBC
  • Spring JMS: Asynchronous through Java Messaging Service (JMS)
  • Spring JMX: Manage services through Java Management Extension (JMX)
  • jOOQ: Query databases using Java Object Oriented Querying (jOOQ)
  • Apache Kafka: Asynchronous messaging
  • Spring LDAP: Directory-based services over Lightweight Directory Access Protocol (jOOQ)
  • Liquibase: Database schema management
  • Spring Mail: Publish emails
  • Netty: An asynchronous web container (non-servlet-based)
  • Quartz scheduling: Timed tasks
  • Spring R2DBC: Access relational databases through Reactive Relational Database Connectivity (R2DBC)
  • SendGrid: Publish emails
  • Spring Session: Web session management
  • Spring RSocket: Support for the async wire protocol known as RSocket
  • Spring Validation: Bean validation
  • Spring MVC: Spring’s workhorse for servlet-based web apps using the Model-View-Controller (MVC) paradigm
  • Spring WebFlux: Spring’s reactive solution for web apps
  • Spring Web Services: Simple Object Access Protocol (SOAP)-based services
  • Spring WebSocket: Support for the WebSocket messaging web protocol

This is a general list and is by no means exhaustive. It’s meant to give us a glance at the breadth of Spring Boot.

And as cool as this set of policies and its various beans are, it’s lacking a few things that would make it perfect. For example, can you imagine managing the versions of all those libraries? And what about hooking in our own settings and components? We’ll cover these aspects in the next few sections.