Microservices Implementation in Java

Last Updated on Jan 25, 2021

Microservices is a synonym for Service Oriented Architectural (SOA) style of constructing aggregation of many small loosely coupled services. When developing microservices with the Java programming language, you can use several microservices framework. Some of the frameworks are Spring Boot, Jersey, Dropwizard, Play Framework, and Restlet. DropWizard pulls together stable Java libraries in lightweight packages. We can also use them for our own applications. With the help of Restlet, developers can create fast and scalable web APIs that follows RESTful architecture pattern. In this document, we will implement a microservice “authenticate” with Spring Boot. Spring Boot is the most used and best Java Microservices framework since long.

The advantage of Spring Boot is that it has a vast infrastructure and has many spring boot projects working along. To create microservices with Spring Boot, you need to follow below mentioned 3 steps:

  • Setup new service
  • Expose the resource using RestController
  • Consume the service resource with RestTemplate

Here, we are going to create 3 different microservices in Java. First microservice is Discovery Server which is a Eureka server. Second microservice is Authentication Service which is Producer service and Third microservice is Consumer service which is discovery client. These microservices can find other microservices using its RestTemplate. Let’s start with developing these three microservices.

Developing Discovery Server

Service Discovery is used so that microservices can find each other. We use Eureka for our service discovery. Eureka, created by Netflix, provides service discovery with Spring Cloud. Folder Structure for Discovery server is as below:

Maven Dependency:

<parent>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-parent</artifactid>
    <version>1.5.3.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter</artifactid>
    </dependency>
    <dependency> <!-- Eureka registration server -->
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter-eureka-server</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
    </dependency>
</dependencies>
<dependencymanagement>
    <dependencies>
        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-dependencies</artifactid>
            <version>Camden.SR5</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencymanagement>

Application.yml:

eureka: # Configure this Discovery Server
    instance:
        hostname: localhost
    client: 
        registerWithEureka: false
        fetchRegistry: false
server: # HTTP (Tomcat) port
    port: 9000

To run Eureka registry service is easy, just define @EnableEurekaServer annotation to spring boot application.

@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DiscoveryServerApplication.class, args);
    }
}

After running this microservice, following output is available on localhost:9000:

Here in the application section of the image, there is no instance currently available with Eureka. After running Producer and Consumer microservice, we will able to see the instances in the Application section.

Developing Authentication Service

In this, we will create Login and Registration methods. We will use Spring Data JPA for querying MySQL database using method name convention. You can learn spring data JPA. Also in this, we will be hashing the password using Spring Security’s BCrypt algorithm. Folder Structure for Authentication service is as below:

Maven Dependency:

<dependencies>
    <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter-eureka</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-data-jpa</artifactid>
    </dependency>
    <dependency>
        <groupid>mysql</groupid>
        <artifactid>mysql-connector-java</artifactid>
    </dependency>
</dependencies>

Application.yml:

spring: # Service registers under this name
    application:
        name: authentication-service
    datasource: # MySql credentials
        url: jdbc:mysql://127.0.0.1:3306/test
        username: root
        password: root
    jpa: # JPA support
        show-sql: true
        hibernate:
            ddl-auto: validate
            use-new-id-generator-mappings: false
        properties:
            hibernate:
            dialect: org.hibernate.dialect.MySQLDialect
eureka: # Discovery Server Access
    client:
        serviceUrl:
            defaultZone: http://localhost:9000/eureka/
server: # HTTP Server (Tomcat) Port
    port: 9001

To define this microservice as Discovery Client, we need to include @EnableDiscoveryClient annotation to application.

@SpringBootApplication
@EnableDiscoveryClient
public class AuthenticationClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(AuthenticationClientApplication.class, args);
    }
}

We will create AuthenticationRepository to querying the database using JPA. To expose Authentication service, we use RestController. In the controller, @CrossOrigin annotation is used to pass data or get data from cross platforms like Angular.

