Spring Boot vs LoopBack – Node.js for developing Microservices


In this post, we will see comparison between Spring Boot and LoopBack – Node.js for implementing Microservices.

SpringBoot

Spring Boot is an open source Java-based framework used to create Microservices. It is developed by Pivotal Team and is used to build stand-alone and production ready spring applications.

Microservices architecture using Java Spring Boot

LoopBack – Node.js

Events and event-driven programming

Events are actions generated by the user or the system, like a click, a completed file download, or a hardware or software error.

Event-driven programming is a programming paradigm in which the flow of the program is determined by events. An event-driven program performs actions in response to events. When an event occurs it triggers a callback function.

Node.js is a platform that executes server-side JavaScript programs that can communicate with I/O sources like file systems and networks.

LoopBack

LoopBack is a highly extensible, open-source Node.js and TypeScript framework based on Express that enables you to quickly create APIs and microservices composed from backend systems such as databases and SOAP or REST services.

The diagram below demonstrates how LoopBack serves as a composition bridge between incoming requests and outgoing integrations. It also shows the different personas who are interested in various capabilities provided by LoopBack.

Advantages of LoopBack – Node.js and Spring Boot

LoopBack – Node.js Spring Boot
Lightweight, fast – loosely typed Java is statically-typed (type safety)
Javascript Community: growing rapidly Java Community: mature and thriving
Great for I/O tasks. Example: file writing and reading, network calls, Streaming Long-term support and maintainability for memory intensive applications
Single-threaded – low memory utilization Support for multi-threading
npm is constantly growing Many easily usable dependencies using Maven, Gradle

Disadvantages of LoopBack – Node.js and Spring Boot

LoopBack – Node.js

  • Doesn’t support multi-threading
  • Lack of strict type checking can lead to runtime problems
  • Not great for heavy computing – performance bottlenecks

Spring Boot

  • High memory utilization
  • Java is verbose
  • Contains lots of boilerplate code which makes debugging tough
  • May include unused dependencies – huge deployment binary file size.

Industry Usage of these technologies

Companies using Spring Boot

  • Amazon
  • Intuit
  • JP Morgan Chase & Co.
  • Capital One
  • Google
  • Microsoft

Companies using Node.js

  • FlightOffice
  • Symantec
  • Pen Systems
  • GoDaddy.com
  • Sapient

LoopBack vs SpringBoot on various parameters

Criteria / Parameter SpringBoot LoopBack
Performance Long-term support and maintainability for memory intensive applications Great for I/O tasks. Example: file writing and reading, network calls, Streaming
Circuit Breaker Resilience4j Opossum
Hystrix Levee
Soap Client Apache CXF, Camel, Spring WebServiceTemplate loopback-connector-soap
JSON Manipulation/Validation Jackson, Spring Validator payload-validator
Orchestration and Routing support Apache CXF, Camel, Spring WebServiceTemplate, RestTemplate loopback-connector-soap, loopback-connector-rest
Caching support Spring Cache, external cache support Interception – CachingService, external cache support
Open API Contract first, API first both are supported Contract first, API first both are supported
Recommended For Building applications which consists of Memory intensive tasks Building applications which consists of I/O intensive tasks

References:

Spring Boot and Netflix Eureka Integration


In this post we will learn how to integrate applications developed in Spring Boot with Netflix Eureka.

First step is to create two Spring Boot application services

  • customer-service
  • order-service

Go to https://start.spring.io and create order-service app using below config details.

Mainly for our use case, adding Spring Web, Eureka Server dependencies are the required ones

Likewise, create customer-service app with same config details used for order-service by adding Spring Web, Eureka Server dependencies.

Next, create eureka-server app with below config . Adding Eureka Server is main important config for our use case

Next, Import the projects created from the above into Eclipse IDE.

Add @EnableEurekaServer on EurekaServerApplication class as shown Below

package com.venkat;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}

Add below properties to the application.properties

server.port=8090
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

Next, Add @EnableEurekaClient on CustomerServiceApplication class in customer-service  app as shown below

@SpringBootApplication
@EnableEurekaClient
public class CustomerServiceApplication {
public static void main(String[] args) throws RestClientException, IOException {
SpringApplication.run(CustomerServiceApplication.class, args);
}

@Bean
public ConsumerControllerClient consumerControllerClient()
{
return new ConsumerControllerClient();
}
}

Likewise, Add @EnableEurekaClient on OrderServiceApplication class in order-service app as shown below

@SpringBootApplication
@EnableEurekaClient
public class OrderSerivceApplication {

public static void main(String[] args) {
SpringApplication.run(OrderSerivceApplication.class, args);
}
}

Next, Add below configuration in customer-service and order-service
application.properties files

customer-service

spring.application.name=customer-service
server.port=8091
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka

order-service

spring.application.name=order-service
server.port=8080
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka

Next, Create Order.java in model package as shown below with orderId, itemName, itemType, Cost attributes.

package com.venkat.model;

public class Order {
private String orderId;
private String itemName;
private String itemType;
private double cost;

public Order() {
}

public String getOrderId() {
return orderId;
}

public void setOrderId(String orderId) {
this.orderId = orderId;
}

public String getItemName() {
return itemName;
}

public void setItemName(String itemName) {
this.itemName = itemName;
}

public String getItemType() {
return itemType;
}

public void setItemType(String itemType) {
this.itemType = itemType;
}

public double getCost() {
return cost;
}

public void setCost(double cost) {
this.cost = cost;
}
}

Create OrderController with a REST GET mapping for /customerorder to return Order object

package com.venkat.controllers;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.venkat.model.Order;

@RestController
public class OrderController {

@RequestMapping(value = "/customerorder", method = RequestMethod.GET)
public Order customerOrder() {
Order order = new Order();
order.setOrderId("TIF567");
order.setItemName("Dosa");
order.setItemType("Tiffin");
order.setCost(40.00);
return order;
}
}

Create a ConsumerControllerClient.java class as shown below

package com.venkat.controllers;

import java.io.IOException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

@RestController
public class ConsumerControllerClient {

@Autowired
private DiscoveryClient discoveryClient;

@GetMapping(path="/customerorderinfo")
public String getCustomerOrder() throws RestClientException, IOException {

List<ServiceInstance> instances = discoveryClient.getInstances("ORDER-SERVICE");

// Creating URL for calling order-service
ServiceInstance serviceInstance = instances.get(0);
String baseURL = serviceInstance.getUri().toString();
String completeURL = baseURL + "/customerorder";

// Calling order-service
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = null;
try {
response = restTemplate.exchange(completeURL, HttpMethod.GET, getHeaders(), String.class);
} catch (Exception ex) {
System.out.println(ex);
}
System.out.println(response.getBody());
return response.getBody();
}

private static HttpEntity<?> getHeaders() throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
return new HttpEntity<>(headers);
}

}

Final step is to Run EurekaServer, order-service, customer-service apps

Open http://localhost:8090 (port on which eureka server is running). Here you will see
order-service,customer-service app instances registered with it.

Output on hitting REST Endpoint http://localhost:8091/customerorderinfo is given below

Conclusion

In the above post we have seen how to register two service applications with Netflix Eureka
Server and communicate between the services via Eureka server registry without knowing the
host, port info of the service to which we are communicating with.