Custom Exception Handling in Quarkus REST API
In this section, we will learn how to handle exceptions in the Quarkus REST application using ExceptionMapper interface implementations. ExceptionMapper is a contract for a provider that will map a thrown application exception to a Response object.
We will show you custom exception handling with the help of a simple application,
Final Project Directory:
Complete pom.xml
<?xml version="1.0"?><project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>org.knf.dev.demo</groupId> <artifactId>quarku-custom-exception-handling</artifactId> <version>1.0.0-SNAPSHOT</version> <properties> <compiler-plugin.version>3.8.1</compiler-plugin.version> <maven.compiler.parameters>true</maven.compiler.parameters> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <quarkus-plugin.version>2.2.3.Final</quarkus-plugin.version> <quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id> <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id> <quarkus.platform.version>2.2.3.Final</quarkus.platform.version> <surefire-plugin.version>2.22.1</surefire-plugin.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>${quarkus.platform.group-id}</groupId> <artifactId>${quarkus.platform.artifact-id}</artifactId> <version>${quarkus.platform.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy-jsonb</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit5</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>io.quarkus</groupId> <artifactId>quarkus-maven-plugin</artifactId> <version>${quarkus-plugin.version}</version> <executions> <execution> <goals> <goal>build</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>${compiler-plugin.version}</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>${surefire-plugin.version}</version> <configuration> <systemProperties> <java.util.logging.manager> org.jboss.logmanager.LogManager </java.util.logging.manager> </systemProperties> </configuration> </plugin> </plugins> </build>
<profiles> <profile> <id>native</id> <activation> <property> <name>native</name> </property> </activation> <build> <plugins> <plugin> <artifactId>maven-failsafe-plugin</artifactId> <version>${surefire-plugin.version}</version> <executions> <execution> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> <configuration> <systemProperties> <native.image.path> ${project.build.directory}/${project.build.finalName}-runner </native.image.path> </systemProperties> </configuration> </execution> </executions> </plugin> </plugins> </build> <properties> <quarkus.package.type>native</quarkus.package.type> </properties> </profile> </profiles></project>
application.properties
knowledgefactory.custom.error.msg.usernotfound = User not found
knowledgefactory.custom.error.msg.badrequest.numeric = User Id must be numeric
knowledgefactory.custom.error.msg.usernotfound = User not found
knowledgefactory.custom.error.msg.badrequest.numeric = User Id must be numeric
Declared error messages.
Create ErrorMessage.java
package org.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; }
public ErrorMessage(String message, Boolean status) { super(); this.message = message; this.status = status; }
public ErrorMessage() { super(); }}
package org.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; }
public ErrorMessage(String message, Boolean status) { super(); this.message = message; this.status = status; }
public ErrorMessage() { super(); }}
Create the Custom Exception Handler
package org.knf.dev.demo.exception;
import org.eclipse.microprofile.config.inject.ConfigProperty;import javax.ws.rs.core.Response;import javax.ws.rs.ext.ExceptionMapper;import javax.ws.rs.ext.Provider;
@Providerpublic class CustomExceptionHandler implements ExceptionMapper<CustomException> {
@ConfigProperty(name = "knowledgefactory.custom.error.msg.usernotfound")String userNotFound;
@Override public Response toResponse(CustomException e) {
if (e.getMessage().equalsIgnoreCase(userNotFound)) { return Response.status(Response.Status.NOT_FOUND). entity(new ErrorMessage(e.getMessage(), false)) .build(); } else {
return Response.status(Response.Status.BAD_REQUEST). entity(new ErrorMessage(e.getMessage(), false)) .build(); } }}
package org.knf.dev.demo.exception;
import org.eclipse.microprofile.config.inject.ConfigProperty;import javax.ws.rs.core.Response;import javax.ws.rs.ext.ExceptionMapper;import javax.ws.rs.ext.Provider;
@Providerpublic class CustomExceptionHandler implements ExceptionMapper<CustomException> {
@ConfigProperty(name = "knowledgefactory.custom.error.msg.usernotfound")String userNotFound;
@Override public Response toResponse(CustomException e) {
if (e.getMessage().equalsIgnoreCase(userNotFound)) { return Response.status(Response.Status.NOT_FOUND). entity(new ErrorMessage(e.getMessage(), false)) .build(); } else {
return Response.status(Response.Status.BAD_REQUEST). entity(new ErrorMessage(e.getMessage(), false)) .build(); } }}
Create the Custom Exception
package org.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); }}
package org.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 User Pojo
package org.knf.dev.demo.data;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 a dummy data generator
package org.knf.dev.demo.data;import javax.inject.Singleton;import java.util.HashMap;import java.util.Map;@Singletonpublicclass UserData {public User getUserById(Long id) {User user = genearteDummyData().get(id);return user;}//Generate Dummy Usersprivate 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 User Controller
package org.knf.dev.demo.controller;
import org.eclipse.microprofile.config.inject.ConfigProperty;import org.knf.dev.demo.data.User;import org.knf.dev.demo.data.UserData;import org.knf.dev.demo.exception.CustomException;import javax.inject.Inject;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.core.Response;
@Path("/api/v1")public class UserController {
@ConfigProperty(name = "knowledgefactory.custom.error.msg.badrequest.numeric")String idNumericErrorMsg;
@ConfigProperty(name = "knowledgefactory.custom.error.msg.usernotfound")String userNotFound;
@Inject UserData userData;
@GET @Path("/users/{id}") public Response findUserById(@PathParam("id") String id) throws CustomException { Long user_id = null; try { user_id = Long.parseLong(id); } catch (NumberFormatException e) { throw new CustomException(idNumericErrorMsg); } User user = userData.getUserById(user_id); if (user == null) { throw new CustomException(userNotFound); } return Response.ok(). entity(userData.getUserById(user_id)).build(); }}
package org.knf.dev.demo.controller;
import org.eclipse.microprofile.config.inject.ConfigProperty;import org.knf.dev.demo.data.User;import org.knf.dev.demo.data.UserData;import org.knf.dev.demo.exception.CustomException;import javax.inject.Inject;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.core.Response;
@Path("/api/v1")public class UserController {
@ConfigProperty(name = "knowledgefactory.custom.error.msg.badrequest.numeric")String idNumericErrorMsg;
@ConfigProperty(name = "knowledgefactory.custom.error.msg.usernotfound")String userNotFound;
@Inject UserData userData;
@GET @Path("/users/{id}") public Response findUserById(@PathParam("id") String id) throws CustomException { Long user_id = null; try { user_id = Long.parseLong(id); } catch (NumberFormatException e) { throw new CustomException(idNumericErrorMsg); } User user = userData.getUserById(user_id); if (user == null) { throw new CustomException(userNotFound); } return Response.ok(). entity(userData.getUserById(user_id)).build(); }}
Quarkus Exception Handling demo
Build application jar file: mvn clean package
Build application jar file: mvn clean package
Start the application: java -jar quarkus-run.jar
Start the application: java -jar quarkus-run.jar
Invalid Request (User Id not found):
Invalid Request(User Id must be numeric):
Valid request:
More related topics,