Microservices with Spring Boot and Spring Cloud Developer Tutorial

In this developer tutorial, we are going to understand the basic concepts of microservices, in what ways microservice architectures are better than monolithic ones, and how we can implement a microservice architecture using Spring Boot and Spring Cloud.

Let’s start from the beginning.

What are Microservices?

There isn’t one universally accepted definition for microservices, but for this tutorial we are going to define microservices as an architectural style for building a suite of autonomous, self-contained and loosely coupled services that communicate over lightweight mechanisms, such as HTTP resource APIs.

 

Characteristics of Microservices

• Autonomous: Microservices are self-contained and can be developed and deployed independently without affecting other services.

• Specialized: Each microservice is designed for one specific capability.

• Stateless: Microservices don’t share the state of the service; in some cases, if there is a requirement to maintain state, it will be maintained in a database.

• Well-defined interfaces (service contract): Microservices have well-defined interfaces that permit communication with them, such as a JSON schema or WSDL.

 

Monolithic vs. Microservices

 

Monolith vs Microservices

 

Monolithic architectures have all processes tightly coupled, and they run as a single service.

 

Monolithic vs Microservices

Which one Should I Implement?

If you want to build a simple, lightweight application, the monolithic architecture can be an option, but if you prefer to develop complex and evolving software, the microservices architecture will definitely be the best choice. In the end, selecting the software architecture will depend entirely on your project size, time, and requirements, among other factors.

 

Creating our Microservices Architecture

Miscroservices-Architecture

Spring Cloud Netflix Eureka Server

This is an application that stores all the information about all the microservices. In other words, Eureka is a dynamic service discovery; every microservice will be registered in the server so that Eureka will know all the client applications running on each port and IP address.

Eureka consists of a server and a client-side component. The server component will be the registry in which all the microservices register their availability. The microservices will use the Eureka client to register; once the registration is complete, it reaches out to the server and notifies it of its existence. It is important to understand that the consuming components will also use the client to discover the service instances.

 

How does Eureka works

Image from oreilly.com

Setting up the Eureka Server

First, we are going to create a new Maven project with Spring Boot; we can create our project using the https://start.spring.io/ page. The project structure should look like this:

Eureka project structure

Once we’ve created the project, we are going to make sure that we have the “spring-cloud-starter-config” and “spring-cloud-starter-netflix-eureka-server” dependencies. Your pom.xml should look like this:

In this guide, we are going to create the Eureka server in stand-alone mode, so we are going to point the Eureka default zone to our stand-alone instance.

To set up our Eureka server, we need to follow these steps:

1. Add the following Eureka configuration to the “application.properties”:

a. Eureka server name

b. Server port

c. Additional configuration

 

2. Change the default “Application.java” to “EurekaServerApplication.java”. In this class, we need to add the “@EnableEurekaServer” annotation:

 

3. Start the Eureka server, running the application as a Spring Boot app. Once the application starts, we can open the Eureka console, which is going to be hosted in the server port we previously defined in the application properties.

 Eureka console log

 

Eureka web console link:  http://localhost:8761/

 

Eureka Web Console

 

Note: As you can see, there is no instance registered under the “instances currently registered with Eureka” section. This is because we haven’t registered any microservices as a client yet.

Register Microservices as Eureka Clients

In this section, we are going to be creating our product, order and authentication microservices. In order to do so, follow these 8 steps:

1. Just as we did with the Eureka service, we are going to create three new Spring Boot applications (order, product, authentication), and we are going to make sure we have the following dependencies in all the pom.xml files:

 

2. Once we have the microservices, we need to add the “@EnableEurekaClient” annotation in the default “Application.java” for each service.

Product Application

 

Order Application

 

Authentication Application

 

3. Then, in the application properties file, we define the Eureka client configurations:

Product Application

 

Order Application

 

Authentication Application

 

4. In this example, we are going to call the “products” service within the “order” service. To achieve this, we are going to use an object that is capable of sending requests to other REST API services: the Spring RestTemplate.

This object is a load balancer client; in this guide, we are going to be using the Netflix Eureka default load balancer called “Ribbon.” In order to do this, we are going to be registering a RestTemplate as a “bean,” a method-level annotation allowing the Java “config” to execute and register the return value of the methods annotated with “@Bean.” Once we have that annotation, we are going to be adding the “@LoadBalance” annotation to the “OrderApplication.java” class:

 

