Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Microservices with Spring Boot 3 and Spring Cloud, Third Edition - Third Edition

You're reading from  Microservices with Spring Boot 3 and Spring Cloud, Third Edition - Third Edition

Product type Book
Published in Aug 2023
Publisher Packt
ISBN-13 9781805128694
Pages 706 pages
Edition 3rd Edition
Languages
Author (1):
Magnus Larsson Magnus Larsson
Profile icon Magnus Larsson

Table of Contents (26) Chapters

Preface 1. Introduction to Microservices 2. Introduction to Spring Boot 3. Creating a Set of Cooperating Microservices 4. Deploying Our Microservices Using Docker 5. Adding an API Description Using OpenAPI 6. Adding Persistence 7. Developing Reactive Microservices 8. Introduction to Spring Cloud 9. Adding Service Discovery Using Netflix Eureka 10. Using Spring Cloud Gateway to Hide Microservices behind an Edge Server 11. Securing Access to APIs 12. Centralized Configuration 13. Improving Resilience Using Resilience4j 14. Understanding Distributed Tracing 15. Introduction to Kubernetes 16. Deploying Our Microservices to Kubernetes 17. Implementing Kubernetes Features to Simplify the System Landscape 18. Using a Service Mesh to Improve Observability and Management 19. Centralized Logging with the EFK Stack 20. Monitoring Microservices 21. Installation Instructions for macOS 22. Installation Instructions for Microsoft Windows with WSL 2 and Ubuntu 23. Native-Complied Java Microservices 24. Other Books You May Enjoy
25. Index

Docker

I assume that Docker and the concept of containers need no in-depth presentation. Docker made the concept of containers as a lightweight alternative to virtual machines very popular in 2013. A container is actually a process in a Linux host that uses Linux namespaces to provide isolation between different containers, in terms of their use of global system resources such as users, processes, filesystems, and networking. Linux control groups (also known as cgroups) are used to limit the amount of CPU and memory that a container is allowed to consume.Compared to a virtual machine that uses a hypervisor to run a complete copy of an operating system in each virtual machine, the overhead in a container is a fraction of the overhead in a traditional virtual machine. This leads to much faster startup times and significantly lower overhead in terms of CPU and memory usage.The isolation that's provided for a container is, however, not considered to be as secure as the isolation that...

Summary

In this chapter, we have been introduced to Spring Boot and complementary open source tools that can be used to build cooperating microservices.Spring Boot is used to simplify the development of Spring-based, production-ready applications, such as microservices. It is strongly opinionated in terms of how to set up both core modules from the Spring Framework and third-party tools. Using Spring WebFlux we can develop microservices that expose reactive, that is, non-blocking, REST services. To document these REST services we can use springdoc-openapi to create OpenAPI-based documentation for the APIs. If we need to persist data used by the microservices, we can use Spring Data, which provides an elegant abstraction for accessing and manipulating persistent data using entities and repositories. Spring Data's programming model is similar, but not fully portable between different types of databases, for example, relational, document, key-value, and graph databases.If we prefer...

Questions

  1. What is the purpose of the @SpringBootApplication annotation?
  2. What are the main differences between the older Spring component for developing REST services, Spring Web MVC, and the new Spring WebFlux?
  3. How does springdoc-openapi help a developer document REST APIs?
  4. What is the function of a repository in Spring Data and what is the simplest possible implementation of a repository?
  5. What is the purpose of a binder in Spring Cloud Stream?
  6. What is the purpose of Docker Compose?

Generating skeleton microservices

Now it’s time to see how we can create projects for our microservices. The final result for this topic can be found in the $BOOK_HOME/Chapter03/1-spring-init folder. To simplify setting up the projects, we will use Spring Initializr to generate a skeleton project for each microservice. A skeleton project contains the necessary files for building the project, along with an empty main class and test class for the microservice. After that, we will see how we can build all our microservices with one command using multi-project builds in the build tool that we will use, Gradle.

Using Spring Initializr to generate skeleton code

To get started with developing our microservices, we will use a tool called Spring Initializr to generate skeleton code for us. Spring Initializr is provided by the Spring team and can be used to configure and generate new Spring Boot applications. The tool helps developers to choose additional Spring modules to be...

Adding RESTful APIs

Now that we have projects set up for our microservices, let’s add some RESTful APIs to our three core microservices!

The final result of this and the remaining topics in this chapter can be found in the $BOOK_HOME/Chapter03/2-basic-rest-services folder.

First, we will add two projects (api and util) that will contain code that is shared by the microservice projects, and then we will implement the RESTful APIs.

Adding an API and a util project

To add an api project, we need to do the following:

  1. First, we will set up a separate Gradle project where we can place our API definitions. We will use Java interfaces in order to describe our RESTful APIs and model classes to describe the data that the API uses in its requests and responses. To describe what types of errors can be returned by the API, a number of exception classes are also defined. Describing a RESTful API in a Java interface instead of directly in the Java class is, to me...

Adding a composite microservice

Now, it’s time to tie things together by adding the composite service that will call the three core services!

The implementation of the composite services is divided into two parts: an integration component that handles the outgoing HTTP requests to the core services and the composite service implementation itself. The main reason for this division of responsibility is that it simplifies automated unit and integration testing; we can test the service implementation in isolation by replacing the integration component with a mock.

As we will see later on in this book, this division of responsibility will also make it easier to introduce a circuit breaker!

Before we look into the source code of the two components, we need to take a look at the API classes that the composite microservices will use and also learn about how runtime properties are used to hold address information for the core microservices.

The full implementation...

Adding error handling

Handling errors in a structured and well-thought-out way is essential in a microservice landscape where a large number of microservices communicate with each other using synchronous APIs, for example, using HTTP and JSON. It is also important to separate protocol-specific handling of errors, such as HTTP status codes, from the business logic.

It could be argued that a separate layer for the business logic should be added when implementing the microservices. This should ensure that business logic is separated from the protocol-specific code, making it easier both to test and reuse. To avoid unnecessary complexity in the examples provided in this book, we have left out a separate layer for business logic, so the microservices implement their business logic directly in the @RestController components.

I have created a set of Java exceptions in the util project that are used by both the API implementations and the API clients, initially InvalidInputException...

Testing APIs manually

That concludes the implementation of our microservices. Let’s try them out by performing the following steps:

  1. Build and start the microservices as background processes.
  2. Use curl to call the composite API.
  3. Stop the microservices.

First, build and start up each microservice as a background process, as follows:

cd $BOOK_HOME/Chapter03/2-basic-rest-services/
./gradlew build

Once the build completes, we can launch our microservices as background processes to the Terminal process with the following code:

java -jar microservices/product-composite-service/build/libs/*.jar &
java -jar microservices/product-service/build/libs/*.jar &
java -jar microservices/recommendation-service/build/libs/*.jar &
java -jar microservices/review-service/build/libs/*.jar &

A lot of log messages will be written to the Terminal, but after a few seconds, things will calm down and we will find the following messages written...

Adding automated microservice tests in isolation

Before we wrap up the implementation, we also need to write some automated tests.

We don’t have much business logic to test at this time, so we don’t need to write any unit tests. Instead, we will focus on testing the APIs that our microservices expose; that is, we will start them up in integration tests with their embedded web server and then use a test client to perform HTTP requests and validate the responses. With Spring WebFlux comes a test client, WebTestClient, that provides a fluent API for making a request and then applying assertions on its result.

The following is an example where we test the composite product API by doing the following tests:

  • Sending in productId for an existing product and asserting that we get back 200 as an HTTP response code and a JSON response that contains the requested productId along with one recommendation and one review
  • Sending in a missing productId and asserting...

Adding semi-automated tests of a microservice landscape

Being able to automatically run unit and integration tests for each microservice in isolation using plain Java, JUnit, and Gradle is very useful during development, but insufficient when we move over to the operation side. In operation, we also need a way to automatically verify that a system landscape of cooperating microservices delivers what we expect. Being able to, at any time, run a script that verifies that a number of cooperating microservices all work as expected in operation is very valuable – the more microservices there are, the higher the value of such a verification script.

For this reason, I have written a simple bash script that can verify the functionality of a deployed system landscape by performing calls to the RESTful APIs exposed by the microservices. It is based on the curl commands we learned about and used above. The script verifies return codes and parts of the JSON responses using jq. The...

Summary

We have now built our first few microservices using Spring Boot. After being introduced to the microservice landscape that we will use throughout this book, we learned how to use Spring Initializr to create skeleton projects for each microservice.

Next, we learned how to add APIs using Spring WebFlux for the three core services and implemented a composite service that uses the three core services’ APIs to create an aggregated view of the information in them. The composite service uses the RestTemplate class in the Spring Framework to perform HTTP requests to APIs that are exposed by the core services. After adding logic for error handling to the services, we ran some manual tests on the microservice landscape.

We wrapped this chapter up by learning how to add tests for microservices in isolation and when they work together as a system landscape. To provide controlled isolation for the composite service, we mocked its dependencies to the core services using Mockito...

Questions

  1. What is the command that lists available dependencies when you create a new Spring Boot project using the spring init Spring Initializr CLI tool?
  2. How can you set up Gradle to build multiple related projects with one command?
  3. What are the @PathVariable and @RequestParam annotations used for?
  4. How can you separate protocol-specific error handling from the business logic in an API implementation class?
  5. What is Mockito used for?
lock icon The rest of the chapter is locked
You have been reading a chapter from
Microservices with Spring Boot 3 and Spring Cloud, Third Edition - Third Edition
Published in: Aug 2023 Publisher: Packt ISBN-13: 9781805128694
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime}