java.net.UnknownHostException | in calling service using eureka service discovery

Requirement

I am working on a demo application based on microservice architecture and using Eureka for service discovery. I have successfully configured Eureka and two microservices order service and payment service.

eureka service

Problem

While calling the PAYMENT-SERVICE from the ORDER SERVICE received exception “java.net.UnknownHostException: PAYMENT-SERVICE”.


Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://PAYMENT-SERVICE/payment/pay": PAYMENT-SERVICE; nested exception is java.net.UnknownHostException: PAYMENT-SERVICE] with root cause


java.net.UnknownHostException: PAYMENT-SERVICE
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184) ~[na:1.8.0_45]
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_45]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_45]
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_45]
at java.net.Socket.connect(Socket.java:538) ~[na:1.8.0_45]
at sun.net.NetworkClient.doConnect(NetworkClient.java:180) ~[na:1.8.0_45]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:432) ~[na:1.8.0_45]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:527) ~[na:1.8.0_45]
at sun.net.www.http.HttpClient.<init>(HttpClient.java:211) ~[na:1.8.0_45]
at sun.net.www.http.HttpClient.New(HttpClient.java:308) ~[na:1.8.0_45]
at sun.net.www.http.HttpClient.New(HttpClient.java:326) ~[na:1.8.0_45]
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1168) ~[na:1.8.0_45]
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1104) ~[na:1.8.0_45]
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:998) ~[na:1.8.0_45]
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:932) ~[na:1.8.0_45]
at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:711) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:437) ~[spring-web-5.3.9.jar:5.3.9]
at com.codersdesks.orderservice.service.OrderService.createOrder(OrderService.java:31) ~[classes/:na]
at com.codersdesks.orderservice.controller.OrderController.pay(OrderController.java:22) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.9.jar:5.3.9]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.9.jar:5.3.9]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.9.jar:5.3.9]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.9.jar:5.3.9]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1064) ~[spring-webmvc-5.3.9.jar:5.3.9]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.9.jar:5.3.9]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.9.jar:5.3.9]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.9.jar:5.3.9]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) ~[tomcat-embed-core-9.0.50.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.9.jar:5.3.9]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.50.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:228) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.50.jar:9.0.50]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.9.jar:5.3.9]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723) [tomcat-embed-core-9.0.50.jar:9.0.50]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.50.jar:9.0.50]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_45]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.50.jar:9.0.50]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]


Solution

After analyzing the logs and referring to clientside load balancing found what is missing in ORDER-SERVICE. Basically, when calling a microservice using the service name defined in application.yml or application.properties, we have to use client-side load balancing.

To enable the clientside load balancing you simply need to add @LoadBalanced (org.springframework.cloud.client.loadbalancer.LoadBalanced) annotation on top of your RestTemplate bean or web client bean, like below.


@Bean
@LoadBalanced
public RestTemplate newTemplate(){
return new RestTemplate();
}

@LoadBalanced
@Bean
WebClient.Builder webClientBuilder() {
return WebClient.builder();
}

Reference

For reference, you can check out my microservice repository on Github.

Happy Learning !!

Java Programming Questions | Java sample coding problems

This is a post dedicated to Java programming challenges that can be useful to refresh and validate your knowledge of Java.

Question 1

Write the output of the following code?

int x = 1, y = 1, z = 0;
if (x == y | x < ++y) {
z = x + y;
} else {
z = 1;
}
System.out.println(z);

Question 2

Write the output of the following code?

int x = 1, y = 1, z = 0;
if (x == y | x < ++y) {
z = x + y;
} else {
z = 1;
}
System.out.println(z);

Not Sure why the out of questions 1 and 2 are different read about Java short circuit and full evaluation.

Question 3

Write the output of the following code?

int period = 1, amt = 10;
float rate = 0.5f;
switch (period) {
case 4:
	amt += amt * rate;
case 3:
	amt += amt * rate;
case 2:
	amt += amt * rate;
case 1:
	amt += amt * rate;

	System.out.println("final amt : " + amt);
}

Also, try to run the above code after modifying case 4 as below

case 4:
    amt += amt * rate;
    break;

Question 4

Write the output of the following code?

public static void main(String... strings) {
	int localVal = 5;
	calculate(localVal);
	System.out.println(localVal);
}

public static void calculate(int calcVal) {
    calcVal = calcVal * 100;
}

Question 5

Write the output of the following code?

String str = ""; 
str  = 1 + 1 + "u";
System.out.println(str);
str  = "u" + 1 + 1;
System.out.println(str);
str  = "u" + (1 + 1);
System.out.println(str);

Happy Learning !!

Java Short-Circuit Evaluation | Java Operators

There are so many operators available in Java. Here we will discuss Java Short circuit operators and how they evaluate the given expression. As a Java developer, you must know these basics and how to use them effectively.

OperatorEvaluation
&& and ||Short-Circuit
& and |Full

Operator && and || are known as short-circuit operators and how they evaluate an expression is known as short circuit evaluation.

What exactly Short-circuit evaluation is?

The short circuit evaluation enables you to not evaluate the right-hand side AND or OR expression when the overall result of the expression can be predicted from the left-hand side value.

So for AND (&&), both parts must be true for the overall results to be true. For OR (||), one part must be true, either one of these. The other may be false, it doesn’t matter. The overall result will be true. And for exclusive OR (^), either part has to be true, and the other part has to be false for the overall result to become true.

Now, instead of the double ampersand (&&) and double vertical line (||), there are also single ampersand and single vertical line operators available, and they’re known as full evaluation versus the double ampersand and double vertical line, which are known as short circuit evaluation.

Refer to the below picture and see how the evaluation of these operators happens.

Java Short-Circuit Evaluation

Example

Now let’s understand this using the below code snippet.

 
int a = 3, b = 2;
boolean c = false;

c = (a > b && ++b == 3); 
System.out.println("value of c is "+c + " and b is "+b);

c = (a > b && ++b == 3);
System.out.println("value of c is "+c + " and b is "+b);

c = (a > b || ++b == 3); 
System.out.println("value of c is "+c + " and b is "+b);

c = (a < b || ++b == 3); 
System.out.println("value of c is "+c + " and b is "+b);

c = (a < b | ++b == 3); 
System.out.println("value of c is "+c + " and b is "+b);

c = (a > b & ++b == 3);
System.out.println("value of c is "+c + " and b is "+b);

c = (a < b ^ ++b == 3);
System.out.println("value of c is "+c + " and b is "+b);

c = (a > b ^ ++b == 3);
System.out.println("value of c is "+c + " and b is "+b);

//Output
value of c is true and b is 3
value of c is false and b is 3
value of c is false and b is 4
value of c is true and b is 4
value of c is true and b is 5
value of c is false and b is 6
value of c is true and b is 7
value of c is false and b is 8

Note: You don’t have to put round brackets around Booleans, but that may make your code a little bit more readable, just sort of from a visual point of view so the Boolean expression will stand out.

Output Explantion

Let’s understand the output of each line.

 c = (a > b && ++b == 3); 

For AND condition, both parts of the expression need to be true for the overall results to become true. So we have to evaluate both parts to tell that.

If you look at a Boolean expression, the double ampersand is AND, the first part evaluates to true and then ++b increment the b to 3 and it also evaluates to true. That’s why c is true and b is 3.

See the next line of code which is a copy of the first line but its output is different from the first line. In this case, the first condition evaluates to false as b is incremented to 3 in the first line. Hence the second part of the expression will not be evaluated.

 c = (a > b || ++b == 3);  

OR condition, here one part of the expression needs to be true for the overall results to become true. So we have to evaluate both parts to tell that.

If you look at a Boolean expression, the first part evaluates to false and then ++b increment the b to 4 and it also evaluates to false. That’s why c is false and b is 4.

The next line also used the OR operator but changed the first part of the condition to a < b.

 c = (a < b || ++b == 3);  

In this case the first part evaluates to true hence the second part of the expression is omitted from the evaluation. That’s why c is true and b is still 4.

The next line also used the OR operator but not the short circuit one. This time we used the full evaluation of OR (|) means a single vertical line. The difference in full evaluation is even if the first condition of the OR is true the second part will still be evaluated and it doesn’t impact the overall result of the expression.

 c = (a < b | ++b == 3);  

Hence, in the output of the above line value of c is true and b is incremented to 5.

The next line is having the full evaluation AND operator. These means don’t matter the first condition evaluates to true or false the second condition will be evaluated which is not the case when we use short circuit AND (&&) operator.

 c = (a > b & ++b == 3);  

In the above line the first condition is evaluated to false but still, the second condition is evaluated which is not the case when we use &&. Hence The value of c is false in the output of the above line but the b is still incremented to 6.

The next two lines of the code are using XOR (^) operator. This is also used for a full evaluation of both the expression. This will return true if one condition is true and another is false.

 c = (a < b ^ ++b == 3);  

Here the first condition is evaluated to true then it increments b to 7 and the second condition evaluates to false.

 c = (a > b ^ ++b == 3);  

The last line output value of c is false and b is 8. Here if you see the first condition is evaluated to false then it incremented b to 8 and that condition is false.

Conclusion

Here we discussed the &&, ||, &, | and ^ operators and how they evaluate a given condition. While using full evaluation the second part of the condition is evaluated doesn’t matter the first condition is evaluated to true or false.

Happy Learning !!

Read more

Refrence

How to use Java 8 Function and BiFunction Interface?

With all the other enhancements in Java 8 a new package java.util.function is also added to the Java library. In this post, we will discuss how to use the Function and BiFunction interface with examples. Both the interface are functional interface.

Function Interface Syntax

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Salient Points of Function interface

  • It has been defined with the generic types T & R, where T is the type of the input and R is the output type.
  • Method apply() is the functional method (only abstract method in a functional interface). It takes an input t of type T and returns an output of type R.
  • It has two default method.
  • The first default method compose()  Returns a composed function that first applies the function to its input, and then applies this function to the result. If the evaluation of either function throws an exception, it is relayed to the caller of the composed function. In simple words, a composed function that first applies the before function and then applies its own function to the result of before.
  • The second default method is andThen() is inverse of the compose function. It is a composed function that first applies its own function to the input and then applies the after function to the result.
  • Function interface has one static method identity() which returns a function that always returns its input argument.

BiFunction Interface

@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);

    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}

Salient Points of BiFunction interface

  • It has been defined with the generic types T, U & R, where T and U are the types of the first and second input and R is the output type.
  • Method apply() is the functional method that applies this function to the given input T and U and returns the output of Type R.
  • The default method andThen() is a composed function that first applies its own function to the input and then applies the after function to result.

Example

In this example, we will use a class Product to demonstrate the Function interface.

class Product{
	private int id;
	private String name;
	private String desc;
	
	public Product(int id, String name, String desc) {
		super();
		this.id = id;
		this.name = name;
		this.desc = desc;
	}

	@Override
	public String toString() {
		return "Product [id=" + id + ", name=" + name + ", desc=" + desc + "]";
	}

	public int getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public String getDesc() {
		return desc;
	}

	public void setName(String name) {
		this.name = name;
	}
	
} 

Function Interface apply method

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class FunctionDemo {
	static List<Product> products = new ArrayList<>();	
	
	static Function<Product, String> getProductNameFunction = Product::getName;
		
	public static void main(String[] args) {
		prepareData();
		List<String> productNames = new ArrayList<>(); 
		products.forEach(p ->{
			productNames.add(getProductNameFunction.apply(p));
		});
		System.out.println("productNames => "+productNames);		
	}

	static void prepareData() {
		for(int i =1 ; i<= 10; i++) {
			products.add(new Product(i, "product name "+i, "product desc "+i));
		}
	}
}

In the above code snippet, we have created a list of Products and a Function getProductNameFunction which will convert the list of Products into a list of String containing product names.

Function Interface compose method

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;

public class FunctionDemo {
	static List<Product> products = new ArrayList<>();	
	
	static Function<Product, String> getProductNameFunction = Product::getName;
	
	static Function<Product, Product> composeBeforeFunction = (Product p)->{
		String name = p.getName().replace(" ", " "+new Random().nextInt());
		p.setName(name);
		return p;
	};
		
	public static void main(String[] args) {
		prepareData();
		
		List<String> productNames = new ArrayList<>(); 
		products.forEach(p ->{
			productNames.add(getProductNameFunction.compose(composeBeforeFunction).apply(p));
		});
		System.out.println("productNames => "+productNames);		
	}

	static void prepareData() {
		for(int i =1 ; i<= 10; i++) {
			products.add(new Product(i, "product "+i, "product desc "+i));
		}
	}
}

Here we have created a list of products and a new Function composeBeforeFunction and we also use getProductNameFunction from apply example. Here when we run this code snippet as per the description of compose() method composeBeforeFunction will apply and it will add a random string to the product name and then the getProductNameFunction will be applied which will return a list of the product name.

Function Interface andThen method

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class FunctionDemo {
	static List<Product> products = new ArrayList<>();	
	
	static Function<Product, String> getProductNameFunction = Product::getName;
	
	static Function<String, String> andThenFunction = (String s)-> s.substring(s.length()-1,s.length());
	
	public static void main(String[] args) {
		prepareData();
		
		List<String> productNames = new ArrayList<>(); 
		
		products.forEach(p ->
			productNames.add(getProductNameFunction.andThen(andThenFunction).apply(p))
		);
		
		System.out.println("productNames => "+productNames);		
	}

	static void prepareData() {
		for(int i =1 ; i<= 10; i++) {
			products.add(new Product(i, "product "+i, "product desc "+i));
		}
	}
}

In this example, we have created a list of products and a new Function andThenFunction also we have used getProductNameFunction from apply example. Here when we run this code snippet as per the description of andThen() method getProductNameFunction will apply first and then the andThenFunction will be applied which will return a list of String only having the last char of the product name.

Function Interface identity method

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FunctionDemo {
	static List<Product> products = new ArrayList<>();	
	
	public static void main(String[] args) {
		prepareData();
		
		Map<Integer, Product> productmap = products.stream()
				.collect(Collectors.toMap(Product::getId, Function.identity()));
		
		System.out.println("productmap => "+productmap);		
	}

	static void prepareData() {
		for(int i =1 ; i<= 10; i++) {
			products.add(new Product(i, "product "+i, "product desc "+i));
		}
	}
}

In this example, we have converted the list of products into a Map of using the identity() method.

If we haven’t used the identity() method to create a Map we have to use the other way like below.

Map<Integer, Product> productmapWithForeach = new HashMap<>();
		
products.forEach(product -> productmapWithForeach.put(product.getId(),
 product));

BiFunction apply method

public class FunctionDemo {	
		
	public static void main(String[] args) {
				
		 BiFunction<Integer, Integer, Integer> addFunction = (t, u) -> t + u;
		 
		 int sum = addFunction.apply(10, 20);
	 
		 System.out.println("sum is => +sum");

		
	}
}

Conclusion

In this post, we have discussed Function and BiFunction Interface and how can we use these functions to write more concise and clean code.

Recommended Read

Java 8 Method Reference
Java 8 Stream API
Java 8 comparison using Lambda

Happy Learning !!

Understanding and preventing memory leaks in Java

For any developer, memory should be one of the most precious resources to think of while writing a program. A program can be said to be memory efficient when it consumes as little memory as possible when in operation but still doing what it was designed to do. So, before write code think of memory uses, do you know What happens when a Java object is created?

What is a Memory Leak?

In simple words, memory leak means unused memory that the garbage collectors can not reclaim.

A memory leak occurs when objects are no longer being used by the application, but the garbage collector is unable to clear them from working memory. This is a serious problem because these objects hold the memory that could otherwise be used by other parts of the program. With time, this piles up and leads to a degradation in system performance over time.

Garbage Collection in Java

One of the coolest features of Java is its automatic memory management. The Garbage Collection is a program that implicitly takes care of memory allocation and deallocation. It’s an effective program and can handle the majority of memory leaks that are likely to occur. However, it’s not infallible. Memory leaks can still sneak up and start taking up precious resources and, in worst cases, result in the java.lang.OutOfMemoryError.

It’s worth mentioning that an OutOfMemoryError is not always because of memory leaks. At times, it could be poor code practices like loading large files in memory.

The three common causes of memory leaks?

  • Misused static fields
  • Un closed streams
  • Un closed connections

Misused static fields

Static fields live in the memory as long as the class that owns them is loaded in the JVM, which means there are no instances of the class in the JVM, at this point, the class will be unloaded and the static field will be marked for garbage collection. But the catch here is, the static classes can live in the memory forever.

Consider the following code:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class StaticDemo {
public static List&lt;Integer&gt; list = new ArrayList&lt;&gt;();

public void populateList() {
for (int i = 0; i &lt; 10000000; i++) {
   list.add(new Random().nextInt());
}
}
public static void main(String[] args) {
  new StaticDemo().populateList();
}
}

This is a simple and small code snippet, we have a static List and we added values into it. But If we see the declaration of the list we have used static in front of it.  That’s the problem, the memory occupied by this list will be in use until the program finishes its execution even though the operations on the list are already completed.

To avoid this mistake, Minimize the use of static fields in your application.

Un closed streams

Till now we have understood memory leak is when code holds a reference to an object and the garbage collector can’t claim that object. But, a closed stream object is not memory unless it holds a reference of an unclosed stream.

Usually, the operating system limits how many open files (while using FileInputStream) an application can have. So, if such streams are not closed and the garbage collector may take some to claim these objects, it is also a case of the leak but not particularly a memory leak.

Refer to the following code snippet:

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class OpenStreamDemo {

    public static void main(String[] args) throws IOException {
        URL url = new URL("http://ergast.com/api/f1/2004/1/results.json");
        ReadableByteChannel rbc = Channels.newChannel(url.openStream());
        FileOutputStream outputStream = new FileOutputStream("/");
        outputStream.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
    }
}

Here the unclosed FileOutputStream and ReadableByteChannel will cause potential issues. The solution to this problem would be closing these stream objects once they are used and not require further. Or use java to try with resources wherever allowed.

rbc.close();
outputStream.close();

Un closed connections

The frequent mistake in Java programming is, developer forgot to close the database connections.  Having an unclosed database connection can give you a tough time in production and they are difficult to replicate in local environments.

Refer to the below code snippet:

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class OpenConnectionDemo {

    public static void main(String[] args) {
        try {
            List&lt;String&gt; names = fetchUsersName("foo", "bar");
            names.forEach(System.out::println);

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static List&lt;String&gt; fetchUsersName(String username, String password) throws SQLException {
        List&lt;String&gt; names = new ArrayList&lt;&gt;();
        Connection con = DriverManager.getConnection("jdbc:myDriver:devDB",
                username,
                password);

        Statement stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
        return names;
    }
}

Here every resource is leaking. Here we could have use try-catch and finally, and inside the finally block we can close

stmt.close();
con.close();

Here is the complete code for the fetchUsersName method.

public static List&lt;String&gt; fetchUsersName(String username, String password) throws SQLException {
    Statement stmt = null;
    Connection con = null;
    List&lt;String&gt; names = new ArrayList&lt;&gt;();
    try {

        con = DriverManager.getConnection("jdbc:myDriver:devDB",
                username,
                password);

        stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
    }catch (SQLException se){
        se.printStackTrace();
    }finally {
        stmt.close();
        con.close();
    }
    return names;
}

Or we can use try with resources like below.

public static List&lt;String&gt; fetchUsersName(String username, String password) throws SQLException {
    List&lt;String&gt; names = new ArrayList&lt;&gt;();
    try (Connection con = DriverManager.getConnection("jdbc:myDriver:devDB",username,password);
         Statement stmt = con.createStatement();
    ){
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
    }catch (SQLException se){
        se.printStackTrace();
    }
    return names;
}

We can also use ORM like hibernate or jooq which provides easier and more maintainable resource handling.

So the take away from this post are:

  1. Be careful while using static fields.
  2. Make sure to close the stream and connection or use try with resources.
  3. Use ORM if your application allows.

 

Happy Learning !!!

Parsing JSON With Java 8 Without Dependencies

While working with JSON we often need to parse the JSON into an object, or Map, or List, or to a custom object as well.  To parse the JSON we have to use a dependency to process it easily.

But, starting with JDK 8u60+ the built-in Nashorn engine is capable to convert JSON content into java.util.Map or java.util.List. No external dependencies are required for parsing.

Here is an example with sample JSON. You can follow the below steps.

  1. Copy the below JSON into a file “test.json” and place it inside your java project.
{
	"page": "1",
	"per_page": 10,
	"total": 23,
	"total_pages": 3,
	"data": [
		{
			"competition": "UEFA Champions League",
			"year": 2014,
			"round": "GroupG",
			"team1": "Chelsea",
			"team2": "Schalke 04",
			"team1goals": "1",
			"team2goals": "1"
		},
		{
			"competition": "UEFA Champions League",
			"year": 2014,
			"round": "GroupG",
			"team1": "Chelsea",
			"team2": "NK Maribor",
			"team1goals": "6",
			"team2goals": "0"
		},
		{
			"competition": "UEFA Champions League",
			"year": 2014,
			"round": "GroupG",
			"team1": "Chelsea",
			"team2": "Sporting CP",
			"team1goals": "3",
			"team2goals": "1"
		},
		{
			"competition": "UEFA Champions League",
			"year": 2014,
			"round": "R16",
			"team1": "Chelsea",
			"team2": "Paris Saint-Germain",
			"team1goals": "1",
			"team2goals": "1"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Leicester City",
			"team1goals": "2",
			"team2goals": "0"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Swansea City",
			"team1goals": "4",
			"team2goals": "2"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Aston Villa",
			"team1goals": "3",
			"team2goals": "0"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Arsenal",
			"team1goals": "2",
			"team2goals": "0"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Queens Park Rangers",
			"team1goals": "2",
			"team2goals": "1"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "West Bromwich Albion",
			"team1goals": "2",
			"team2goals": "0"
		}
	]
}

2. Create a class “JSONParser.java” and put the below code inside it.

package com.codersdesks.json;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.junit.Before;
import org.junit.Test;

public class JSONParser {
	
	private ScriptEngine scriptEngine;
	private String json;

	@Before
	public void setup() throws IOException {
		ScriptEngineManager sem = new ScriptEngineManager();
		this.scriptEngine = sem.getEngineByName("javascript");
		File file = new File("test.json");
		this.json = new String(Files.readAllBytes(file.toPath()));
	}

	@Test
	public void parse() throws ScriptException {
		String script = "Java.asJSONCompatible(" + this.json + ")";
		Object result = this.scriptEngine.eval(script);
		Map contents = (Map) result;
		
		contents.forEach((k,v) ->{
			System.out.println("Key => "+k +" value =>"+contents.get(k));
		});
		
		List data = (List) contents.get("data");
		data.forEach(d ->{
			Map matchDetail = (Map) d;
			matchDetail.forEach((k,v) ->{
				System.out.println("Key => "+k +" value =>"+matchDetail.get(k));
			});	
		});
	}

}

Run the Junit test and you can see the below output.

Key => page value =>1
Key => per_page value =>10
Key => total value =>23
Key => total_pages value =>3
Key => data value =>[[object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object]]
Key => competition value =>UEFA Champions League
Key => year value =>2014
Key => round value =>GroupG
Key => team1 value =>Chelsea
Key => team2 value =>Schalke 04
Key => team1goals value =>1
Key => team2goals value =>1
Key => competition value =>UEFA Champions League
Key => year value =>2014
Key => round value =>GroupG
Key => team1 value =>Chelsea
Key => team2 value =>NK Maribor
Key => team1goals value =>6
Key => team2goals value =>0
Key => competition value =>UEFA Champions League
Key => year value =>2014
Key => round value =>GroupG
Key => team1 value =>Chelsea
Key => team2 value =>Sporting CP
Key => team1goals value =>3
Key => team2goals value =>1
Key => competition value =>UEFA Champions League
Key => year value =>2014
Key => round value =>R16
Key => team1 value =>Chelsea
Key => team2 value =>Paris Saint-Germain
Key => team1goals value =>1
Key => team2goals value =>1
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Leicester City
Key => team1goals value =>2
Key => team2goals value =>0
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Swansea City
Key => team1goals value =>4
Key => team2goals value =>2
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Aston Villa
Key => team1goals value =>3
Key => team2goals value =>0
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Arsenal
Key => team1goals value =>2
Key => team2goals value =>0
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Queens Park Rangers
Key => team1goals value =>2
Key => team2goals value =>1
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>West Bromwich Albion
Key => team1goals value =>2
Key => team2goals value =>0

You can also read about JSON Schema and How to use Jackson databind with JSON

For more information, you can refer to the official Nashorn extensions documentation.

Happy Learning !!

io.lettuce.core.RedisConnectionException: DENIED Redis is running in protected mode

Problem

While trying to connect to Redis running on Linux through my java code getting io.lettuce.core.RedisConnectionException: DENIED Redis is running in protected mode.

The exception stack trace is as below.

io.lettuce.core.RedisConnectionException: DENIED Redis is running in protected mode because the protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode, connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and
then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.
        at io.lettuce.core.protocol.CommandHandler.onProtectedMode(CommandHandler.java:667) ~[lettuce-core-5.0.1.RELEASE.jar!/:na]
        at io.lettuce.core.protocol.CommandHandler.channelInactive(CommandHandler.java:305) ~[lettuce-core-5.0.1.RELEASE.jar!/:na]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:75) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.lettuce.core.ChannelGroupListener.channelInactive(ChannelGroupListener.java:46) ~[lettuce-core-5.0.1.RELEASE.jar!/:na]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:75) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.lettuce.core.PlainChannelInitializer$1.channelInactive(PlainChannelInitializer.java:85) ~[lettuce-core-5.0.1.RELEASE.jar!/:na]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1429) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:947) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:822) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-common-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:466) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]

