Blogg

Här finns tekniska artiklar, presentationer och nyheter om arkitektur och systemutveckling. Håll dig uppdaterad, följ oss på Twitter

Callista medarbetare Magnus Larsson

Upgrade to Spring Boot 2.7 and Spring Native 0.12

// Magnus Larsson

It has been a year since the 2’nd edition of my book on building microservices with Spring Boot, Spring Cloud, Kubernetes, and Istio was published. Since then, many new versions of the tools and frameworks used in the book have been released. In this and a few following blog posts, I will describe how to upgrade the source code in the book to use the latest versions.

Table of Contents

1. Overview

In this blog post, we will start to learn how to upgrade to the latest versions of Spring Boot (2.7), Spring Cloud (2021.0), and Spring Native (0.12). In the coming blog posts, I will describe how to upgrade to the latest releases of Minikube, Kubernetes, and Istio. Also, how to build and run microservices on ARM64-based hardware, such as a MacBook Pro with Apple silicon, will be explained.

With Spring Boot 3.0 around the corner, Spring Boot 2.7 will be the last branch of Spring Boot 2.x. To prepare for Spring Boot 3.0, Pivotal recommends upgrading to Spring Boot 2.7 and Java 17. So we will also upgrade to Java 17, forcing us to upgrade the Gradle version as well. For further details, see Preparing for Spring Boot 3.0. Finally, to work with Spring Boot 2.7, springdoc-openapi will be upgraded to 1.6.10.

The following table summarizes the updates covered by this blog post:

Software Old version New version
Java 16 17
Gradle 7.0 7.4.1
Spring Framework 5.3.8 5.3.22
Spring Boot 2.5.2 2.7.3
Spring Cloud 2020.0.3 2021.0.3
Spring Native 0.10.1 0.12.1
Spring Dep Mgm 1.0.11 1.0.13
springdoc-openapi 1.5.9 1.6.10

The source code for this blog post is found in the Git branch: SB2.7 in the book’s Git repo. Since each chapter builds on the previous chapter only Chapter 14 (covering all Spring Cloud features), Chapter 20 (covering all features in Kubernetes, Istio, and the EFK stack), and Chapter 23 (covering Spring Native) has been updated in this Git branch.

The following illustration summarizes the Spring Cloud features covered in Chapter 14:

SpringCloud-landscape

Figure 1 - Spring Cloud capabilities

The Kubernetes, Istio, and the EFK stack features covered in Chapter 20 are summarized by the following illustration:

K8S-Istio-landscap

Figure 2 - Kubernetes, Istio, EFK-stack capabilities

Note that each infrastructure component has a label next to it describing what capabilities it adds to the system landscape. You can compare them with the capabilities required by a microservice-based system landscape, as discussed in chapter 1.

Before we look into the code changes required, let’s see where to find information regarding news in the various releases.

2. What’s new?

  1. News about Spring Boot can be found at:
    1. For v2.6, see the announcement blog post and the release notes.
    2. For v2.7, see the announcement blog post and the release notes.

    There is no news in the v2.6 and v2.7 releases that should affect the source code in this book.

    However, I found the following news of general interest in the v2.7 release:

    1. Podman can now be used, as a no-cost alternate to Docker Desktop, when building Docker images using Cloud Native Buildpacks.
    2. Spring Boot 2.7 ships support for the Spring GraphQL project with a new spring-boot-starter-graphql starter-dependency. You’ll find more information in the GraphQL section of the Spring Boot reference documentation.
  2. Spring Cloud 2021.0.3 is the first release compatible with Spring Boot 2.7; see the announcement blog post.

  3. In Spring Native v0.11, a new AOT engine was released; see the announcement blog post New AOT Engine Brings Spring Native to the Next Level. Detailed information on each Spring Native release can be found here.

The most critical update that affects the source code in the book is the new AOT engine (Ahead Of Time) introduced in Spring Native v0.11.

The new AOT engine provides improved compatibility at the cost of less runtime flexibility. From the blog post above, we can read the following summary:

Improved Compatibility
The AOT engine is also much more accurate because it doesn’t try to analyze Spring annotations or the various types to replicate what Spring does at runtime. Instead, it forks a new process where it creates and introspects an application context at build-time (without starting it). That allows use of a subset of what Spring Framework does at runtime and works at the bean definition level, which is much more accurate.

Runtime Flexibility
Performing those optimizations at build time means that there is less runtime flexibility than with the regular Spring Boot auto-configuration model. You can still change the HTTP port or the log level of your application when running an already compiled Spring Boot application, but you cannot add new beans at runtime by using a profile, for example.

These updates require a few changes in the source code of chapter 23, as described in the next section.

3. Source code changes

I have divided the required source code changes into three sections:

  1. One for upgrading Java and Gradle
  2. One for upgrading all Spring dependencies
  3. One for changes required by the new AOT engine in Spring Native

Let’s start with Java and Gradle!

3.1. Java and Gradle

Upgrading the Gradle version is done in the file gradle/wrapper/gradle-wrapper.properties:

distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip

Upgrading the Java JRE version used in runtime is done by updating the Dockerfile - files for each microservice:

FROM eclipse-temurin:17.0.4_8-jre-focal

Installing the Java 17 JDK on your computer can be done by following the instructions in chapters 21 and 22.

3.2. Spring dependencies

The new versions of the Spring components are specified in each microservice’s build file, build.gradle. An example from the product-composite microservice:

springBootVersion = '2.7.3'
springCloudVersion = "2021.0.3"

id 'io.spring.dependency-management' version '1.0.13.RELEASE'

implementation 'org.springdoc:springdoc-openapi-common:1.6.10'

