Apache Kafka vs RabbitMQ


RabbitMQ is an open-source message-broker software that originally implemented the Advanced Message Queuing Protocol (AMQP) and has since been extended with a plug-in architecture to support Streaming Text Oriented Messaging Protocol (STOMP), MQ Telemetry Transport (MQTT), and other protocols.

Written in Erlang, the RabbitMQ server is built on the Open Telecom Platform framework for clustering and failover. Client libraries to interface with the broker are available for all major programming languages. The source code is released under the Mozilla Public License.

Messaging

In RabbitMQ, messages are stored until a receiving application connects and receives a message off the queue. The client can either ack (acknowledge) the message when it receives it or when the client has completely processed the message. In either situation, once the message is acked, it’s removed from the queue.

unlike most messaging systems, the message queue in Kafka is persistent. The data sent is stored until a specified retention period has passed, either a period of time or a size limit. The message stays in the queue until the retention period/size limit is exceeded, meaning the message is not removed once it’s consumed. Instead, it can be replayed or consumed multiple times, which is a setting that can be adjusted.

Protocol

RabbitMQ supports several standardized protocols such as AMQP, MQTT, STOMP, etc, where it natively implements AMQP 0.9.1. The use of a standardized message protocol allows you to replace your RabbitMQ broker with any AMQP based broker.

Kafka uses a custom protocol, on top of TCP/IP for communication between applications and the cluster. Kafka can’t simply be removed and replaced, since its the only software implementing this protocol.

The ability of RabbitMQ to support different protocols means that it can be used in many different scenarios. The newest version of AMQP differs drastically from the officially supported release, 0.9.1. It is unlikely that RabbitMQ will deviate from AMQP 0.9.1. Version 1.0 of the protocol released on October 30, 2011 but has not gained widespread support from developers. AMQP 1.0 is available via plugin.

Pull vs Push approach

RabbitMQ is push-based, while Kafka is pull-based. With push-based systems, messages are immediately pushed to any subscribed consumer. In pull-based systems, the brokers waits for the consumer to ask for data. If a consumer is late, it can catch up later.

Routing

RabbitMQ’s benefits is the ability to flexibly route messages. Direct or regular expression-based routing allows messages to reach specific queues without additional code. RabbitMQ has four different routing options: direct, topic, fanout, and header exchanges. Direct exchanges route messages to all queues with an exact match for something called a routing key. The fanout exchange can broadcast a message to every queue that is bound to the exchange. The topics method is similar to direct as it uses a routing key but allows for wildcard matching along with exact matching.

Kafka does not support routing; Kafka topics are divided into partitions which contain messages in an unchangeable sequence. You can make use of consumer groups and persistent topics as a substitute for the routing in RabbitMQ, where you send all messages to one topic, but let your consumer groups subscribe from different offsets.

Message Priority

RabbitMQ supports priority queues, a queue can be set to have a range of priorities. The priority of each message can be set when it is published. Depending on the priority of the message it is placed in the appropriate priority queue. Here follows a simple example: We are running database backups every day, for our hosted database service. Thousands of backup events are added to RabbitMQ without order. A customer can also trigger a backup on demand, and if that happens, a new backup event is added to the queue, but with a higher priority.

A message cannot be sent with a priority level, nor be delivered in priority order, in Kafka. All messages in Kafka are stored and delivered in the order in which they are received regardless of how busy the consumer side is.

License

RabbitMQ was originally created by Rabbit Technologies Ltd. The project became part of Pivotal Software in May 2013. The source code for RabbitMQ is released under the Mozilla Public License. The license has never changed (as of Nov. 2019).

Kafka was originally created at LinkedIn. It was given open-source status and passed to the Apache Foundation in 2011. Apache Kafka is covered by the Apache 2.0 license. 

Maturity

RabbitMQ has been in the market for a longer time than Kafka – 2007 & 2011 respectively. Both RabbitMQ and Kafka are “mature”, they both are considered to be reliable and scalable messaging systems.

Ideal use case

Kafka is ideal for big data use cases that require the best throughput, while RabbitMQ is ideal for low latency message delivery, guarantees on a per-message basis, and complex routing.

Summary

ToolApache KafkaRabbitMQ
Message orderingMessages are sent to topics by message key.
Provides message ordering due to its partitioning.
Not supported.
Message lifetimeKafka persists messages and is a log, this is managed by specifying a retention policyRabbitMQ is a queue, so messages are removed once they are consumed, and acknowledgment is provided.
Delivery GuaranteesRetains order only inside a partition. In a partition, Kafka guarantees that the whole batch of messages either fails or passes.Atomicity is not guaranteed
Message prioritiesNot supportedIn RabbitMQ, priorities can be specified for consuming messages on basis of high and low priorities

References

Apache Kafka vs IBM MQ


Message Queue (MQ)

A Message Queue (MQ) is an asynchronous service-to-service communication protocol used in microservices architectures. In MQ, messages are queued until they are processed and deleted. Each message is processed only once. In addition, MQs can be used to decouple heavyweight processing, buffering, and batch work.

Apache Kafka

Apache Kafka was originally developed at Linkedin as a stream processing platform before being open-sourced and gaining large external demand. Later, the Kafka project was handled by the Apache Software Foundation. Today, Apache Kafka is widely known as an open-source message broker and a distributed data storage platform written in Scala.

It provides services in a distributed, highly scalable, elastic, fault-tolerant, and secure manner. Options are available to self manage your kafka environments or fully managed services offered by vendors. It can be deployed on bare-metal hardware, virtual machines, and containers in on-premise as well as cloud environments.

IBM MQ

IBM MQ is a messaging middleware that integrates various business applications and data across multiple platforms faster and easier. It provides enterprise-grade messaging capabilities with a proven record for expertly and securely moving data. Indeed, apps can communicate with the aid of IBM MQ. By transmitting message data via messaging queues, IBM MQ makes exchanging information easier for applications, services, systems, and files. This dramatically simplifies the process of developing and maintaining business applications.