Solution

After analyzing the logs noticed following lines which describe the root cause and fix for this.

DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no auth

In order to fix this we need to do one of the following:

  1. Disable protected mode from redis CLI
  2. Disable protected mode from redis config
  3. Restart redis it with the ‘–protected-mode no’ option, only for testing purposes.
  4. Setup a bind address or an auth

Since we knew the solution for this, let’s see how we can actually do it.

  1. To disable the protected mode just open the redis-cli and run ‘CONFIG SET protected-mode no’.
  2. To disable the protected mode stop redis server and edit redis.conf file inside conf folder, add ‘protected-mode no’.  Restart the redis server .
  3. To restart redis server with –protected-mode no’ option, run redis-server  with option –protected-mode. Like redis-server –protected-mode no
  4. To bind an IP address stop redis server, edit redis config and add bind *.*.*.* to bind a specific IP to access the redis server. i.e. bind 127.0.0.1. Restart redis server.

Note: If none of the above options are performed you will not be able to access redis server.

If you know of any other fixes to this issue please let us know through comments.

Read more about Java

What happens when a Java object is created?

Java 8 Stream API with examples

Happy Learning !!

Amazon EC2 – disk full /dev/nvme0n1p1 full how to fix

Problem: While running my Jenkins build, build failed with following error.

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.1.RELEASE:repackage (repackage) on project <project name>: No space left on device -> [Help 1]

To investigate, when I run df -h on my Amazon EC2 server, this is the output:

[root@ip-172-*-*-3 builds]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 516K 1.9G 1% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/nvme0n1p1 20G 20G 76K 100% /
tmpfs 389M 0 389M 0% /run/user/1000

For some reason my space is almost full and I really can’t find the big files or directory is easily.

To get the files/directory eating up my space I used the following command to find all the files greater than 10 MB:

sudo find / -type f -size +10M -exec ls -lh {} \;

This command return you list of files with complete path, which helps me to identify which ones are causing the trouble and deal with them accordingly.

After analyzing the result form the above command, I found that Jenkins keeps archiving all the previous builds which are eating up most of my memory.

Once I have the list of files I deleted all the large files using rm -r commands and removed all the files inside directory using rm -rf *.

Once I have deleted the large files, I ran the Jenkins build again and it work perfectly.

