How to create Microservices in Java using Spring — Step 5

Richy Great
6 min readJun 4, 2020

--

Photo by Justin Lim on Unsplash

This story is part of a series “Initial Commit till Running on Cloud”.

Remember the days when we wrote an entire application in a single repository and packaged it into a Jar or War. We even deployed to that single server our clients bought from IBM or Oracle. Scaling meant increasing RAM size and running the whole “Big Mac” application in all those new nodes you added in the name of horizontal scaling. At some point of time we decided not to do it anymore. “Enough” said the industry and Microservices were born.

Some may say that we are just doing distributed monolith, I will keep them in my prayers. So are you splitting a monolith into applications of simple and single responsibility? Buddy you started out alright, just go on. With this you have already achieved 2 major things for which microservices are known for

  1. Scalability, you are scaling only the service that needs scaling and not the entire app
  2. Isolation, your services are isolated now and so the failure of one does not bring your entire product down (At least for some degree)

Imagine you had an online shopping portal and found that the orders are coming in huge volumes during Corona times. Strangely user registration volume remains the same but orders are piling up. With monolith you will have user, order, email and whole lot of other services in the same application and you will scale the entire application which demands more classes being loaded and hence more RAM. Do you know how much a c5.xlarge (8 GB RAM) instance in AWS costs? Close to 0.2$ per hour. So you already added up 140$ to your monthly bill if you are running in AWS.

Imagine having order microservice carved out of this monolith and it runs in a t3a.small instance (2 GB RAM) with burstable CPU which can take on a sudden spike like this corona scenario. 0.0216$ per hour which will come around 15$ for a month. You have already achieved a great feat called “Cost Saving” with this microservices approach. Let the microservice evangelist talk about the article he read somewhere that popped up in his “Read recommendations”. We will march towards success.

Also if this order microservice goes down, new users are still getting registered without any issues. We are still in business bro ;) Don’t forget to inform the order microservices team though.

By book the definition of microservices goes like this

Microservices — also known as the microservice architecture — is an architectural style that structures an application as a collection of services that are

  • Highly maintainable and testable
  • Loosely coupled
  • Independently deployable
  • Organized around business capabilities
  • Owned by a small team

The microservice architecture enables the rapid, frequent and reliable delivery of large, complex applications. It also enables an organization to evolve its technology stack.

So are we not treading in the right way?

Spring for Microservices

With Spring Boot and Spring Cloud, creating a microservice is a few minute affair. One minute you are creating your pom.xml and the next you have a fully running application. Spring Boot contains embedded servers like Tomcat and Netty (For Non blocking IO which I love but makes no big difference under stress). Spring Boot also contains actuators which adds health and info endpoints. Health endpoint is needed for AWS Elastic Load Balancer to check if a target node is responsive. With Info endpoint we can view few important details like which version of the application is deployed. This is useful after a deployment.

Spring Cloud comes with a huge armory of awesome frameworks like Netflix OSS, Cloud stream etc. We will not be using much of Netflix OSS in this architecture because we are utilizing AWS for Load balancing. But we will use Spring cloud gateway for API gateway and Spring cloud stream for event driven architecture.

Checkout the project above and follow the commits to understand the step by step process of creating this microservice.

  1. Create a pom.xml with latest spring-boot-starter-parent as parent
  2. Add spring-boot-starter-web for Rest framework, spring-boot-starter-actuator for health and info endpoints. Finally spring-boot-starter-data-mongodb for Data operations
  3. Add an application.yml with server port 8081 and spring.data.mongodb.uri like we did for BFF. Please create separate database for each microservices, trust me on this one.
  4. Add a plain SpringBootApplication

I have created a user package to go by package by feature style.

After finishing user API

Creating User API

I have created 4 methods for handling CRUD operation on user entity and a list method which is paginated. The User entity will contain username which is the primary key, password which should be in encrypted format and list of roles e.g.: BUYER, ADMIN, SELLER etc.

We will create a simple user registration page which will contain only username and password. The roles has a single entry BUYER by default. So the UserModel which is our User API model is as given below.

@Data
public class UserModel {
@NotEmpty
private String username;
@NotEmpty
private String password;
@NotEmpty
private List<String> roles;
}

UserDocument is the mongo document for the same. We will separate the API data transfer objects and Mongo document objects in separate classes. This helps us in lot of ways, validation for example. We can ignore certain fields like password in JSON response and we can add additional attributes like creation timestamp and updation timestamp in UserDocument which might not be of any interest to API model.

@Data
@Document("user")
public class UserDocument {
@Id
private String username;
private String password;
private List<String> roles;
}

I have used a mapstruct mapper to map the model to entity and viz. After the project is built you will see a UserMapperImpl with implemented toModel and toDocument methods. So when you use Mappers.getMapper(UserMapper.class) you will get this generate implementation instance.

@Mapper
public interface UserMapper {
UserModel toModel(UserDocument userDocument);

UserDocument toDocument(UserModel userModel);
}

For Repository I have used MongoRepository provided by Spring.

public interface UserRepository extends MongoRepository<UserDocument, String> {
}

Service class has CRUD methods and a listUsers method for paged retrieval.

To finish it of with a pinch of salt, we have the Rest controller with CRUD capability. Also a list method to call service class methods and returns a 200 Http status code on success.

As you can see from the API endpoint url it is versioned and has a prefix /api. Also the name I prefer to be in plural as the Get call to /api/v1/users means we are getting users and not a single user. If we are representing a single user then we have id in the url path. I personally think this is more than enough for a rest endpoint and there is no need to complicate it using HATEOAS.

I prefer creating the service and rest controller manually instead of seeking the help of some framework like spring-data-rest because we will add some more code in this to push events to Kafka topics on CRUD operation on User.

Now run our user-microservice and check http://localhost:8081/actuator/health and http://localhost:8081/actuator/info endpoints. Try our API using http://localhost:8081/swagger-ui.html

Cool, yeah? We will create an API gateway in our next step and then deploy stuff on cloud to see our architecture come to life.

Going good? Please read the next part of this series. Also kindly leave your feedback :)

--

--

Richy Great
Richy Great

Written by Richy Great

Father, Software Developer, Tech founder and a Story teller

No responses yet