Additionally, IBM MQ fits into several environments, such as on-premise, cloud, and hybrid cloud deployments, and is compatible with a broad range of computing systems. It also offers a global messaging backbone with a service-oriented architecture (SOA).

Integration

Initial set up for both IBM MQ & Kafka is straightforward and has good documentation & community support

Communication

Pull based communication is used in Kafka where receiving system send a message request to producing system. IBM MQ utilizes push based communication where it pushes the message to the queue where any receiver can consume at the same time from multiple systems

Cost

Kafka is an open-source solution. IBM MQ is a paid platform. IBM MQs has good customer support. Kafka on the other hand provides paid assistance based on subscription system but there is good open-source community as it is fairly popular messaging solutions

Security

IBM MQ offers a range of advanced capabilities such as enhanced granular security and message simplification capability while Apache Kafka do not. However, both provide superior security features to build data sensitive, mission critical applications

In Apache Kafka, messages are not erased once the receiving system has read them. Hence, it is easier to log events

Performance

  • Both Kafka and MQ can be horizontally scaled. But Kafka is more scalable with the number of consumers as it uses the single log file for all consumers
  • IBM MQ is suited for applications which require high reliability and do not tolerate message loss where as Kafka is suited for applications which requires high throughput
  • Apache Kafka can get a message from one system to it’s receiver quickly compared to traditional message queue tools, but each receiver must make a request for the message, rather than the producing system placing the message into an accessible queue.  Additionally, while Apache Kafka can be used to log events and scales well, it doesn’t include as many granular features for security and message simplification. 

References

Spring Cloud Sleuth & Zipkin – Distributed Logging and Tracing


In standard applications, app logs are implemented into a single file which can be read for debugging purposes. However, apps which follows microservices architecture style comprises multiple small apps and multiple log files are to maintained to have at least one file per microservice. Due to this , identification and correlation of logs to a specific request chain becomes difficult.

For this, distributed logging & tracing mechanism can be implemented using tools like Sleuth, Zipkin, ELK etc

How to use Sleuth?

Sleuth is part of spring cloud libraries. It can be used to generate the traceid, spanid and add this information to the service calls in headers and mapped diagnostic context (MDC). These ids can be used by the tools such as Zipkin, ELK to store, index and process the log file.

To use sleuth in the app, following dependencies needs to be added

<dependency> 
<groupId>org.springframework.cloud</groupId> 
<artifactId>spring-cloud-starter-sleuth</artifactId> 
</dependency>

How to use Zipkin?

Zipkin contains two components

  • Zipkin Client
  • Zipkin Server

Zipkin client contains Sampler which collects data from ms apps with the help of sleuth and provides it the zipkin server.

To use zipkin client following dependency needs to be added in the application

<dependency> 
<groupId>org.springframework.cloud</groupId> 
<artifactId>spring-cloud-starter-zipkin</artifactId> 
</dependency>

To use zipkin server, we need to download and set up the server in our system

zipkin server

Implementation on microservice apps

To see distributed logging implementation, we need to create three services with the same configuration, the only difference has to be the service invocation details where the endpoint changes.

  • Create services as Spring boot applications with WebRest RepositoryZipkin and Sleuth dependencies.
  • Package services inside a single parent project so that three services can be built together. Also, I’ve added useful windows scripts in github repo to start/stop all the services with a single command
  • Below is one rest controller in service1 which exposes one endpoint and also invokes one downstream service using the RestTemplate. Also, we are using Sampler.ALWAYS_SAMPLE that traces each action.

Service 1

package com.mvtechbytes.service1;
 
import brave.sampler.Sampler;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
 
@SpringBootApplication
public class Service1Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Service1Application.class, args);
    }
}
 
@RestController
class Service1Controller {

    private static final Logger LOG = Logger.getLogger(Service1Controller.class.getName());
     
    @Autowired
    RestTemplate restTemplate;
 
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
 
    @Bean
    public Sampler alwaysSampler() {
        return Sampler.ALWAYS_SAMPLE;
    }
     
    @GetMapping(value="/service1")
    public String service1() 
    {
        LOG.info("Inside Service 1..");         
String response = (String)   restTemplate.exchange("http://localhost:8082/service2", HttpMethod.GET, null, new ParameterizedTypeReference<String>() {}).getBody();
        return response;
    }
}

Appication Configuration

As all services will run in a single machine, so we need to run them in different ports. Also to identify in Zipkin, we need to give proper names. so configure the application name and port information in application.properties file under the resources folder.

application.propertiesserver.port = 8081
spring.application.name = zipkin-server1

Similarly, for the other 2 services, we will use ports 8082, 8083 and their name will also be zipkin-server2 and zipkin-server3

Also, we have intentionally introduced a delay in the second service so that we can view that in Zipkin.

Above project is available in below github location

Github repo : https://github.com/mvtechbytes/Zipkin-Sleuth

On running app using bat files

Find Traces
Individual Trace
Trace details

References

Apache FreeMarker for transformation between data formats


In this post, we will learn how to use Apache FreeMarker for data format transformations

What is Apache FreeMarker?

Apache FreeMarker is a template engine: a Java library to generate text output (HTML web pages, e-mails, configuration files, XML, JSON, source code, etc.) based on templates and changing data. Templates are written in the FreeMarker Template Language (FTL), which is a simple, specialized language (not a full-blown programming language like PHP). Usually, a general-purpose programming language (like Java) is used to prepare the data (issue database queries, do business calculations). Then, Apache FreeMarker displays that prepared data using templates. In the template you are focusing on how to present the data, and outside the template you are focusing on what data to present.

If your project needs you to transform between data formats like XML to JSON or vice versa. Such transformations can be accomplished using FreeMarker

Apache FreeMarker for Data Transformations

XML TO JSON Transformation using FreeMarker

We will use SpringBoot project created using Spring Initilizer. https://start.spring.io/

FreeMarker Transformations – Project Structure

Firstly add dependencies to pom.xml

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>
    <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1</version>
    </dependency>

    <dependency>
        <groupId>no.api.freemarker</groupId>
        <artifactId>freemarker-java8</artifactId>
        <version>1.3.0</version>
    </dependency>

    <dependency>
        <groupId>org.everit.json</groupId>
        <artifactId>org.everit.json.schema</artifactId>
        <version>1.5.1</version>
    </dependency>

Add XML to transform in src/main/resources folder – test.xml

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <employee>
        <id>30123</id>
        <name>Ben</name>
        <location>Toronto</location>
    </employee>
</data>

Add FTL Template in src/main/resources/templates folder – FTL file: xml2json.ftl

<#assign data = xml['child::node()']>
{
    "employee": {
        "id": ${data.employee.id},
        "name": "${data.employee.name}",
        "location": "${data.employee.location}"
    }
}

Create FmtManager to load and process template as below

package com.mvtechbytes.fmt;

import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;

import freemarker.cache.StringTemplateLoader;
import freemarker.ext.beans.BeansWrapperBuilder;
import freemarker.template.Configuration;
import freemarker.template.Template;

public class FmtManager {

    private Configuration freemarkerConfig;
    private static final String TEMPLATE_DIRECTORY = "src/main/resources/templates/";

    public FmtManager() {
        freemarkerConfig = new Configuration(Configuration.VERSION_2_3_23);
        freemarkerConfig.setTagSyntax(Configuration.ANGLE_BRACKET_TAG_SYNTAX);
        freemarkerConfig.setDefaultEncoding("UTF-8");
        freemarkerConfig.setNumberFormat("computer");
        freemarkerConfig.setObjectWrapper(new BeansWrapperBuilder(Configuration.VERSION_2_3_23).build());
        freemarkerConfig.setTemplateLoader(new StringTemplateLoader());
    }