@RestController
@CrossOrigin
public class AuthenticationController {
    @Autowired
    private AuthenticationRepository repo;
    @RequestMapping("/api/getUsers")
    public @ResponseBody List<userauthenticationbean> getUsers() {
        return repo.findAll();
    }
    @RequestMapping(value = "/api/addUser",method = RequestMethod.POST)
    public @ResponseBody UserAuthenticationBean addStudent(@RequestBody UserAuthenticationBean user) {   // Hashing the password using BCrypt of Spring Security 
        String hashed_password = BCrypt.hashpw( user.getPassword(), BCrypt.gensalt(12) ); 
        UserAuthenticationBean newuser = new UserAuthenticationBean();
        newuser.setUserName(user.getUserName());
        newuser.setPassword(hashed_password);
        return repo.save(newuser);
    }
    @RequestMapping(value = "/api/getUser" ,method = RequestMethod.POST)
    public @ResponseBody UserAuthenticationBean getByUser(@RequestBody UserAuthenticationBean user) {
        UserAuthenticationBean userget = repo.findByUserName(user.getUserName());
        // Comparing Hashed password with given password
        If ( BCrypt.checkpw( user.getPassword(), userget.getPassword() ) ){
            return userget;
        } return null;
    } 
}
</userauthenticationbean>

After running this microservice, you can fire rest call to this service on localhost:9001. Also, instance of this service gets registered in eureka server which is already running on localhost:9000.

Developing Consumer Service with Spring Cloud

In this service, we will use RestTemplate to consume the remote service resource. Also we use Spring Cloud’s Netflix support for load balancing. Load balancing is used to decide which service instance to use. Netflix Ribbon provides several algorithms for client-side load balancing. Folder Structure for Consumer service is as below:

Maven Dependency:

<dependencies>
    <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter-eureka</artifactid>
    </dependency>
    <dependency> <!-- Netflix Ribbon used for Load Balancing -->
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter-ribbon</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
    </dependency>
</dependencies>

Application.yml:

spring: # Service registers under this name
    application:
        name: consumer-service
eureka: # Discovery Server Access
    client:
        serviceUrl:
            defaultZone: http://localhost:9000/eureka/
server: # HTTP Server (Tomcat) Port
    port: 8081

You need to include RemoteRepository bean and RestTemplate bean in main application, so that this microservice can consume other microservices.

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerServiceApplication {
 
    public static final String AUTHENTICATION_SERVICE_URL = "http://AUTHENTICATION-SERVICE";
 
    public static void main(String[] args) {
        SpringApplication.run(ConsumerServiceApplication.class, args);
    }
 
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
 
    @Bean
    public AuthenticationRepository authenticationRepository(){
        return new RemoteAuthenticationRepository(AUTHENTICATION_SERVICE_URL);
    }
}

RemoteRepository will pass the HTTP request to the given Service URL and get the response from the remote service.

public class RemoteAuthenticationRepository implements AuthenticationRepository {
    @Autowired
    @LoadBalanced
    protected RestTemplate restTemplate;
    protected String serviceUrl;
 
    public RemoteAuthenticationRepository(String serviceUrl) {
        this.serviceUrl = serviceUrl.startsWith("http") ? serviceUrl : "http://" + serviceUrl;
    }
    @Override
    public List<userauthenticationbean> findAll() {
        UserAuthenticationBean[] users = restTemplate.getForObject(serviceUrl+"/api/getUsers", UserAuthenticationBean[].class);
        return Arrays.asList(users);
    }
 
    @Override
    public UserAuthenticationBean findByUserNameAndPassword(String userName, String password) {
        UserAuthenticationBean user= new UserAuthenticationBean(); 
        user.setPassword(password);
        user.setUserName(userName);
        return restTemplate.postForObject(serviceUrl + "/api/getUser",user,UserAuthenticationBean.class);
    }
 
    @Override
    public UserAuthenticationBean save(UserAuthenticationBean user) {
        return restTemplate.postForObject(serviceUrl + "/api/addUser", user, UserAuthenticationBean.class);
    }
}
</userauthenticationbean>

After running this service on localhost:8081, you can fire HTTP request from client side and request to this service will be passed to producer microservice, in our scenario Authentication service. Also, you will be able to see instance of this microservice in Eureka server on localhost:9000 as below:

Advantages of Microservices

Is it fair not to know the advantages of Microservices when we have discussed almost everything about it? Ideally not. Microservices are well-suited to agile development techniques and are designed to meet the growing demands of market for a more fluid information flow. It has the capability to offer many advantages such as

