DEV Community

b0r
b0r

Posted on

1. Getting started with Spring Framework - Spring in Action - book notes

Another month, another book.

To refresh my Spring Framework / Spring Boot knowledge (that I'm using on day-to-day basis), I've started reading an excellent Spring in Action, 6th edition published by Manning.

Spring in Action, Sixth Edition

I'm not sure about you, but taking notes (writing/drawing) really helps me get the most out of the book, so I'm sharing everything I have with you (for further reference).

I also really like taking notes in Markdown format. The nice thing about Markdown is, that I can publish it on dev.to and get a nice HTML automatically generated/published for further reference!!

1. Getting started with Spring

This chapter covers

  • Spring and Spring Boot essentials
  • Initializing a Spring project
  • An overview of the Spring landscape

1.1 What is Spring?

Application Context

  • at its core, Spring offers a container, often referred to as the Spring application context, that creates and manages application components
  • these components, or beans, are wired together inside the Spring application context to make a complete application, much like bricks, mortar, timber...are bounded to make a house

  • application components are managed and injected into each other by spring application context

Dependency Injection

  • the act of wiring beans together
  • dependency injected application relies on a separate entity (container) to create and maintain all components and inject those into the beans that need them.
  • typically done through constructor args or property accessor methods
<bean id="inventoryService"
      class="com.example.InventoryService"
/>

<bean id="productService"
      class="com.example.ProductService">
      <constructor-arg ref="inventoryService"/>
</bean>
Enter fullscreen mode Exit fullscreen mode
@Configuration
public class ServiceConfiguration {
  @Bean
  public InventoryService inventoryService() {
    return new InventoryService();
  }

  @Bean
  public ProductService productService() {
    return new ProductService(inventoryService());
  }
}
Enter fullscreen mode Exit fullscreen mode

@Configuration

  • indicates that class provides beans to the Spring application context

@bean

  • indicates that returned object should be added as a bean in the application context

Component Scanning

  • Spring automatically discover components from an application's classpath and create them as bean in the Spring application context

Autowiring

  • Spring automatically injects the components with the other beans that they depend on

Spring Boot

  • most well-known enhancement is auto-configuration
    • make reasonable guesses of what components need to be configured and wired together based on entries in the classpath, env vars,...

1.2 Initializing a Spring application

Initializing a Spring project with Spring Tool Suite

  • Taco Cloud

    • an online app for ordering food
    • dependencies:
    • spring web
    • spring dev tools
    • thymeleaf

Exploring the build specification

  • parent pom provides dependency management for several libraries commonly used in Spring projects:
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.3</version>
    <relativePath />
  </parent>
Enter fullscreen mode Exit fullscreen mode
  • library version is inherited from the parent version

  • spring boot starter dependencies typically don't have any library code themselves, but instead transitively pull in other libraries

    • you're able to think of your dependencies in terms of what capabilities they provide, rather than their library names
    • you don't have to worry about the library version

Spring Boot Plugin

  • it provides a Maven goal to run the application
  • ensures that all deps. are included within the executable JAR file and available on the runtime classpath
  • produces a manifest file (contains metadata) in the JAR file that denotes the bootstrap class as the main class for the executable JAR

Bootstrapping the application

@SpringBootApplication

  • composite annotation that combines 3 other annotations:
    • @SpringBootConfiguration (specialized form of the @Configuration)
    • @EnableAutoConfiguration (automatically configure any component you might need)
    • @ComponentScan (spring automatically discovers/registers components, services, controllers..)

Testing the application

$ ./mvnw package
...
$ java -jar target/taco-cloud-0.0.1-SNAPSHOT.jar
Enter fullscreen mode Exit fullscreen mode
$ ./mvnw package
...
$ java -jar target/taco-cloud-0.0.1-SNAPSHOT.jar
Enter fullscreen mode Exit fullscreen mode

A baseline application test

  • can be used to assert that the application starts
package tacos;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class TacoCloudApplicationTests {

  @Test
  public void contextLoads() {
  }

}
Enter fullscreen mode Exit fullscreen mode

@SpringBootTest

  • tells JUnit to bootstrap the test with Spring Boot capabilities
  • ocmposite annotation:
    • @ExtendWith(SpringExtension.class)

1.3 Writing a Spring application

Create Taco Cloud application homepage:

  • create controlle
  • create view template
  • write tests

Handling web requests

Spring MVC

  • controller - a class that handles req/resp
  • @Controller annotation
    • identify class as a component for component scanning
  • home() method
  • @GetMapping
  • return "home"
    • "home" is a logical name of a view
    • template name is derivered from the logical view name /templates/home.html

Defining the view

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Taco Cloud</title>
  </head>

  <body>
    <h1>Welcome to...</h1>
    <img th:src="@{/images/TacoCloud.png}"/>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Static content, e.g. images are kept in the /src/main/resources/static/

Testing the controller

  • perform the HTTP GET request for the root path '/'
    • expect successful result (viewName = home, content = "Welcome to...")
package tacos;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(HomeController.class)
public class HomeControllerTest {

  @Autowired
  private MockMvc mockMvc;

  @Test
  public void testHomePage() throws Exception {
    mockMvc.perform(get("/"))
      .andExpect(status().isOk())
      .andExpect(view().name("home"))
      .andExpect(content().string(
          containsString("Welcome to...")));
  }

}
Enter fullscreen mode Exit fullscreen mode

@WebMvcTest

  • special annotation provided by spring boot
  • arranges the test to run in the context of a Spring MVC application
    • arranges HomeController to be registered in Spring MVC so that you can send request to it
  • it doesn't start the server (mockin is good enough in this case)
  • the test class is injected with a MockMvc object for the test to drive the mockup

Building and running the application

./mvnw springBoot:run

Spring Boot application tend to bring everything they need with them and don't need to be deployed to some application server. Tomcat is a part of your application.

Getting to know Spring Boot DevTools

Spring DevTools provides developers with some handy development-time tools:

  • automatic application restart when code (or application properties) changes
  • automatic browser refresh
  • automatic disable of template caches
  • built in h2 console/DB

How it works?

  • there are 2 class loaders
    • first one contains you Java code, property files that change frequently
    • second one contains dependency libraries which aren't changed often
  • when change is detected, first class loader is automatically restarted

Let's review

  • initialized project
  • wrote controller
  • defined template
  • wrote simple test

The main benefit is that you can focus on the code that meets the requirements of an application, rather than on satisfying the demands of a framework <- "framework-less framework"

  • declare dependencies in pom.xml
    • web
    • thymeleaf

these two dependencies transitively bring in other dependencies:

  • spring mvc framework
  • embedded tomcat
  • thymeleaf and thymeleaf layout dialect
  • spring auto-configuration library

1.4 Surveying the Spring landscape

  • Spring Framework (Core)
    • provides core container and dependency injection
    • provides Spring MVC, a Spring's web framework, JDBC support, WebFlux (reactive)
  • Spring Boot
    • provides starter dependencies and auto-configuration
    • actuator (runtime insight into the inner workings of the application)
    • flexible specification of env. properties
    • additional testing support
    • Spring Boot CLI (alternative programming model based on Groovy scripts)
  • Spring Date
    • define data repositories as Java interfaces (sql, nosql, graph,..)
  • Spring Security
    • authentication, authorization, API security
  • Spring Integration
    • real time integration where data is processed as it's made available
  • Spring Batch
    • batched integration
  • Spring Cloud
    • check out Cloud Native Spring
  • Spring Native
    • Spring Boot + GraalVM => native images

1.5 Sumary

  • spring aims to make developer challenges easy
    • creating web apps, working with databases, securing applications, and microservices
  • spring boot builds on top of spring to make spring even easier
  • spring applications can be initialized using the spring initializer
  • beans (components) can be declared explicitly with Java or XML, discovered by component scanning, or automatically configured with spring boot auto-configuration

Top comments (0)