adam bien's blog

Mapping JPA OptimisticLockException Into HTTP Status Code 📎

A JAX-RS resource deployed as an EJB will wrap all exceptions into javax.ejb.EJBException:


@Stateless
@Path("todos")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public class ToDosResource {
}

An javax.ejb.EJBException can be easily transformed by an ExceptionMapper into a meaningful HTTP status code:

@Provider
public class EJBExceptionMapper implements ExceptionMapper<EJBException> {

    @Override
    public Response toResponse(EJBException ex) {
        Throwable cause = ex.getCause();
        if (cause instanceof OptimisticLockException) {
            OptimisticLockException actual = (OptimisticLockException) cause;
            return Response.status(Response.Status.CONFLICT).
                    header("cause", "conflict caused by entity: " + actual.getEntity()).
                    header("additional-info", actual.getMessage()).
                    build();

        }

        return Response.serverError().
                header("cause", ex.toString()).build();
    }
}

The 409 status code

"...Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request..."
is a natural HTTP representation of the OptimisticLockException.

The example above was taken from the DoIt sample application of the effectivejavaee.com online course.