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 !!

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.

 

Spring circular dependency with resolution

Problem:

Circular Dependency

Exception:

org.springframework.beans.factory.BeanCurrentlyInCreationException

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'reportService': Bean with name 'reportService' has been injected into other beans [dataExportService] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:622)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
	... 45 more

The most common reason for this is a circular dependency. Where two or more dependent classes declare each other as a dependency.

Spring Circular Dependency

Like:

public class Service1 {

	@Autowired
	private Service2 service2;
}

public class Service2 {

        @Autowired
	private Service1 service1;
}

Solution:

To resolve this exception check if you can remove the dependency from one of the classes. This is likely a design problem where responsibilities are not properly separated.

If the redesign is not the choice there are other workarounds as well.

The @Lazy annotation

As the annotation name suggests, we can break the cycle by initializing one of the beans lazily, instead of fully initializing the bean. It will create a proxy to inject it into the other bean. The injected bean will only be fully created when it’s first needed. We can refactor our Service1 like below.

import org.springframework.context.annotation.Lazy;
@Service
public class Service1 {

	private Service2 service2;
	
	@Autowired
	public Service1(@Lazy Service2 service2) {
		this.service2 = service2;
	}
}

Using Setter/Field Injection

Simply changes the way beans are wired to use setter injection (or field injection) instead of constructor injection also purposed by Spring docs. This way Spring creates the beans, but the dependencies are only injected when they are needed.

Let’s refactored Service1 to use setter injection.

public class Service1 {

	private Service2 service2;

	@Autowired
	public void setService2(Service2 service2) {
		this.service2 = service2;
	}

	public Service2 getService2() {
		return service2;
	}
   }
}

The @PostConstruct annotation

Another savior from circular dependency is @PostConstruct annotation. We can use this to inject the dependency after this bean is initialized.

To use it, we can refactor both Service1 and Service2 as below.

@Service
public class Service2 {
	
	private Service1 service1;
	
	public void setService1(Service1 service1) {
		this.service1 = service1;
	}
}


import javax.annotation.PostConstruct;

@Service
public class Service1 {

	@Autowired
	private Service2 service2;

	@PostConstruct
	public void init() {
		service2.setService1(this);
	}

	public Service2 getService2() {
		return service2;
	}
}

Read More about Java Exception.

Happy Learning !!

Spring boot: Path with “WEB-INF” or “META-INF”

Warning Path with “WEB-INF” or “META-INF”

Today I faced an issue while developing a spring boot demo app. I Have created a spring boot project, added UserController, and updated the application.properties file with the following configuration.

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp

The complete project structure looks like below.

WEB-INF or META-INF

These configurations are used to tell spring where to look for JSP files. We can configure it in our Springboot application class as well as below.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@SpringBootApplication
public class DemoappApplication implements WebMvcConfigurer{

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

	@Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/view/");
        resolver.setSuffix(".jsp");
        resolver.setViewClass(JstlView.class);
        registry.viewResolver(resolver);
    }
}

UserController.java

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/user")
public class UserController {

	@GetMapping("/add")
	public String dispalyAddUser(Model model) {

		return "add-user";
		
	}
}

ad-user.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>add user</title>
</head>
<body>
	
</body>
</html>

After creating all the required files, I started the application and access the URL http://localhost:8080/user/add. I was expecting an empty HTML page with the title “add user” based on the configuration, but in response displayed an error page.

Path with WEB-INF or META-INF

Therefore I checked the console log and found the warning “WARN 3676 — [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : Path with “WEB-INF” or “META-INF”: [WEB-INF/view/add-user.jsp]”.

Root Cause

The class requires to resolve the JSP path is available in the tomcat jasper package and the dependency is not added in pom.xml. Hence, the spring boot application is not able to resolve the JSP path.

Solution

The dependent classes are available in tomcat jasper. Add tomcat jasper dependency in the pom.xml file.

<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

You can copy this from the maven repository as well.

Once you add the above dependency in the pom.xml file and re-run the application it will work as expected.

Recommended Read

Java Exception in detail with example
Java Exception Test

Happy Learning !!

Java try with resources statement

Java Exception handling try with resources statement.

Similar to Multi-catch introduced in Java 7 another enhancement made is the try-with-resources Statement.

Earlier the resources need to be close inside the try{ …. } block. But since Java 7 this can be using try-with-resources Statement.

As per the oracle doc

The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.

See the below code snippet before Java 7.

public class TryWithResourceExample {

    public static void main(String[] args) {
        readFile("/home/input.txt");
    }

    static String readFile(String path) {
        File file = null;
        try {
            StringBuilder sb = new StringBuilder();
            file = new File(path);
            Scanner sc = new Scanner(file);
            while(sc.hasNextLine()) {
                
                sb.append(sc.nextLine());
            }
            sc.close();
            
            return sb.toString();
            
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

The above code can be rewritten using the try with a resource statement like the below.

public class TryWithResourceExample {

    public static void main(String[] args) {
        readFile("/home/input.txt");
    }

    static String readFile(String path) {
        StringBuilder sb = new StringBuilder();
        
        try (Scanner sc = new Scanner(new File(path))){
            
            while(sc.hasNextLine()) {
                sb.append(sc.nextLine());
            }
            
        }catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
}

The try with the resource can also be used with multiple closeable resources. Observe the following code snippet.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

public class TryWithResourceExample {

    public static void main(String[] args) {
        readFile("/home/inputfile.txt");
    }

    static void readFile(String path) {
        
        try (InputStream i = new FileInputStream(new File(path)); 
             BufferedReader reader = new BufferedReader(new InputStreamReader(i));    
            ){
            
            System.out.println("File content is : "+reader.readLine());
            
        }catch (Exception e) {
            e.printStackTrace();
        }
        
    }
}

Point to remember: Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used inside the try with resource statement.

For Objects that do not implement AutoCloseable, the compiler will alert the following error.

The resource type {Resource name} does not implement java.lang.AutoCloseable

Recommended read:

Java Exception in detail with example
How to create custom Java Exception?

Happy Learning !!

How to create Java Custom Exception?

How to create Java Custom Exception?

Java provides a huge hierarchy of Exceptions include both checked and unchecked exceptions. But sometimes when we have to choose which type of exception to be thrown, we can either choose the one already defined by Java or we can write our own custom Java exception.

But when will you require to write your exception, or I would say, how to decide when to write a custom Exception?

The main reasons for introducing custom exceptions are:

  • Business logic exceptions: Exceptions that are specific to the business logic and workflow. These help the application users or the developers understand what the exact problem is.
  • To catch and provide specific handling to an exception to provide clear exception cause.

We can write both checked and unchecked custom exception, let’s see how to create it.

Checked custom exception:

For example, refer following code snippet.

public static void readFromFile()  {
    try {
        File file = new File("/home/inputfile.txt");
        InputStream is = new FileInputStream(file);
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        System.out.println(br.readLine());
        
        is.close();
        br.close();
        
    } catch (IOException e) {   
        e.printStackTrace();
    }

}

In the above code snippet, the IOException can be caused by multiple reasons. i.e. FileNotFoundException. Even FileNotFoundException can have multiple causes, like the file is not available or the file is present but the file name is not valid. So what if we want to tell the user that the file name is not valid. In this case, we can make our Custom checked exception and throw it if the name is not valid.

Let’s create the custom checked exception.

public class InvalidFileNameException extends Exception{
    
    private static final long serialVersionUID = 3411057007944826395L;

    public InvalidFileNameException(String message) {
        super(message);
    }
}

Now, let’s rewrite the above method using custom exceptions. Observe the following code snippet.

public class CustomExceptionExample{
    
    public static void main(String[] args) throws InvalidFileNameException {
        readFromFile();
    }

    public static void readFromFile() throws InvalidFileNameException  {
        File file = null;
        try {
            file = new File("/home/input.file.txt");
            InputStream is = new FileInputStream(file);
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            System.out.println(br.readLine());
            
            is.close();
            br.close();
            
        } catch (IOException e) { // this IOException can be caused by multiple reason. i.e. FileNotFoundException  
            if(e instanceof FileNotFoundException) {
                if(isInvalidFileName(file.getName())) {
                    throw new InvalidFileNameException("file name "+file.getName() + " is not valid");
                }
            }
        }
    }
    
    // Invalid file name if it has multiple dot (.)
    static boolean isInvalidFileName(String fileName) {
        String [] arr = fileName.split("\\.");
        return arr.length > 2;
    }    
}

Using this way we can tell the user that, the file name is not valid.

Unchecked custom exception:

Similar to the checked custom exception, we can create an unchecked custom exception. Assume we are reading text from a text file, but if the input is not a text file we should throw an exception that the file extension is not valid. Observe the below code, we will come to know about the file extension only during the runtime, hence we will create an unchecked custom exception to throw invalid file extension.

Let’s create a custom unchecked exception.

public class InvalidFileExtension extends RuntimeException {

    private static final long serialVersionUID = -7284958373872448993L;
    
    public InvalidFileExtension(String message) {
        super(message);
    }
}

Observe the following code snippet.

public class CustomExceptionExample{
    
    public static void main(String[] args) throws InvalidFileNameException {
        readFromFile();
    }

    public static void readFromFile() throws InvalidFileNameException  {
        //file = new File("/home/input.file.txt");
        File file = new File("/home/abc.gif");
        
        try (Scanner sc = new Scanner(file)){
            
            if(sc.hasNextLine()) {
                System.out.println(sc.nextLine());
            }else {
                throw new InvalidFileExtension("not a valid file " + file.getName());
            }    
        }catch (FileNotFoundException e) {
            if(isInvalidFileName(file.getName())) {
                throw new InvalidFileNameException("file name "+file.getName() + " is not valid");
            }
        }
    }
    
    // Invalid file name if it has multiple (.)
    static boolean isInvalidFileName(String fileName) {
        String [] arr = fileName.split("\\.");
        return arr.length > 2;
    }    
}

If the custom exception is implemented properly, it can be very helpful for writing business logic and effective application logging.

Recommended read:
Exception in detail
How to create custom Java Exception?

Happy Learning !!

Reference:

Exception Oracle Docs

Java Exception in detail with example

Let’s start the topic with what is an Exception?

Exceptions are unexpected events that occur during the execution of a program. An exception might result due to an unavailable resource, unexpected input from a user, or simply a logical mistake by the programmer. In Java, exceptions are objects that can be thrown by code that encounters an unexpected situation, or by the Java Virtual Machine. For example, if JVM running out of memory. An exception may also be caught by a surrounding block of code that “handles” the problem in an appropriate way. If uncaught, an exception causes the virtual machine to stop executing the program and print an appropriate message with the root cause to the console.

Catching Exceptions:

If an exception occurs and is not handled by the programmer, then the Java run-time will terminate the program after printing an appropriate message together with a trace of the run-time stack. The stack trace shows the series of nested method calls that were active at the time the exception occurred, as in the following example:

Exception in thread "main" java.lang.NullPointerException
at com.exception.AllAboutException.main(AllAboutException.java:31)

However, before a program is terminated, each method on the stack trace has an opportunity to catch the exception. Starting with the method in which the exception occurs. Each method may either catch the exception or allow it to pass through to the method that called it. This is also known as exception propagation.

The usual way of exception handling is a try-catch construct in which a snippet of code that might throw an exception is executed. If it throws an exception, then that exception caught by a predefined catch block. That catch block contains the code to analyze the exception and apply an appropriate resolution. If no exception occurs in that code snippet inside the try block, all catch blocks are ignored.

The typical syntax for a try-catch block in Java is as follows:

try {
/.. code snippet

} catch (exceptionType1  e1) {

// TODO::

} catch (exceptionType2  e2) {
// TODO::
*
}
/…

Let’s changes the code that caused java.lang.NullPointerException, by putting it inside a try-catch block as below.

public class AllAboutException {
    
    public static void main(String[] args) {
        Object obj = null;
        try {
            System.out.println(obj.toString());
        }catch (Exception e) {
            System.out.println(" Exception during execution obj is: "+ obj);
            
        }
    }
} 

Again run the above code, this time it will only print the message “exception during execution obj is: null“.

Try with Multiple catch block:

Similar to above we can have multiple catch blocks for a try block. The point to be remembered is that the order of the catch block should be most relevant to most generic. Consider the following example.

public class AllAboutException {
        
    public static void main(String[] args) {
        try {
            int a = Integer.parseInt(args[0]);
            
            if(a < 0) {
                a = 10;
                System.out.println("default value of a is "+a);
            }
            else
                System.out.println("value received of a is "+a); 
            
        }
        catch (ArrayIndexOutOfBoundsException ae) {
            System.out.println(" no argument passed to main ");
        }catch (NumberFormatException ne) {
            System.out.println(" the argument passed to main is not a valid integer");
        }catch (Exception e) {
            System.out.println("Error while processing.");
        }

    }
}

Multi Catch

Since Java 7 it was made possible to catch multiple different exceptions in the same catch block. It is often known as multi-catch. By applying this concept we can change the above catch block like below:

 
catch (ArrayIndexOutOfBoundsException | NumberFormatException | Exception e) {
        System.out.println(" Error while processing.");
}

Finally:

Writing the code inside the try-catch block is fine to avoid unintended execution of programs. But what if you have to perform some task even if there is an exception?

In those cases, we can use the finally block, which executes whether there is an exception or not.

The key point while writing the code inside a try:

A try block must be followed by at least one catch block or by a finally block. We can have both as well. Refer to the code snippet.

public class AllAboutException {
        
    public static void main(String[] args) {
        try {
            int a = Integer.parseInt(args[0]);
            
            if(a < 0) {
                a = 10;
                System.out.println("default value of a is "+a);
            }
            else
                System.out.println("value received of a is "+a); 
            
        }
        catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
            System.out.println("Error in execution");
        }
        finally {
            System.out.println("Finally block after catch ");
        }
    }
}

If you run the above program the output will be as below:

Error in execution
Finally block after catch   

So, enough reading about Exception, let’s take a simple test and see if you could answer it correctly.

Throwing Exceptions:

Exceptions occur when a chunk of Java code finds some problem during execution and throws an exception object. This is done by using the throw keyword followed by an instance of the exception type to be thrown, as follows:

throw new exceptionType(message);

Where the exception type is the type of exception and the message is the parameters sent to the constructor.

public class AllAboutException {
        
    public static void main(String[] args) {
        
        isPositiveInt(-1);
        
    }
    
    public static boolean isPositiveInt(int a) {
        if( a < 0) {
            throw new IllegalArgumentException(" only positive int allowed");
        } 
        return true;
    }
}
 
<strong>Output:</strong>

Exception in thread "main" java.lang.IllegalArgumentException:  only positive int allowed
    at com.exception.AllAboutException.isPositiveInt(AllAboutException.java:157)
    at com.exception.AllAboutException.main(AllAboutException.java:151)

Note: The execution of a throw statement immediately terminates the body of a method.

The Throws Clause

Java allows us to declare exceptions as part of its method signature, which is achieved using the throws clause. The possibility that a particular exception may be thrown during a call to that method. It does not matter whether the exception is directly from a throw statement in that method body, or propagated upward from a method call made from within the body of the method itself.

The syntax for declaring possible exceptions in a method signature relies on the keyword throws. For example, the parseInt method of the Integer class has the following formal signature:

public static int parseInt(String s) throws NumberFormatException;

The ‘throws NumberFormatException’ warns the caller of that method about the possibility of an exception if the inputs are not valid so that they might be better prepared to handle an exception that may arise. If more than one exception requires to be thrown, all such types can be listed, separated with commas.

Java Exception Hierarchy:

Java provides an inheritance hierarchy of all objects that are deemed Throwable. The exception hierarchy is divided into two subclasses, Error and Exception.

Errors are typically thrown only by the Java Virtual Machine and designate the most severe situations that are unlikely to be recoverable, such as when the system runs out of memory. On the other hand, exceptions designate situations in which a running program might be able to recover or can be handled using a try-catch block, for example, like files not found, etc.

Further to this Exceptions are categories in two categories:

  • Checked Exception
  • Unchecked Exception

All subclasses of RuntimeException in Java are officially treated as unchecked exceptions, and any exception type that is not part of the RuntimeException is a checked exception.

Exeption Hierarchy

Recommended read:
How to create custom Java Exception?
Java try with resources statement

Reference:
https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html

Happy Learning !!

springframework.beans.factory.BeanCreationException

Problem

While working on a Spring Boot demo application encounter error creating bean with name ‘userRepo’

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘userRepo’: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.example.entity.User

The complete stack trace is as below.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepo': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.example.entity.User
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1287) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	... 19 common frames omitted
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.example.entity.User
	at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:582) ~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
	at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:85) ~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
	at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:74) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:211) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:161) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:144) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:69) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:312) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.util.Lazy.getNullable(Lazy.java:212) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.util.Lazy.get(Lazy.java:94) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:121) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
	... 29 common frames omitted