So, while using Jenkins I think we should also think about the clean up process for the archives, if not the entire one we can delete the significantly old archives and have enough space for builds to execute successfully.

Read more about Java here.

 

MongoDB CRUD operations in detail

In the previous post, we discussed the fundamentals of MongoDB and also introduced you to MongoDB CRUD operations. In this post we will deep dive into CRUD operations as often we use them only.

Here is the list of methods provided by MongoDB to fulfill the requirement of CRUD operations.

InsertFindUpdateDelete
insertOne()findOne()updateOne()deleteOne()
insertMany()find()UpdateMany()deleteMany()
insert()findAndModify()Update()remove()
findOneAndDelete()replaceOne()
findOneAndReplace()
findOneAndUpdate()

Let’s move further and discuss each of the methods in detail.

Create

The first operation of CRUD used to create new documents in a collection. As shown in the above table MongoDB offers three methods to create new documents. These three methods use the default write concern unless we pass a write concern and likewise the use database command it also creates a new collection if the collection is not available.

db.collection.insertOne() inserts a single document into a collection.

Syntax:

db.collection.insertOne(
   <document>,
   {
      writeConcern: <document>
   }
)

Returns: A document containing:

  • A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled.
  • A field inserted Id with the _id value of the inserted document.

In the below example we will insert a new document in userinfo collection. Make sure you are in the correct database. To use a database just write

use this command does two things, one creates a new database if it does not exist, and switch to the given database.

use user
switched to db user
db.userinfo.insertOne({name:'user 1',email:'user1@test.com',age:21})

#Output 
{
"acknowledged" : true,
"insertedId" : ObjectId("5ed6f5a9b66c8269070b4af2")
}

db.collection.insertMany() can insert multiple documents into a collection. This method takes an array of documents.

Syntax:

db.collection.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>
   }
)

The ordered boolean parameter is Optional also as mentioned above it uses default concern if not provided. A boolean specifying whether the mongo instance should perform an ordered or unordered insert. Defaults to true.

Returns: A document containing:

  • A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled
  • An array of _id for each successfully inserted documents

Refer to the below snippet here we have created 3 documents using insert many.

db.userinfo.insertMany([

{name:'user 2',email:'user2@test.com',age:22},

{name:'user 3',email:'user3@test.com',age:32},

{name:'usr 4',email:'user4@test.com',age:30}

])

#Output 

{


"acknowledged" : true,
"insertedIds" : [
ObjectId("5ed6f6ceb66c8269070b4af3"),
ObjectId("5ed6f6ceb66c8269070b4af4"),
ObjectId("5ed6f6ceb66c8269070b4af5")
]
}

db.collection.insert() Inserts a document or documents into a collection. It works as insertOne () in case of a single document and in case of multiple documents works as insertMany ().

Syntax:

db.collection.insert(
   <document or array of documents>,
   {
     writeConcern: <document>,
     ordered: <boolean>
   }
)

Returns:

  • A WriteResult object for single inserts.
  • A BulkWriteResult object for bulk inserts.

MongoDB also provide  db.collection.save() method to create documents but as per the Mongo documentation it is deprecated and they emphasize on using inserOne (), insertMany() and insert() methods.

Read

The second operation of CRUD used to read/fetch the documents from a collection. As shown in the above table MongoDB offers two methods to fetch the data from a collection.

db.collection.findOne() Returns one document that satisfies the specified query criteria on the collection or the first document from the collections if no query provided.

Syntax:

db.collection.findOne(query, projection)

Parameter

query:  The query parameter is an Optional document, which specifies a query for selection criteria using query operators.

projection: It is also an Optional document, which specifies the fields to return using projection operators. Omit this parameter to return all fields in the matching document. For details, see Projection.

Note: The basic thumb rule for applying projection is to use 1 to include any field and 0 to exclude. By default, the _id field is always included unless you explicitly exclude it.

Returns:

It returns One document that matches the criteria specified in the query, the first parameter. If you specify a projection parameter, findOne() returns a document that only contains the projection fields.

Although it is similar to the find() method, the findOne() method returns a document rather than a cursor.

Example:

db.employees.findOne({gender:'male'},{gender:1, name:1})

#Output

{
"_id" : ObjectId("5f20577536c73fc3e870fda4"),
"gender" : "male",
"name" : {
"title" : "mr",
"first" : "harvey",
"last" : "chambers"
}
}

db.collection.find() Returns document or documents that satisfies the specified query criteria on the collection.

Syntax:

db.collection.find(query, projection)

Parameter

query:  The query parameter is an Optional document, which specifies a query for selection criteria using query operators.

projection: It is also an Optional document, which specifies the fields to return using projection operators. Omit this parameter to return all fields in the matching document. For details, see Projection.

Returns:

It returns the document or documents that match the criteria specified in the query. If you specify a projection parameter, find () returns a document that only contains the projection fields.

Although it is similar to the findOne() method, the find() method returns a cursor instead of documents.

Example:

db.employees.find({},{gender:1, name:1})db.employees.findOne({gender:'male'},{gender:1, name:1})

#Output


