Blogg
Här finns tekniska artiklar, presentationer och nyheter om arkitektur och systemutveckling. Håll dig uppdaterad, följ oss på Twitter
Här finns tekniska artiklar, presentationer och nyheter om arkitektur och systemutveckling. Håll dig uppdaterad, följ oss på Twitter
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
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:
Figure 1 - Spring Cloud capabilities
The Kubernetes, Istio, and the EFK stack features covered in Chapter 20 are summarized by the following illustration:
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.
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:
spring-boot-starter-graphql
starter-dependency. You’ll find more information in the GraphQL section of the Spring Boot reference documentation.Spring Cloud 2021.0.3 is the first release compatible with Spring Boot 2.7; see the announcement blog post.
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.
I have divided the required source code changes into three sections:
Let’s start with 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.
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, theauthorization-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.
The following changes have been applied to the source code in chapter 23 to work with the new Spring Native release:
Updated the native hint annotations as required by the new AOT engine. For details, see each microservice’s application class.
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.
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.
Each microservice now has a base class, *KafkaTestBase.java
, for TestContainer-based tests that start up a Docker container running Kafka.
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.
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:
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.
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.
Updated test-em-all.bash
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
.
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.
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.
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.