After giving it multiple try found the solution, which is just some config changes that need to be done inside the Spring boot config file.

Add the below line in your Spring boot application and provide the package name containing entity classes.

@EntityScan(basePackages = {"com.example.entity"})

Recommended Read

Java Exception in detail with example
How to create custom Java Exception?

Happy Learning !!

Cannot be cast to java.lang.Comparable

Problem: java.lang.ClassCastException: com.coderdesks.basic.Orders cannot be cast to java.lang.Comparable

Exception in thread "main" java.lang.ClassCastException: com.coderdesks.basic.Orders cannot be cast to java.lang.Comparable
	at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
	at java.util.Arrays.sort(Arrays.java:472)
	at com.coderdesks.basic.ComparatorVsComparable.main(ComparatorVsComparable.java:25)
	

Reason:
When we sort array or collection of primitive or wrapper classes it works fine. The reason for that is that these classes have implemented a Comparable interface. But when we try to sort an array of the custom object which does not implement a comparable interface you will face this exception.

Solution:
To resolve this exception implements the Comparable interface and override the compareTo () method just like we have changed the Orders class as shown below.

package com.coderdesks.basic;

public class Orders implements Comparable<Orders>{

	private int orderId;
	
	private double amount;
	
	private String orderBy;

	public Orders(){
		
	}

	public Orders(int orderId, double amount, String orderBy) {
		super();
		this.orderId = orderId;
		this.amount = amount;
		this.orderBy = orderBy;
	}

	@Override
	public String toString() {
		return "Orders [orderId=" + orderId + ", amount=" + amount + ", orderBy=" + orderBy + "]";
	}

	@Override
	public int compareTo(Orders o) {
		return (this.orderId - o.orderId);
	}
}

Recommended Read

Comparable and Comparator.
Java Exception in detail with example

Happy Learning !!