> db.employees.find({},{gender:1, name:1})
{ "_id" : ObjectId("5f20577536c73fc3e870fda4"), "gender" : "male", "name" : { "title" : "mr", "first" : "harvey", "last" : "chambers" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda5"), "gender" : "male", "name" : { "title" : "mr", "first" : "victor", "last" : "pedersen" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda6"), "gender" : "male", "name" : { "title" : "mr", "first" : "elijah", "last" : "lewis" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda7"), "gender" : "female", "name" : { "title" : "mrs", "first" : "olav", "last" : "oehme" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda8"), "gender" : "male", "name" : { "title" : "mr", "first" : "carl", "last" : "jacobs" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda9"), "gender" : "female", "name" : { "title" : "mrs", "first" : "madeleine", "last" : "till" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdaa"), "gender" : "female", "name" : { "title" : "miss", "first" : "shona", "last" : "kemperman" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdab"), "gender" : "female", "name" : { "title" : "ms", "first" : "louise", "last" : "graham" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdac"), "gender" : "male", "name" : { "title" : "mr", "first" : "zachary", "last" : "lo" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdad"), "gender" : "male", "name" : { "title" : "mr", "first" : "isolino", "last" : "viana" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdae"), "gender" : "female", "name" : { "title" : "mrs", "first" : "katie", "last" : "welch" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdaf"), "gender" : "female", "name" : { "title" : "miss", "first" : "sandra", "last" : "lorenzo" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb0"), "gender" : "female", "name" : { "title" : "miss", "first" : "mestan", "last" : "kaplangı" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb2"), "gender" : "male", "name" : { "title" : "mr", "first" : "gideon", "last" : "van drongelen" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb3"), "gender" : "female", "name" : { "title" : "miss", "first" : "maeva", "last" : "wilson" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb4"), "gender" : "female", "name" : { "title" : "ms", "first" : "anaëlle", "last" : "adam" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb5"), "gender" : "female", "name" : { "title" : "miss", "first" : "anne", "last" : "ruiz" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb6"), "gender" : "female", "name" : { "title" : "mademoiselle", "first" : "delia", "last" : "durand" } }
Type "it" for more
>

db.collection.findAndModify() Used to modifies and return a single document. By default, the returned document does not include the modifications made on the update. To return the updated document, we need to use the new option.

Syntax:

db.collection.findAndModify({
    query: <document>,
    sort: <document>,
    remove: <boolean>,
    update: <document or aggregation pipeline>,
    new: <boolean>,
    fields: <document>,
    upsert: <boolean>,
    bypassDocumentValidation: <boolean>,
    writeConcern: <document>,
    collation: <document>,
    arrayFilters: [ <filterdocument1>, ... ]
});

 

query:  The query parameter is an Optional document, which specifies a query for selection criteria using query operators similar to find() method. Although the query may match multiple documents, db.collection.findAndModify() will only select one document to modify.

sort: It is also an Optional document, determines which document the operation modifies if the query selects multiple documents. db.collection.findAndModify() modifies the first document in the sort order specified by this argument.

remove: An optional field of type boolean which must specify either to remove or update the field. Removes the document specified in the query field. Set this to true to remove the selected document. The default is false.

new: An optional boolean field. When true, returns the modified document rather than the original. The db.collection.findAndModify() method ignores the new option for remove operations. The default is false.

fields: An Optional document work similar to projection in find() method. The fields document specifies an inclusion of a field with 1, as in: fields: { : 1, : 1, … }.

For more details on parameter visit Mongo official doc

Returns:

To remove operations, if the query matches a document, it will return the removed document. If the query does not match a document to remove returns null.

For update operations, it will return one of the following:

If the new parameter is not set or is false:

  • The pre-modification document is returned if the query matches a document
  • Otherwise, null.

If new is set to true:

  • The modified document if the query returns a match
  • The inserted document if upsert: true and no document matches the query
  • Otherwise, null

Example:

db.userinfo.find({name:'test user'})

#Output

{ "_id" : ObjectId("5f444629c2254dfb46403a0a"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f4446c9c2254dfb46403a0b"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }


db.userinfo.findAndModify({
query: {name:'test user'},
update: { age: 22}
})

#Output

{
"_id" : ObjectId("5f444629c2254dfb46403a0a"),
"name" : "test user",
"email" : "testuser@test.com",
"age" : 21
}

Here you can see that it updated the document successfully but returned the old one with age 21.

If we again run the following query we will get the updated document with age 22.

db.userinfo.find({name:'test user'})

#Output

db.userinfo.find({name:'test user'})
{ "_id" : ObjectId("5f4448cbc2254dfb46403a0c"), "name" : "test user", "email" : "testuser@test.com", "age" : 22 }
{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

But, if we run the same update with one additional parameter new with the value true it will return the update document.

db.userinfo.findAndModify({
query: {name:'test user'},
update: {name:'test user',email:'testuser@test.com',age:23},
new :true
})

#Output

{
"_id" : ObjectId("5f4448cbc2254dfb46403a0c"),
"name" : "test user",
"email" : "testuser@test.com",
"age" : 23
}

db.collection.findOneAndDelete() Used to deletes a single document based on the filter and sort criteria, returning the deleted document. Deletes the first matching document in the collection that matches the filter. The sort parameter can be used to influence which document is deleted.

Syntax:

db.collection.findOneAndDelete(
   <filter>,
   {
     projection: <document>,
     sort: <document>,
     maxTimeMS: <number>,
     collation: <document>
   }
)

Parameter

filter: The selection criteria for the deletion same as the query in find() method. Pass and empty {} document to delete the first document returned in the collection. By default, an empty document {}.

projection: Same as the projection in find() method

sort: An Optional field. Specifies a sorting order for the documents matched by the filter.

For more details on parameter visit Mongo official doc

Returns: Returns the deleted document.

Example:

db.userinfo.find({name:'test user'})
{ "_id" : ObjectId("5f4448cbc2254dfb46403a0c"), "name" : "test user", "email" : "testuser@test.com", "age" : 23 }
{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

#Output

db.userinfo.findOneAndDelete({age:23})
{
"_id" : ObjectId("5f4448cbc2254dfb46403a0c"),
"name" : "test user",
"email" : "testuser@test.com",
"age" : 23
}

Now if run the same find command again we will only get a single record with name ‘test user’

db.userinfo.find({name:'test user'})
{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

db.collection.findOneAndReplace() Used to replace a single document based on the specified filter. The sort parameter can be used to influence which document is deleted. It works the same way findAndModify() works.

Syntax:

db.collection.findOneAndReplace( 
	<filter>, <replacement>, 
	{ projection: <document>,
	 sort: <document>, 
	 maxTimeMS: <number>,
	 upsert: <boolean>, 
	 returnNewDocument: <boolean>,
	 collation: <document> 
	} 
)

Parameter

filter: The selection criteria for the deletion same as the query in find() method. Pass and empty {} document to delete the first document returned in the collection. By default, an empty document {}.

replacement: The replacement document.

projection: Same as the projection in find() method

sort: An Optional field. Specifies a sorting order for the documents matched by the filter.

returnNewDocument: An Optional field. When true, returns the replacement document instead of the original document. Defaults to false.

For more details on parameter visit Mongo official doc

Returns: Returns either the original document or the replaced document if returnNewDocument is true.

Example:

db.userinfo.find({name:'test user'})

#Output

{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbcc2254dfb46403a0e"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a0f"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a10"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

db.userinfo.findOneAndReplace(
{ "age" : 21},
{name:'test user',email:'testuserAge22@test.com',age:22}
)


#Output

{
"_id" : ObjectId("5f4448cdc2254dfb46403a0d"),
"name" : "test user",
"email" : "testuser@test.com",
"age" : 21
}

db.userinfo.find({name:'test user'})

#Output

{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuserAge22@test.com", "age" : 22 }
{ "_id" : ObjectId("5f444fbcc2254dfb46403a0e"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a0f"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a10"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

But, if we pass returnNewDocument as true, it will return the replaced document.

db.userinfo.findOneAndReplace(
{ "age" : 22},
{name:'test user',email:'testuserAge23@test.com',age:23},
{returnNewDocument : true}
)

#Output
{
"_id" : ObjectId("5f4448cdc2254dfb46403a0d"),
"name" : "test user",
"email" : "testuserAge23@test.com",
"age" : 23
}

db.collection.findOneAndUpdate() Used to update a single document based on the filter and sort criteria.

Used to replace a single document based on the specified filter. The sort parameter can be used to influence which document is deleted. It works the same way findAndModify() works.

Syntax:

db.collection.findOneAndUpdate(
   <filter>,
   <update document or aggregation pipeline>,
   {
     projection: <document>,
     sort: <document>,
     maxTimeMS: <number>,
     upsert: <boolean>,
     returnNewDocument: <boolean>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

Parameter

filter: The selection criteria for the deletion same as the query in find() method. Pass and empty {} document to delete the first document returned in the collection. By default, an empty document {}.

update: The updated document.

projection: Same as the projection in find() method

sort: An Optional field. Specifies a sorting order for the documents matched by the filter.

returnNewDocument: An Optional field. When true, returns the replacement document instead of the original document. Defaults to false.

For more details on parameter visit Mongo official doc

Returns: Returns either the original document or the replaced document if returnNewDocument is true.

Example:
db.userinfo.find({name:'test user'})

#output

{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuserAge23@test.com", "age" : 23 }
{ "_id" : ObjectId("5f444fbcc2254dfb46403a0e"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a0f"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a10"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

db.userinfo.findOneAndUpdate(
{ "age" : 23},
{ $inc: { "age" : 2 }},
{returnNewDocument : true}
)

#output

{
"_id" : ObjectId("5f4448cdc2254dfb46403a0d"),
"name" : "test user",
"email" : "testuserAge23@test.com",
"age" : 25
}

db.userinfo.find({name:'test user'})

#output

{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuserAge23@test.com", "age" : 25 }
{ "_id" : ObjectId("5f444fbcc2254dfb46403a0e"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a0f"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a10"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

Note: The update parameter only contains update operator expressions.  You can not pass an entire document to replace as we did in the findOneAndReplace() method.

 

IntelliJ: Error:java: error: release version 5 not supported

Problem: While creating a new maven project using IntelliJ IDEA with Java 11 started getting the following error:

Error:java: error: release version 5 not supported

After exploring the internet for a while I found what is causing this error.

Reason: Generally Maven sets the default Java version to 1.5. Hence you need to set the correct language level and release version in pom.xml.

Before searching for a solution you can check your current Java version at, File => Settings => Build, Execution, Deployment => Compiler => Java Compiler and change it if required.

IntelliJ_Java_compiler_version

Even after changing the java version, if it didn’t work, you can apply the following solutions.

Solution 1:

Set the source /target versions in pom.xml like below:

<properties>
     <maven.compiler.source>1.11</maven.compiler.source>
     <maven.compiler.target>1.11</maven.compiler.target>
</properties>

You will also need to include the maven-compiler-plugin if you haven’t already like:

plugins>
     <plugin>
	 <groupId>org.apache.maven.plugins</groupId>
	      <artifactId>maven-compiler-plugin</artifactId>
	      <version>3.6.0</version>
	      <configuration>
	        <source>1.11</source>
                <target>1.11</target>
	      </configuration>
	</plugin>
</plugins>

Solution 2: Specific to SPring boot, If you are using spring boot as a parent, you have to set the java version.

<properties>
   <java.version>11</java.version>
</properties>

This will automatically set the correct versions.

If The above-mentioned option didn’t work for you, you can move one step further by changing the “language level” in every module at, File => Project Structure => Modules

Here we discussed how we can change the Java compiler version in IntelliJ and solution to common error while creating a maven project using IntelliJ.

You are free to share if there are other ways to fix this error.

If you are new to Java you may find these articles helpful.

What happens when a Java object is created?

Java bitwise operators with example

Java Exception in detail with example

How to create Java Custom Exception?

Java try with resources statement

Java Generic, Generic with super and wildcard

Happy Learning !!