Learn Quarkus - RESTEasy & REST API
Episode 5 of 24

Learn Quarkus - RESTEasy & REST API

This episode builds a REST API with RESTEasy Reactive: mapping requests with @GET, @POST, @PUT, @DELETE and @Path, binding bodies and response objects, up to error handling with a custom exception mapper.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

After mastering CDI, it's time to build the interface most Quarkus applications use the most: a REST API. Quarkus uses RESTEasy Reactive — a Vert.x-based JAX-RS implementation that is non-blocking and tightly integrated with build-time augmentation.

Episode 5 covers the foundations of a REST API: mapping endpoints with @GET, @POST, @PUT, @DELETE, and @Path, binding JSON bodies to Java objects, producing response objects, and error handling with a custom exception mapper.

Building a REST Endpoint with RESTEasy Reactive

Your First Resource

RESTEasy Reactive uses the standard JAX-RS annotations. A simple resource class:

JavaFirst REST endpoint
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
 
@Path("/api/hello")
public class HelloResource {
 
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String halo() {
        return "Halo Quarkus!";
    }
}

With the resteasy-reactive-jackson extension, JSON is also supported:

Adding the JSON extension
./mvnw quarkus:add-extension -Dextensions=resteasy-reactive-jackson

Objects as Responses

For a real API, return a Java object that's automatically serialized to JSON:

JavaResponse object
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
 
@Path("/api/greeting")
public class GreetingResource {
 
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public GreetingResponse greeting() {
        return new GreetingResponse("Halo", "Quarkus");
    }
 
    public record GreetingResponse(String message, String to) {}
}

The @GET method returns a Java record that Jackson automatically serializes to JSON. Run it with ./mvnw quarkus:dev then test it with curl.

Request Mapping: HTTP Methods and Paths

Full CRUD

RESTEasy Reactive maps every HTTP method:

JavaCRUD resource with RESTEasy
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.ArrayList;
 
@Path("/api/items")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ItemResource {
 
    private final List<Item> items = new ArrayList<>();
 
    @GET
    public List<Item> list() { return items; }
 
    @GET
    @Path("/{id}")
    public Item get(@PathParam("id") long id) {
        return items.stream()
            .filter(i -> i.id() == id)
            .findFirst()
            .orElseThrow(() -> new NotFoundException("Item tidak ditemukan"));
    }
 
    @POST
    public Item create(Item item) {
        items.add(item);
        return item;
    }
 
    @PUT
    @Path("/{id}")
    public Item update(@PathParam("id") long id, Item item) {
        items.set((int) id, item);
        return item;
    }
 
    @DELETE
    @Path("/{id}")
    public void delete(@PathParam("id") long id) {
        items.removeIf(i -> i.id() == id);
    }
 
    public record Item(long id, String nama) {}
}

The @Path("/{id}") annotation captures a path segment, and @PathParam("id") maps it to a method parameter. This is the standard pattern for resources with path parameters.

Body Binding and Content Negotiation

A parameter without any annotation on a POST method is automatically bound from the JSON body. @GET methods cannot have a body, while @POST, @PUT, and @PATCH use the request body. Besides @PathParam, JAX-RS also provides @QueryParam for query strings and @HeaderParam for headers. @Produces and @Consumes control the content format, for example MediaType.APPLICATION_JSON for JSON.

Error Handling and Custom Exception Mappers

ExceptionMapper

JAX-RS provides an exception mapper mechanism to translate exceptions into clean HTTP responses:

JavaCustom exception mapper
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
 
@Provider
public class ItemNotFoundMapper implements ExceptionMapper<NotFoundException> {
 
    @Override
    public Response toResponse(NotFoundException ex) {
        return Response.status(Response.Status.NOT_FOUND)
            .entity(new ErrorResponse(404, ex.getMessage()))
            .build();
    }
 
    public record ErrorResponse(int status, String message) {}
}

With @Provider and the ExceptionMapper<T> implementation, every exception of type NotFoundException is translated into a 404 response with a structured JSON body.

A Centralized Error Format

Consistency in the error format matters for APIs used by many clients. Create one centralized error format and register mappers for global exceptions. Test the error handling with curl:

Testing endpoints and errors
curl http://localhost:8080/api/items
curl -i http://localhost:8080/api/items/999

The command curl http://localhost:8080/api/items returns the list of items as JSON, while a request to a non-existent item returns a structured error body with status 404.

Wrap-Up

Episode 5 builds the foundation of your REST API: creating resources with RESTEasy Reactive, mapping all HTTP methods and path parameters, binding JSON bodies to Java objects, producing response objects, and handling errors with a custom exception mapper.

Key takeaways:

  • RESTEasy Reactive uses the standard JAX-RS annotations.
  • @Path("/{id}") together with @PathParam captures path segments.
  • @GET has no body; @POST, @PUT, @PATCH use the body.
  • @Produces and @Consumes control the content format.
  • Java objects and records are automatically serialized to JSON.
  • ExceptionMapper handles errors with a centralized format.

In episode 6 we'll connect your application to a database — Hibernate ORM and Panache, entity mapping, the repository pattern, datasource and connection pooling configuration, as well as the in-memory H2 database for development.

Learn Quarkus - RESTEasy & REST API | Learn Quarkus