5. Create the controllers for each service.

5.1 Product Service

ProductController.java

 

5.2 Order Service

OrderController.java

 

5.3 Authentication Service

AuthenticationController.java

 

6. Your project’s structure should look like the following screenshot:

Service Final Structure

 

7. Start all services, including the Eureka server.

8.  Go to the Eureka server web console. Now, you can see we have all the order, product and authentication instances up and running:

Eureka Web Console with clients

Setting up a Zuul Proxy as the API Gateway

Zuul is the Spring Cloud embedded gateway service. Why do we need it? In most microservice implementations, only a few endpoints are public; the other ones are kept as private services. Zuul is going to act as an intermediate layer between the user and those public services.

1. First, we are going to create another Spring Boot application. The project structure should look like this:

Zuul Structure

 

2. Once we’ve created the project, we are going to make sure that we have the “spring-cloud-starter-netflix-eureka-client” and “spring-cloud-starter-netflix-zuul” dependencies. Your pom.xml should look like this:

 

 

3. The next step is to integrate the API gateway with Eureka and map the product, order and authentication services. For this specific case, we are going to be using the “application.yml” instead of the “application.properties”:

 

4. Edit “Application.java” to add the “@EnableZuulProxy” and the “@EnableEurekaClient” annotation to tell our gateway application that this is the Zuul proxy and that it is a Eureka client.

 

5. Run the application, making sure that the Eureka server is already running.

6. Go to the Eureka server web console. Now, you can see we have all the order, product, authentication and Zuul gateway instances up and running:

Eureka Web Console with zuul

Testing our Microservices

At this point, we have a Eureka server, three services (the order, product and the authentication), and a Zuul proxy. All of them are up and running.

To test our microservices, we have to send a request to the gateway, adding the path of the specific service. For example: http://localhost:8762/orders/order

Service test

Once you hit that specific URL using POST, you should see the following message:

Order Controller, Port: 8300

If you hit that specific URL using GET, you should see the following message:

Order Controller, Port: 8300 Product Controller, Port: 8200

 

Setting up Authentication with Spring Security

The idea of setting up JWT authentication in the gateway is to prevent all unauthenticated requests to specific services. There are a lot of ways to implement JWT token validators; in this example, I will be using the Amazon Cognito JWT configuration that I previously explained in my Java Integration with Amazon Cognito blog post, but you can use any other JWT configuration.

In order to achieve this, we need to follow these steps:

1. Import all the dependencies and create all of the JWT config classes and the JWT filter. Remember to ensure a single execution of our JWT filter; it must extend from “OncePerRequestFilter”.

2. Create the “WebSecurityConfigurerAdapter” with our security configurations.

 

 

3. Add the “web ignores” to the web security to accept the authentication request without the JWT token validation. Add the following method to “WebSecurityConfigurerAdapter.java”:

 

Remember that we set the authentication path for the authentication service on “application.yml”; that is why we are setting the path “/authentication” on the “web ignore.”

Testing our JWT Authentication

1. Hit the URL “http://localhost:8762/orders/order” using POST; you should see the following message:

 

2. Once you have implemented the JWT token “config” classes on the gateway and the authentication service, you will get a response similar to this one:

Postman Auth

 

3. Copy the access token generated by your authentication service and pass it to the order service request.

Order Token Setup

 

 

4. Execute the order request again (http://localhost:8762/orders/order), and now you should see the following message:

Order Controller, Port: 8300 Product Controller, Port: 8200

Conclusion

The main purpose of this blog post was to show the costs and benefits of creating monolithic and microservice architectures, in addition to demonstrating how we can create a microservice architecture using Spring Boot and Spring Cloud.

Spring Boot allows you to create both architectures; as we have seen in this post, creating microservices with Spring Boot is really easy, and it provides an effective way to build and maintain them. On the other hand, Spring Cloud makes managing the additional complexity of the service registries and load balancing easier to understand and perform.

In the end, choose the architecture that best suits your context and requirements. Stick to the architecture you can live with!

Subscribe to our Blog

Illary Huaylupo
Illary Huaylupo
Illary is a backend developer and has been working as a software engineer since 2007. She graduated from Cenfotec University and is currently working on a master’s degree in business administration with an emphasis on IT Management.

Deliver off-the-chart results.

WordPress Video Lightbox Plugin