Micronaut REST Exception Handling - Global

Hello everyone, today we will learn how to handle exceptions in the Micronaut REST application using ExceptionHandler. You can download the source code from our Github Repository.

Project Directory:



Pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.knf.dev.demo</groupId>
<artifactId>micronaut-global-exception-handling</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>

<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.1.3</version>
</parent>

<properties>
<packaging>jar</packaging>
<jdk.version>11</jdk.version>
<release.version>11</release.version>
<micronaut.version>3.1.3</micronaut.version>
<exec.mainClass>com.knf.dev.demo.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>

<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths combine.children="append">
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-validation</artifactId>
<version>${micronaut.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=com.knf.dev.demo</arg>
<arg>
-Amicronaut.processing.module=micronaut-global-exception-handling
</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>



Create a POJO class:

package com.knf.dev.demo.model;

public class User {

private String name;
private String email;

public User(String name, String email) {
this.name = name;
this.email = email;
}

public String getName() {
return name;
}

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

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}
}



Create an Error Message:

package com.knf.dev.demo.exception;

public class ErrorMessage {

private String message;
private Boolean status;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public Boolean getStatus() {
return status;
}

public void setStatus(Boolean status) {
this.status = status;
}
}



Create a data generator class:

package com.knf.dev.demo.data;

import java.util.HashMap;
import java.util.Map;
import com.knf.dev.demo.model.User;
import jakarta.inject.Singleton;

@Singleton
public class UserData {

public User getUserById(Long id) {
User user = genearteDummyData().get(id);
return user;
}

// Generate Dummy Users
private Map<Long, User> genearteDummyData() {

Map<Long, User> dummyUsers = new HashMap<>();

User user1 = new User("user-1", "user-1@gmail.com");
User user2 = new User("user2", "user2@gmail.com");
User user3 = new User("user3", "user3@gmail.com");

dummyUsers.put(22l, user1);
dummyUsers.put(13l, user2);
dummyUsers.put(19l, user3);

return dummyUsers;
}
}


Create the Custom Exception:

package com.knf.dev.demo.exception;

import java.io.Serializable;

public class CustomException extends RuntimeException
implements Serializable {

private static final long serialVersionUID = 1L;

public CustomException() {
}

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

public CustomException(String message, Throwable cause) {
super(message, cause);
}

public CustomException(Throwable cause) {
super(cause);
}

public CustomException(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause,
enableSuppression, writableStackTrace);
}
}


Create the Custom Exception Handler:

package com.knf.dev.demo.exception;

import io.micronaut.context.annotation.Requires;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.annotation.Produces;
import io.micronaut.http.server.exceptions.ExceptionHandler;
import jakarta.inject.Singleton;

@Produces
@Singleton
@Requires(classes = { CustomException.class, ExceptionHandler.class })

public class CustomExceptionHandler
implements ExceptionHandler<CustomException,
HttpResponse<ErrorMessage>> {

@Override
public HttpResponse<ErrorMessage>
handle(HttpRequest request, CustomException exception) {

ErrorMessage message = new ErrorMessage();
message.setMessage(exception.getMessage());
message.setStatus(false);
return HttpResponse.serverError(message).
status(HttpStatus.BAD_REQUEST);
}
}



Create the User Controller class:

package com.knf.dev.demo.controller;

import com.knf.dev.demo.data.UserData;
import com.knf.dev.demo.exception.CustomException;
import com.knf.dev.demo.model.User;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

@Controller
public class UserController {

protected final UserData userData;

public UserController(UserData userData) {
this.userData = userData;
}

@Get("/users/{id}")
public User findUserById(String id) throws CustomException {
Long user_id = null;
try {
user_id = Long.parseLong(id);
} catch (NumberFormatException e) {
throw new CustomException("User Id must be numeric");
}
User user = userData.getUserById(user_id);
if (user == null) {
throw new CustomException("Entity Not Found");
}
return user;
}
}



Main

package com.knf.dev.demo;

import io.micronaut.runtime.Micronaut;

public class Application {

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



Verify the REST APIs

Run as Java Application 

or

mvn mn:run


Invalid Request (Entity Not found):



Invalid Request(User Id must be numeric):



Valid request:

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Spring Boot + Mockito simple application with 100% code coverage

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete