Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Status codes and Response

The status code is the first thing an API client sees: did it work, was the record created, does it exist. When a resource method returns an object, Jakarta REST answers 200 OK. When you need another code or extra headers, the method returns a Response object — a full description of the reply: status, headers and body.

Main status codes

CodeWhen it is used
200 OKData received
201 CreatedRecord created, its address is in the Location header
204 No ContentSuccess without a body: for example after a delete
400 Bad RequestAn error in the client's data
404 Not FoundNo such record
415 Unsupported Media TypeWrong Content-Type
500 Internal Server ErrorAn unhandled exception on the server

The post or 404

Add a delete method to PostStore that reports whether the post existed:

// src/main/java/com/example/blog/PostStore.java (fragment)
public boolean delete(long id) {
    return posts.remove(id) != null;
}

Now the methods of the resource src/main/java/com/example/blog/PostResource.java:

// src/main/java/com/example/blog/PostResource.java (fragment)
@GET
@Path("/{id}")
public Response show(@PathParam("id") long id) {
    return store.findById(id)
            .map(post -> Response.ok(post).build())
            .orElse(Response.status(Response.Status.NOT_FOUND).build());
}
 
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response create(NewPost data, @Context UriInfo uriInfo) {
    Post post = store.add(data);
    URI location = uriInfo.getAbsolutePathBuilder()
            .path(String.valueOf(post.id()))
            .build();
    return Response.created(location).entity(post).build();
}
 
@DELETE
@Path("/{id}")
public void delete(@PathParam("id") long id) {
    if (!store.delete(id)) {
        throw new NotFoundException("Post " + id + " not found");
    }
}

The imports you need are jakarta.ws.rs.DELETE, jakarta.ws.rs.NotFoundException, jakarta.ws.rs.core.Context, jakarta.ws.rs.core.Response, jakarta.ws.rs.core.UriInfo and java.net.URI.

What happens here:

  • show returns Response.ok(post) or a 404 response without a body.
  • create builds the address of the new post from the address of the current request. The server passes UriInfo through @Context. Response.created(location) gives status 201 and a Location header.
  • delete returns nothing — for a void method Jakarta REST answers 204. The NotFoundException becomes a 404 response.

Trying it out

curl -i -H "Content-Type: application/json" -d '{"title":"Status codes","body":"201, 204 and 404."}' http://localhost:8080/blog/api/posts
HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:8080/blog/api/posts/3
Content-Length: 83

{"body":"201, 204 and 404.","createdAt":"2026-10-04","id":3,"title":"Status codes"}
curl -i -X DELETE http://localhost:8080/blog/api/posts/3
curl -i -X DELETE http://localhost:8080/blog/api/posts/3
curl -i http://localhost:8080/blog/api/posts/99

The first delete returns HTTP/1.1 204 No Content, the second HTTP/1.1 404 Not Found: the post is already gone. Requesting a missing post also gives 404.

Ready-made exceptions

Instead of a Response you can throw an exception — Jakarta REST turns it into a status code:

ExceptionCode
BadRequestException400
NotAuthorizedException401
ForbiddenException403
NotFoundException404
WebApplicationException(status)Any

Common mistake

Returning null from a method that should return an object. In the previous lesson show returned store.findById(id).orElse(null), and a request for a missing post ended like this:

HTTP/1.1 204 No Content

The client sees success and an empty body instead of an error. When the record does not exist, answer 404 — with a Response or an exception.

Thanks for reading!

Donate to the site — we work hard for you.