    private Template loadTemplate(String templateName, String templatePath) {
        try {
            String templateContent = new String(Files.readAllBytes(Paths.get(templatePath)));
            ((StringTemplateLoader) freemarkerConfig.getTemplateLoader()).putTemplate(templateName, templateContent);
            return freemarkerConfig.getTemplate(templateName);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public String processTemplate(String templateName, Map<String, Object> data) {
        Template template = loadTemplate(templateName, TEMPLATE_DIRECTORY + templateName + ".ftl");
        try (StringWriter writer = new StringWriter()) {
            template.process(data, writer);
            return writer.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

After adding all the code in the respective folders. Execution of use case can be done using below static method with FmtManager bean injected

public static void xmlToJson(FmtManager templateManager) throws Exception {

        String xmlString = new String(Files.readAllBytes(Paths.get("src/main/resources/test.xml")));
        NodeModel xmlNodeModel = NodeModel.parse(new InputSource(new StringReader(xmlString)));

        Map<String, Object> data = new HashMap<>();
        data.put("xml", xmlNodeModel);

        String json = templateManager.processTemplate("xml2json", data);

        System.out.println(json);
 }

Execution Log Output:

12:48:44.926 [main] DEBUG freemarker.cache - TemplateLoader.findTemplateSource("xml2json"): Found
12:48:44.929 [main] DEBUG freemarker.cache - Loading template for "xml2json"("en_US", UTF-8, parsed) from "xml2json"
{
"employee": {
"id": 101,
"name": "Vikas",
"location": "Toronto"
}
}

JSONTOXML Transformation using FreeMarker

Add JSON to transform in src/main/resources folder – test.json

{
  "data": {
    "employee": {
      "empid": 2012,
      "empname": "Virat",
      "location": "Hyderabad"
    }
  }
}

Add FTL Template in src/main/resources/templates folder – FTL file: json2xml.ftl

<#-- @ftlvariable name="JsonUtil" type="de.consol.jbl.util.JsonUtil" -->
<#assign body = JsonUtil.jsonToMap(input)>
<?xml version="1.0" encoding="UTF-8"?>
<data>
    <employee>
        <id>${body.data.employee.empid}</id>
        <name>${body.data.employee.empname}</name>
     	<location>${body.data.employee.location}</location>
    </employee>
</data>

Create FmtJSONUtil – This to convert json to Java object

package com.mvtechbytes.fmt;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

public class FmtJsonUtil {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    public static Map<String, Object> jsonToMap(String json) throws IOException {
        return OBJECT_MAPPER.readValue(json, new TypeReference<HashMap<String, Object>>(){});
    }
}

After adding all the code in the respective folders. Execution of use case can be done using below static method with FmtManager bean injected

private static void jsonToXml(FmtManager templateManager) throws IOException, TemplateModelException {
		 String input = new String(Files.readAllBytes(Paths.get("src/main/resources/test.json")));

	        Map<String, Object> data = new HashMap<>();
	        data.put("input", input);

	        TemplateHashModel staticModels = new BeansWrapperBuilder(Configuration.VERSION_2_3_23).build().getStaticModels();
	        data.put("JsonUtil", staticModels.get(FmtJsonUtil.class.getName()));

	        String output = templateManager.processTemplate("json2xml", data);

	        System.out.println(output);
	}

Execution Log Output:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <employee>
        <id>2012</id>
        <name>Virat</name>
     	<location>Hyderabad</location>
    </employee>
</data>

Full sourcecode is available in below github link

https://github.com/malliktalksjava/FreeMarkerTransformations

References:

REST API Components – Standards and Design aspects


In this post, we will see the different REST API components w.r.t standards and design aspects

Query parameters and QueryString length in HTTP GET

Security Aspect:

Although officially there is no limit specified by RFC 2616, many security protocols and recommendations state that maxQueryStrings on a server should be set to a maximum character limit of 1024. While the entire URL, including the querystring, should be set to a max of 2048 characters. This is to prevent the Slow HTTP Request DDOS vulnerability on a web server. This typically shows up as a vulnerability on the Qualys Web Application Scanner and other security scanners.

Please see the below example code for Windows IIS Servers with Web.config:

<system.webServer>
<security>
    <requestFiltering>
        <requestLimits maxQueryString="1024" maxUrl="2048">
           <headerLimits>
              <add header="Content-type" sizeLimit="100" />
           </headerLimits>
        </requestLimits>
     </requestFiltering>
</security>
</system.webServer>

This would also work on a server level using machine.config.

Note: Limiting query string and URL length may not completely prevent Slow HTTP Requests DDOS attack but it is one step you can take to prevent it.

414 URI Too Long (RFC 7231):

The URI provided was too long for the server to process. Often the result of too much data being encoded as a query-string of a GET request, in which case it should be converted to a POST request. Called “Request-URI Too Long” previously.

Browser restrictions:

  • Microsoft Internet Explorer (Browser)
    Microsoft states that the maximum length of a URL in Internet Explorer is 2,083 characters, with no more than 2,048 characters in the path portion of the URL. Attempts to use URLs longer than this produced a clear error message in Internet Explorer.
  • Microsoft Edge (Browser)
    The limit appears to be around 81578 characters.
  • Chrome
    It stops displayingthe URL after 64k characters, but can serve more than 100k characters. No further testing was done beyond that.
  • Firefox (Browser)
    After 65,536 characters, the location bar no longer displays the URL in Windows Firefox 1.5.x. However, longer URLs will work. No further testing was done after 100,000 characters.
  • Safari (Browser)
    At least 80,000 characters will work. Testing was not tried beyond that.
  • Opera (Browser)
    At least 190,000 characters will work. Stopped testing after 190,000 characters. Opera 9 for Windows continued to display a fully editable, copyable and pasteable URL in the location bar even at 190,000 characters.
  • Apache (Server)
    Early attempts to measure the maximum URL length in web browsers bumped into a server URL length limit of approximately 4,000 characters, after which Apache produces a “413 Entity Too Large” error. The current up to date Apache build found in Red Hat Enterprise Linux 4 was used. The official Apache documentation only mentions an 8,192-byte limit on an individual field in a request.
  • Microsoft Internet Information Server (Server)
    The default limit is 16,384 characters (yes, Microsoft’s web server accepts longer URLs than Microsoft’s web browser). This is configurable.
  • Perl HTTP::Daemon (Server)
    Up to 8,000 bytes will work. Those constructing web application servers with Perl’s HTTP::Daemon module will encounter a 16,384 byte limit on the combined size of all HTTP request headers. This does not include POST-method form data, file uploads, etc., but it does include the URL. In practice this resulted in a 413 error when a URL was significantly longer than 8,000 characters. This limitation can be easily removed. Look for all occurrences of 16×1024 in Daemon.pm and replace them with a larger value. Of course, this does increase your exposure to denial of service attacks.

When to use @QueryParam versus @PathParam

REST may not be a standard as such, Most APIs tend to only have resource names and resource IDs in the path. Such as:

/departments/{dept}/employees/{id}

Some REST APIs use query strings for filtering, pagination and sorting, but REST isn’t a strict standard.

Recommendation is put any required parameters in the path, and any optional parameters should certainly be query string parameters. Putting optional parameters in the path will end up getting really messy when trying to write URL handlers that match different combinations.

When to use Headers versus URL parameters (PathParam or QueryParam)

GET /orders/view
(custom HTTP header) CLIENT_ID: 23

instead of

GET /orders/view/client_id/23 or
GET /orders/view/?client_id=23

The URL indicates the resource itself. A “client” is a resource that can be acted upon, so should be part of the base url: /orders/view/client/23.

Parameters are just that, to parameterize access to the resource. This especially comes into play with posts and searches: /orders/find?q=blahblah&sort=foo. There’s a fine line between parameters and sub-resources: /orders/view/client/23/active versus /orders/view/client/23?show=active. Recommendation is the sub-resource style and reserve parameters for searches.

Since each endpoint Represents a State Transfer (to mangle the mnemonic), custom headers should only be used for things that don’t involve the name of the resource (the url), the state of the resource (the body), or parameters directly affecting the resource (parameters). That leaves true metadata about the request for custom headers.

HTTP has a very wide selection of headers that cover most everything you’ll need. Where we could see custom headers which come up in a system to system request operating on behalf of a user. The proxy system will validate the user and add “X-User: userid” to the headers and use the system credentials to hit the endpoint. The receiving system validates that the system credentials are authorized to act on behalf of the user, then validate that the user is authorized to perform the action.

Custom headers have the following advantages:

  • Can be read easily by network tools/scripts (authentication, meta info)
  • Keeps urls free from security stuff (safer, not in browser/proxy caches)
  • Keeps urls cleaner: allows for better caching of resources

References:

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:

Algorithms in Java Interviews


In this post, we will see algorithm problems with their solutions which are asked during Java interviews.

How to check if a number is Palindrome?

void checkPalindrome(int n){
  int temp, sum = 0;
  int input=n;

  while(n>0) {
     temp = n%10;
     sum = (sum*10) + temp;
     n = n/10;
  }

  if(input == sum){
   System.out.println("Palindrome");
  } else {
   System.out.println("Not Palindrome");
  }
}

How to check if a number is Prime in Java8?

void checkPrime(int n) {
if(n > 1 && IntStream.range(2, n).noneMatch(i -> i%n==0)) {
System.out.println("Prime");
} else {
System.out.println("Non-Prime");
}
}

How to sort objects in reverse order in Java8?

Student student1 = new Student(372,"Venkat",1);
Student student2 = new Student(2,"Sachin",4);
Student student3 = new Student(2345,"Ganguly",6);
Student student4 = new Student(72,"Karthik",2);
List studlist = new CopyOnWriteArrayList();
studlist.add(student1);
studlist.add(student2);
studlist.add(student3);
studlist.add(student4);

// Iterate in Java8
studlist.forEach(s -> System.out.println(s.name));

// Sort by Ids
studlist.sort((Student s1,Student s2) -> s1.getId() - s2.getId());

// Sort by Rank in reverse Order
studlist.sort((Student s1,Student s2) -> s2.getRank() - s1.getRank());

Find second highest number in an Array?

int arr[] = {45,89, 29,1, 9, 100};
int highest = 0, secondHighest = 0;

for(int i=0; i<arr.length;i++) {   if(arr[i] > highest) {
     highest = arr[i];
  } else if(arr[i] > secondHighest) {
     secondHighest = arr[i];
  }
}

Find Nth highest Salary from a SQL Table?

SELECT MIN(SALARY) FROM EMPLOYEE
       WHERE SALARY IN (SELECT DISTINCT TOP N 
                               FROM EMPLOYEE ORDER BY SALARY desc);

Print Only Numerics from a String?

String sampleStr = "fdsha3430d3kdjafl0737434833";
String numericsOnlyStr = sampleStr.replaceAll("[^0-9]", "");

Print Duplicates in an Array?

for(int i=0;i<arr.length;i++) {
  for(int j=i+1; j< arr.length; j++) {
     if(arr[i] == arr[j]) {
           System.out.println(arr[j]);
     }
  }
}

Fetch Frequency of Elements repeated in an Array?

  Map<Integer, Integer> mp = new HashMap<>(); 
  
        // Iterating through array elements 
        for (int i = 0; i < n; i++) 
        { 
            if (mp.containsKey(arr[i]))  { 
                mp.put(arr[i], mp.get(arr[i]) + 1); 
            } else { 
                mp.put(arr[i], 1); 
            } 
        } 
        
        // Iterating through Map and Printing frequencies 
        for (Map.Entry<Integer, Integer> entry : mp.entrySet()) { 
            System.out.println(entry.getKey() + " " + entry.getValue()); 
        }

Find Triplets in an array whose sum is equal to n?

public class Triplets {
public static List<List> findTriplets(int[] numbers, int sum) {
List<List> tripletsCombo = new ArrayList<List>();
HashSet set = new HashSet();
List triplets = new ArrayList();

if (numbers.length == 0 || sum <= 0) {
   return tripletsCombo;
}

Arrays.sort(numbers);

for (int i = 0; i < numbers.length - 2; i++) {
int j = i + 1;
int k = numbers.length - 1;

while (j < k) {
   if (numbers[i] + numbers[j] + numbers[k] == sum) {
      String str = numbers[i] + "," + numbers[j] + "," +       numbers[k];
      // Check for the unique Triplet
      if (!set.contains(str)) {
               triplets.add(numbers[i]);
               triplets.add(numbers[j]);
               triplets.add(numbers[k]);
               tripletsCombo.add(triplets);
               triplets = new ArrayList();
               set.add(str);
     }
     j++;
     k--;
} else if (numbers[i] + numbers[j] + numbers[k] < sum) {    j++; } else { // numbers[i] + numbers[j] + numbers[k] > sum
   k--;
}
}
}

return tripletsCombo;
}

public static void main(String[] args) {
int[] numbers = { 2, 3, 1, 5, 4 };
int sum = 9;
List<List> triplets = findTriplets(numbers, sum);

if (triplets.isEmpty()) {
   System.out.println("No triplets are found");
} else {
   System.out.println(triplets);
}
}
}

How to check if two strings are Anagrams?

Two strings are called Anagrams if they contain same set of characters but in different order.  Examples:  “Astronomer – Moon starer”, “A gentleman – Elegant man”, “Dormitory – Dirty Room”, “keep – peek”.

void isAnagram(String input1, String input2) {
   //Removing all white spaces from s1 and s2
   String s1_nonSpaces = input1.replaceAll("\\s", "");
   String s2_nonSpaces = input2.replaceAll("\\s", "");

   boolean status = true;
   if(s1_nonSpaces.length() != s2_nonSpaces.length()) {
      status = false;
   } else {
      char[] s1Array = s1_nonSpaces.toLowerCase().toCharArray();
      char[] s2Array = s2_nonSpaces.toLowerCase().toCharArray();
      Arrays.sort(s1Array); 
      Arrays.sort(s2Array); 
      status = Arrays.equals(s1Array, s2Array);
   }
   System.out.print(status?"Anagrams":"Non-Anagrams");
}

Swap numbers without using temp/third variable?

void swapWithoutTemp(int a, int b) {
 a = a+b;
 b = a-b;
 a = a-b;
}

Find number of combinations for Sum of Two Elements from two arrays is equal to N?

We have two arrays of numbers, suppose we take one element from first array and another element from second array. Their sum should be equal to N(given number).

sumOfTwoElementsInTwoArrays() {
  int arr1[] = {4,8,10,12,7};
  int arr2[] = {6,90,34,45};

  int sumValue = 44; 
  HashSet complements = new HashSet();
  int pairCount = 0;

  for(int i=0;i<arr1.length;i++) {
    complements.add(arr1[i] - sumValue);
  }

  for(int j=0;j<arr1.length;j++) {
    if(complements.contains(arr2[j])) {
      pairCount++;
    }
 }

System.out.print("Number of pairs is "+pairCount);
}

First non repeated character in a String?

String str = "BANANA";
char firsNonRepeatedCharacter;
HashMap<Character, Integer> hmp = new HashMap<Character, Integer>();

for(int z=0;z<s.length();z++) {
  if(hmp.containsKey(str.charAt(z))) {
    hmp.put(str.charAt(z), hmp.get(str.charAt(z))+1);
  } else {
     hmp.put(str.charAt(z), 1);
  }
}

Set characterSet = hmp.keySet();
for(Character c:characterSet){
  if(hmp.get(c).toString()equals("1")) {
    firsNonRepeatedCharacter = c;
    break;
  }
}

Find the number of occurrence of an element in an array using Java8?

int b[] = {1,2,34,1};

List bList = Arrays.stream(b).boxed().collect(Collectors.toList());

System.out.println(bList.stream().filter(z -> z.toString().equalsIgnoreCase("1")).count());

100 doors toggle open/close

There are 100 doors in a row, all doors are initially closed. A person walks through all doors multiple times and toggle (if open then close, if close then open) them in following way:

In first walk, the person toggles every door, In second walk, the person toggles every second door, i.e., 2nd, 4th, 6th, 8th, …, In third walk, the person toggles every third door, i.e. 3rd, 6th, 9th, …

Find in nth walk, what will be the status of all doors

doorsOpenClosed(int no_of_walks) {
  int door_id, walk_id;
  int doors[] = new int[101];
  for(int i=0;i<100;i++) {
   doors[i] = 0;
  }

for (walk_id = 1; walk_id <= no_of_walks; walk_id++) {
  for (door_id = walk_id; door_id <= 100; door_id += walk_id) {
    if(door_id%walk_id == 0) {
      doors[door_id]=(doors[door_id] == 0)?1:0;
    }
  }
}

for (int j = 0; j <= 100; j++) {
 if(doors[j] == 1) {
   System.out.println("Open Door number::::"+j);
 }
}

}

Spring Boot and Zuul API Gateway Integration


In this post, we will learn how to integrate zuul api gateway to the application developed in microservices architecture.

Our application consists of below components

  • customer-service
  • order-service
  • eureka-server
  • zuul-service

We have already seen how to create customer-service, order-service, eureka-server in the previous post given below

https://malliktalksjava.com/2020/05/28/spring-boot-netflix-eureka-integration/

Let us start integrating zuul api gateway service to the above application.

Firstly, Go to https://start.spring.io , Create SpringBoot Application with below configuration. 

As shown above, Spring Web, Eureka Server, Zuul as dependencies needs to be added.

Second Step, Import the project in the Eclipse, go to application.properties and add below properties

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

Next step is to create following filters

  • ErrorFilter
  • PreFilter
  • PostFilter
  • RouteFilter

Below diagram depicts flow of Request & Response intercepted by Zuul filters

Zuul_FlowDFilters creation step 1: Create ErrorFilter by extending ZuulFilter and override methods and shown below

package com.venkat.filters;

import com.netflix.zuul.ZuulFilter;

public class ErrorFilter extends ZuulFilter {

@Override
public String filterType() {
        return "error";
}

@Override
public int filterOrder() {
       return 0;
}

@Override
public boolean shouldFilter() {
       return true;
}

@Override
public Object run() {
        System.out.println(" ############# Using Error Filter ##################");               
return null;
}

}

Filters creation step 2: Create PreFilter by extending ZuulFilter and override methods and shown below

package com.venkat.filters;
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

public class PreFilter extends ZuulFilter {

@Override
public String filterType() {
return "pre";
}

@Override
public int filterOrder() {
return 0;
}

@Override
public boolean shouldFilter() {
return true;
}

@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
System.out.println(" ############# In Pre Filter ################## ");
System.out.println(
"Request Method : " + request.getMethod() + " Request URL : " + request.getRequestURL().toString());

return null;
}

}

Filters creation step 3: Create PostFilter by extending ZuulFilter and override methods and shown below

package com.venkat.filters;

import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.common.io.CharStreams;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

public class PostFilter extends ZuulFilter {

@Override
public String filterType() {
return "post";
}

@Override
public int filterOrder() {
return 0;
}

@Override
public boolean shouldFilter() {
return true;
}

@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
System.out.println(" ############# In Post Filter ################## ");
try {
System.out.println(
"Response Status Code : " + ctx.getResponseStatusCode() + " Response Body : " + CharStreams.toString(new InputStreamReader(ctx.getResponseDataStream(), "UTF-8")));
} catch (IOException e) {

}

return null;
}

}

Filters creation step 4: Create RouteFilter by extending ZuulFilter and override methods and shown below

package com.venkat.filters;

import com.netflix.zuul.ZuulFilter;

public class RouteFilter extends ZuulFilter {

@Override
public String filterType() {
return "route";
}

@Override
public int filterOrder() {
return 0;
}

@Override
public boolean shouldFilter() {
return true;
}

@Override
public Object run() {
System.out.println("Using Route Filter");

return null;
}

}

Next, Add @EnableZuulProxy to ZuulProxyApplication class in zuul-service and add bean configurations for Filters which we have created as shown below

package com.venkat;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulProxyApplication {

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

@Bean
public PreFilter preFilter() {
return new PreFilter();
}

@Bean
public PostFilter postFilter() {
return new PostFilter();
}

@Bean
public ErrorFilter errorFilter() {
return new ErrorFilter();
}

@Bean
public RouteFilter routeFilter() {
return new RouteFilter();
}
}

Once we are done creating all the filters package structure of our
zuul-service will be as shown as shown below

Now we will see changes to done to the customer-service application to enable requests
pass via zuul-service filters.

Go to CusomerControllerClient.java in customer-service replace

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

with

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

and 

String completeURL = baseURL + "/customerorder";

with 

String completeURL = baseURL + "/order/customerorder";

Upon completion of all the code changes/additons discussed above run all the services, eureka-server, order-service, customer-service, zuul-service.

Following will be output once we hit the REST endpoint /customerorderinfo

zuul-service logs on hitting the REST end point are given below, clearly we can see both Request and Response pass through Pre, Route, Post Filters 

############# In Pre Filter ################## 
Request Method : GET Request URL : http://Dell:8079/order/customerorder
Using Route Filter
############# In Post Filter ##################
Response Status Code : 200 Response Body : {"orderId":"TIF567","itemName":"Dosa","itemType":"Tiffin","cost":40.0}
2020-05-31 18:56:18.494 INFO 3892 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
############# In Pre Filter ##################
Request Method : GET Request URL : http://Dell:8079/order/customerorder
Using Route Filter
############# In Post Filter ##################
Response Status Code : 200 Response Body : {"orderId":"TIF567","itemName":"Dosa","itemType":"Tiffin","cost":40.0}

Conclusion

In this post, we have seen how to configure Zuul-proxy and make requests from one microservice pass through customized zuul filters. These filters enable us to apply functionality to our edge service. These filters help us perform the following functions:

  • Authentication & Security – identifying authentication requirements for each resource and rejecting requests that do not satisfy them.
  • Monitoring – tracking data and statistics at the edge which gives us a view of production.
  • Dynamic Routing – dynamically routing requests to various back-end clusters.
  • Load Shedding – allocating capacity for each type of request and dropping requests that exceeds the limit set.
  • Stress Testing – increasing the traffic to a cluster to measure its performance.
  • Static Response handling – sending some responses directly at the edge instead of forwarding them to an internal cluster.

Related links:

References:

Core Java and Java 8 Concepts


In this post, you will see some important Core Java/Java 8 concepts related to Collections, Exception Handling, Multi-threading, Concurrency etc.

Comparable Vs Comparator

Comparable Comparator
Comparable provides a single sorting sequence. In other words, Sorting of  collection is based on a single property of a class such as ID, ItemName or quantity etc. The Comparator provides multiple sorting sequences. In other words, sorting of collection can based of multiple properties such as ID, ItemName, and quantity etc.
Comparable affects the original class, i.e., the actual class is modified. Comparator doesn’t affect the original class, i.e., the actual class is not modified.
Comparable provides compareTo() method to sort elements. Comparator provides compare() method to sort elements.
Comparable is from  java.lang package. A Comparator is from java.util package.
Sorting list of Objects-Comparable type can be done using Collections.sort(List) method. Sorting list of Objects-Comparator type by Collections.sort(List, Comparator) method.

JVM Architecture

Different types of Class Loaders?

  • Bootstrap class Loader
  • Extensions class Loader
  • System class Loader

Boostrap class loader loads the classes from jdk/jre/lib/rt.jar. Extension class loader loads the classes from jdk/lib/ext folder jars. System class loader loads the classes from CLASSPATH.

Difference between ClassNotFoundException and NoClassDefFoundError

  • ClassNotFoundException is an Exception, while NoClassDefFoundError is an Error.
  • ClassNotFoundException occurs when CLASSPATH does not get updated with required JAR files while NoClassDefFoundError occurs when required class definition is not present at runtime.

Example for NoClassDefFoundError :

class Shape {
  public void draw() {
     System.out.println("Drawing Shape!");
  }
}

public class DrawingApp {
  public void draw() {
     System.out.println("Drawing Shape!");
  }
  public static void main(String[] args) {
     Shape shape = new Shape();
     shape.draw();
  }
}

After compilation, Shape.class and DrawApp.class are generated, If Shape.class is deleted and DrawApp is run then NoClassDefFoundError is thrown.

Difference between ConcurrentHashMap and SynchronizedMap

  • ConcurrentHashMap is designed for concurrency and improves performance while Collections.synchronizedMap(map) which is non-synchronized by sort can be synchronized by applying a wrapper using Collections.synchronizedMap(map).
  • ConcurrentHashMap doesn’t support null keys or null values while synchronized HashMap supports one null key.
  • Locking in SynchronizedMap is at object level, so read/write operations performance is slower.
  • Locking in ConcurrentHashMap is at a much finer granularity at a hashmap bucket level.

Differences betwen equals() and hashcode() methods

equals() and hashCode() are methods present in Object class and hashCode method should not be used to check if two object references are same. Reason: hashCode just returns int value for an Object, even two different objects can have same hashCode integer. The value returned by hashCode() is the object’s hash code, which is the object’s memory address in hexadecimal. equals() checks if the two object references are same. If two objects are equal then their hashCode must be the same, but the reverse is not true.

O(1) vs O(n) vs O(log n)

These are measures of time complexity of running a piece of code.

O(1) – if execution time is constant, it requires the same amount of time regardless of the size. Example:  array – accessing any element int i = a[0];

O(n) – if execution time is directly proportional to the size.  Example: Linear search for an element has a time complexity of O(n).

O(log n) – if execution time is proportional to the logarithm of the input size. Example: Performing Binary Search on array of elements

Changes to HashMap in Java8

  • In case of Hash collision entry objects are stored as a node in a LinkedList and equals() method is used to compare keys. That comparison to find the correct key with in a linked-list is a linear operation so in a worst case scenario the complexity becomes O(n).
  • To address this issue, Java 8 hash elements use Balanced Tree instead of LinkedList after a certain threshold is reached. Which means HashMap starts with storing Entry objects in linked list but after the number of items in a hash becomes larger than a certain threshold, the hash will change from using a LinkedList to a Balanced Tree, which will improve the worst case performance from O(n) to O(log n).

Fail Fast Vs Fail Safe Iterators

Fail-Fast Iterators Fail-Safe Iterators
Fail-Fast iterators doesn’t allow  modifications of a collection while iterating over it. Fail-Safe iterators allow modifications of a collection while iterating over it.
Concurrent Modification Exception is thrown if a collection is modified while iterating over it. These iterators don’t throw any exceptions if a collection is modified while iterating over it.
They use original collection to traverse over the elements of the collection. They use copy of the original collection to traverse over the elements of the collection.
These iterators don’t require extra memory. These iterators require extra memory to clone the collection.
Ex : Iterators returned by ArrayList, Vector, HashMap. Ex : Iterator returned by CopyOnWriteArrayList, ConcurrentHashMap.

Difference between map() and flatmap() in Java8

Lets suppose we are applying map and flatmap on stream of streams. Example given below

Stream<List<Character>> stream = Stream.of({'a','b'},{'c','d'})

with map:  For input Stream of two lists {‘a’,’b’} and {‘c’,’d’}, output will be {{‘a’,’b’},{‘c’,’d’}} .Here two lists are placed inside a list, so the output will be list containing lists

With flat map: For input Stream of two lists {‘a’,’b’} and {‘c’,’d’}, output will be {{a,b,c,d}} .Here two lists are flattened and only the values are placed in list, so the output will be list containing only elements

What are Functional interfaces how we can define them?

Functional interfaces are interfaces which have only one single abstract method in it. Example:  Runnable Interface since it has only single abstract method, run().

From Java8, we can use @FunctionalInterface to define a functional interface. Although this annotation is optional, once it is used then declaring more than one abstract method will throw compile time error.

Rules of Method Overloading and Method Overriding

There are specific rules while we implement method overloading and overriding in Java with regards to increasing/decreasing visibility of methods of parent class in child class and throwing Checked Exceptions in child class. Complete rules are posted in this below link

https://malliktalksjava.com/2020/05/29/rules-of-method-overloading-and-overriding/

Exception Handling flow having return statements in try/catch/finally blocks

  • Once try block encounters a return statement, the flow immediately transfers to finally block. Let say,it prints “print statement from finally”.
  • Upon the completion of finally block execution, control goes back to the return statement in the try block and returns “returning from try block”.
  • If finally block has a return statement, then the return statements from try/catch blocks will be overridden.

Exception Handling flow while exceptions thrown in catch/finally blocks

  • If the catch block completes normally, then the finally block is executed. Then there is a choice:
  • If the finally block completes normally, then the try statement completes normally. If the finally block completes abruptly for any reason, then the try statement completes abruptly for the same reason.
  • If the catch block completes abruptly for reason R, then the finally block is executed. Then there is a choice:
    If the finally block completes normally, then the try statement completes abruptly for reason R.
    If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).

FixedThreadPool vs CachedThreadPool vs ScheduledThreadPool

  • newCachedThreadPool(): creates an expandable thread pool executor. New threads are created as needed, and previously constructed threads are reused when they are available. Idle threads are kept in the pool for one minute. This executor is suitable for applications that launch many short-lived concurrent tasks.
  • newFixedThreadPool(int n): creates an executor with a fixed number of threads in the pool. This executor ensures that there are no more than n concurrent threads at any time. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread becomes available. If any thread terminates due to failure during execution, it will be replaced by a new one. The threads in the pool will exist until it is explicitly shutdown. Use this executor if you and to limit the maximum number of concurrent threads.
  • newScheduledThreadPool(int corePoolSize): creates an executor that can schedule tasks to execute after a given delay, or to execute periodically. Consider using this executor if you want to schedule tasks to execute concurrently.

What is ThreadLocal?

ThreadLocal class provides thread-local variables. It enables you to create variables that can only be read and write by the same thread. If two threads are executing the same code and that code has a reference to a ThreadLocal variable then the two threads can’t see the local variables of each other.

Diffence Volatile vs AtomicInteger?

volatile keyword is used on variables to solve the visibility problem in multi-threaded environment.  AtomicInteger is used if we perform compound operations(incrementing(i++) decrementing(i–)) on variables.

volatile is used on boolean flags, AtomicInteger is used for counters.

 

Differences between yield, join, & sleep

yield() method pauses the currently executing thread temporarily for giving a chance to the remaining waiting threads of the same priority to execute. If there is no waiting thread or all the waiting threads have a lower priority then the same thread will continue its execution. The yielded thread when it will get the chance for execution is decided by the thread scheduler whose behavior is vendor dependent.

join() If any executing thread t1 calls join() on t2 i.e; t2.join() immediately t1 will enter into waiting state until t2 completes its execution.

sleep() Based on our requirement we can make a thread to be in sleeping state for a specified period of time

Differences between Runnable and Callable

  • Runnable object does not return a result whereas a Callable object returns a result.
  • Runnable object cannot throw a checked exception wheras a Callable object can throw an exception.
  • The Runnable interface has been around since Java 1.0 whereas Callable was only introduced in Java 1.5.
class ThreadA implements Runnable {
@Override
public void run() { }
}

public class ThreadB implements Callable<String> {
@Override
public String call() throws Exception {
return "Thread B ran Successfully";
}
}

What is Semaphore in concurrency?

Semaphore is used to restrict the entry to a service to a fixed number of threads at a given time. This is generally used on slow services to make it available for fixed number of requests.

Semaphore semaphore = new Semphore(no_of_permits);

In run() method of a thread, we can use semaphore.acquire() before accessing the slow service and semaphore.release() after to ensure fixed number (defined as no_of_permits) of threads are eligible to access it.

Difference between CyclicBarrier and CountDownLatch?

Both CyclicBarrier and CountDownLatch are used in Multi threading scenario where one Thread waits for one or more Thread to complete their job before it continues processing but main difference between two is that, you can not reuse same CountDownLatch instance once count reaches to zero and latch is open, on the other hand, CyclicBarrier can be reused by resetting Barrier, Once barrier is broken.

  • Initialization of countdownlatch is CountDownLatch latch = new CountDownLatch(4);
  • Method used to countdown (generally used inside run method of thread at a specific point) is latch.countDown()
  • Method used to await a specific thread till countdown number completes is latch.await()
  • Phaser can be used either to perform functionality of both CyclicBarrier and CountDownLatch

References:
https://docs.oracle.com/en/java/javase/
https://stackoverflow.com/
https://dzone.com/

Rules of method overloading and overriding


In this post we will see the rules which needs to adhered while implementing method overriding and overloading with regards to increasing/decreasing visibility of methods of parent class in child class and throwing Checked Exceptions in child class.

Method Overriding rules

For terminology, original method is known as overridden method and new method is known as overriding method. Below rules must be followed to override a methods in Java :

  • Overriding method cannot throw checked exception which is higher in hierarchy than the checked Exception thrown by overridden method. For example if overridden method throws IOException which is checked Exception, than overriding method can not throw java.lang.Exception because it comes higher in type hierarchy.
    "Exception 'Exception' is not compatible with throws clause in" 
    
    **** Overriding method can have Runtime Exceptions declared even if Overridden method does not throw any type of Exceptions.
  • Overriding method can not reduce access of overridden method. It means if overridden method is defined as public than overriding method can not be protected or package private. Similarly if original method is protected then overriding method cannot be package-private. You can see what happens if you violate this rule in Java,
     "You cannot reduce visibility of inherited method of a class".
  • Overriding method can increase access of overridden method. This is opposite of earlier rule.
    ****According to this if overridden method is declared as protected then overriding method can be protected or public
  • private, static, final methods can not be overridden.
    "Cannot override the final method from Parent"
  • Return type of overriding method must be same as overridden method. Changing return type of method in child class will throw compile time error
    "return type is incompatible with parent class method"
    

Method Overloading rules

Here is the list of rules which must be followed to overload a method:

  • First rule to overload a method is to change method signature. method signature is made of number of arguments, type of arguments and order of arguments if they are of different types.  One can change any of these or combinations of them to overload a method in Java.
  • Return type of method is not part of method signature, hence changing the return type alone will not overload a method in Java.  In fact, it will result in compile time error.