Note that the authorization-server use Spring Boot v2.4.4 in the source code of the book due to this issue. Since this issue has been fixed, the authorization-server can also be upgraded to Spring Boot 2.7.

Due to changes in Spring Boot’s support for liveness and readiness probes in Kubernetes, the readiness probe, readinessState, now needs to be explicitly specified in the shared configuration file, config-repo/application.yml:

management.endpoint.health.group.readiness.include: readinessState, db, mongo

For more information on Spring Boot’s support for liveness and readiness probes, see chapter 16.

3.3. Spring Native

The following changes have been applied to the source code in chapter 23 to work with the new Spring Native release:

  1. Updated the native hint annotations as required by the new AOT engine. For details, see each microservice’s application class.

  2. Added application.yml files to make the AOT engine detect configuration at build time.

    Since configurations that enable Spring Boot features can no longer be activated at runtime using reflection, configurations must be provided at build time, for example, in a microservice’s src/main/resources/application.yml - file. An example from the product-composite microservice’s application.yml - file:

     # Required to make Spring Native generate the appropriate infrastructure for
     # a separate management port, Prometheus and K8S probes
     management.server.port: 9009
     management.endpoint.health.probes.enabled: true
     management.endpoints.web.exposure.include: health,info,circuitbreakerevents,prometheus
    
     # Required to make Spring Native generate a ReactiveJwtDecoder for the OIDC Issuer
     spring.security.oauth2.resourceserver.jwt.issuer-uri: http://someissuer
    

    Specific values, for example, for the management port and the access token issuer’s URL, can be specified in runtime. But some dummy values must be set for the AOT Engine at build time to understand that it needs to generate code that enables the features at startup time. Remember that a native image can’t rely on detecting features at runtime using reflection. For more information, see the Spring Boot reference manual regarding the AOT-engine.

  3. Added integration tests with Kafka

    Unfortunately, the new AOT engine does not generate a sufficient configuration for Spring Cloud Stream and its Kafka binder. Therefore, we need some extra help from GraalVM’s Tracing Agent. For details on how to use the Tracing Agent, see chapter 23. To make the Tracing Agent detect usage of Kafka and generate correct native image configuration, I have added TestContainer-based tests of the Kafka usage in each microservice. The new integration tests replace the existing messaging tests, which used the Spring Cloud Stream test binder.

    1. Each microservice now has a base class, *KafkaTestBase.java, for TestContainer-based tests that start up a Docker container running Kafka.

    2. The product-composite microservice has a new test-message-consumer, MessageTestConsumerConfig.java, that picks up the events sent to Kafka topics during the integration tests. It is used by the integration tests to compare the received events with the expected events.

    3. The resulting native image configuration produced by the Tracing Agent has been added to each microservice src/main/resources/META-INF/native-image - folder. The configuration will be picked up by the native compiler when it creates the native image for a microservice. The Tracing Agent has been disabled when running Gradle tests, so you don’t need to install the Tracing Agent before trying out the updates in this blog post. If you want to try out the Tracing Agent, see the instructions in chapter 23.

Finally, some minor updates have been applied:

  1. Removed springdoc-openapi

    The latest version of springdoc-openapi supports Spring Native 0.12.1, but unfortunately not when combined with the output from the Tracing Agent. Therefore, springdoc-openapi has been disabled in the source code of chapter 23. Hopefully, this problem will be resolved when Spring Native is built into Spring Boot 3 and no longer is in an experimental state.

  2. Updated access-filter.json

    Added a few new classes for the Tracing Agent to ignore, to minimize both the build time and the size of the resulting native image.

  3. Updated test-em-all.bash

    1. Disabled tests for springdoc-openapi
    2. Added tests for the Prometheus actuator endpoint when deployed to Kubernetes to verify that Spring Native generates the correct configuration for the microservices. The tested endpoint is https://health.minikube.me/actuator/prometheus.

This completes the walkthrough of the changes required in the source code. If you want to see all the changes, you can check out the Git-repository’s main-branch in one folder and the SB2.7-branch in another folder. Then, use a diff-tool of your choice to compare the content in the subfolders Chapter14, Chapter20, and Chapter23.

4. Try it out

To try out the source code changes in chapter 14, first ensure that Docker, Java, git, jq, curl are installed. For installation instructions, see chapters 21 and 22. Then perform the following steps:

git clone https://github.com/PacktPublishing/Microservices-with-Spring-Boot-and-Spring-Cloud-2E.git
cd Microservices-with-Spring-Boot-and-Spring-Cloud-2E
git checkout SB2.7
cd Chapter14
./gradlew build
docker-compose build
docker-compose up -d
./test-em-all.bash

Look for a final log message that says:

End, all tests OK

Tear down the microservice landscape with the command:

docker-compose down

For testing the source code changes in chapter 20 with Kubernetes, Istio, and the EFK Stack, see instructions in chapters 17 - 20 in the book for how to setup the Kubernetes cluster. For building native images with the source code changes in chapter 23, see instructions in chapter 23.

5. Summary

In this blog post, we have seen how easy it is to upgrade the source code in this book to the latest versions of Spring Boot, Spring Cloud et al. However, when it comes to upgrading the experimental Spring Native project, there is more work needed. This is expected since the implementation of Spring Native still changes a lot. Once Spring Boot 3 has been released, a smoother upgrade experience of the native image support in Spring can be expected.

6. Next up

That’s all for this blog post; in the next one, we will look at how we can upgrade to the latest versions of Minikube, Kubernetes, and Istio.

Tack för att du läser Callistas blogg.
Hjälp oss att nå ut med information genom att dela nyheter och artiklar i ditt nätverk.

Kommentarer