The deployment of Microservices works independently

Each microservice can be launched independently as needed, allowing for faster app upgrades and ongoing improvement. Specific development teams might be assigned to specific microservices, allowing them to concentrate completely on one service or functionality. As a result, teams may operate independently without having to worry about what’s going on in the rest of the programme.

Easily Scale an App with Microservices Architecture

It’s easier to scale an app with microservices architecture as demand grows. Rather than growing a full app, you may focus on the most important microservices. Scaling is also faster and more cost-effective as a result of this.

Microservices reduce downtime

If a single microservice fails, you may isolate it from the rest of the programme, preventing cascading failures that would cause it to crash. Because of this fault isolation, even if one of your important application’s modules fails, it can continue to function.

Coding is easier with micro codebase

Microservices have minimal codebases, which makes them easier to manage and deploy. It’s also a lot easier to keep the code clean and assign responsibility for certain services to teams.

Disadvantages of Microservices

While we know that Microservices are a blessing for the developer community, it would be incorrect to ignore the disadvantages of Microservices. This is for the users to know and understand the cons as well before implying within their business.

Microservices increase the Level of Complexity

Microservices allow you to use any technology, troubleshooting may become more difficult. It’s significantly more difficult to trace failures from one microservice to the next than it is in a single traditional application. This is especially true when each service has its own language, platform, monitoring tool, logging system, and other features. Performance issues can also be more difficult to resolve.

Adversely affect the development culture

While using microservices, businesses need to reorganize and distribute throughout all the services they’re working with because your team structure and dynamics have changed. This will not only take a lot of time and effort to figure out who should be where, but it may also create conflict if certain people are unhappy with the change or not. The leaders must grasp the changes and potential pain areas and then there is a great chance to improve the success of your organization.

Java Microservices need DevOps

Finally, microservices teams must work in highly automated environments, as some firms will have dozens of moving parts, which is impossible to manage manually. This will necessitate the adoption and utilization of DevOps tools such as Continuous Integration/Continuous Delivery (CI/CD) and distributed logging, tracing, monitoring, and visualization services.

Conclusion

To summarize, we understand about using microservices with Spring Boot Project. Also we learned some information on Eureka server and Netflix Ribbon for discovery service and Load balancing.

Comments


Your comment is awaiting moderation.

View Comments

  • In this article, the author describes microservices and their implementation in Java, highlighting both their advantages and disadvantages. While microservices offer significant benefits such as enhanced scalability and maintainability for applications, it's crucial to weigh the drawbacks before fully embracing this approach.

  • This comprehensive article delves into the creation of three distinct microservices using Java: Eureka Server (Discovery Server), Authentication Service (Producer Service), and Consumer Service (Discovery Client). It thoroughly explores both the advantages and disadvantages of microservices, making it an excellent resource for those seeking a deeper understanding of this architectural style. Highly recommended!

  • Till now, I think microservices are a blessing for the developer community, but when I go through this article, I read about the disadvantages of microservices, like how they increase the level of complexity, affect the development culture, and that Java microservices need DevOps. Thanks for the great read!

  • This blog post is well-written and informative. Microservices are a powerful architecture that can be used to build scalable, reliable, and maintainable applications. Java is a great language for microservices implementation, and there are several frameworks available to help developers with microservices implementation in Java. Thanks for sharing!

  • By reading this article, I learned about microservices implementation in Java. I also got some information on the Eureka server and Netflix Ribbon for discovery service and load balancing. Thanks for sharing!

  • This article explains Microservices implementation in Java and the advantages and disadvantages of microservices. Thank you for sharing this knowledge and helping the community understand the complexity of implementing microservices using Java.

  • As a java developer, this article helps me a lot to know about how to do microservices implementation in java. I will recommend this to my colleagues.

  • This blog is a valuable resource for developers who are interested in learning about microservices implementation with Java. It explains How use microservices with Spring Boot Project and provide some information on Eureka server and Netflix Ribbon for discovery service and Load balancing.

  • Thanks for sharing this article. I have learned how to implement Java microservices like the Discovery Server, Authentication Service, and Consumer Service through reading this article. Keep sharing!