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:
<?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;
@Singletonpublic 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;
@Controllerpublic 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