W jaki sposób powinienem rejestrować niezłapane wyjątki w mojej usłudze RESTful JAX-RS?

Mam serwis internetowy RESTful działający pod Glassfish 3.1.2 z wykorzystaniem Jersey i Jacksona:

@Stateless
@LocalBean
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("users")
public class UserRestService {
    private static final Logger log = ...;

    @GET
    @Path("{userId:[0-9]+}")
    public User getUser(@PathParam("userId") Long userId) {
        User user;

        user = loadUserByIdAndThrowApplicableWebApplicationExceptionIfNotFound(userId);

        return user;
    }
}

Dla oczekiwanych wyjątków rzucam odpowiednieWebApplicationExceptioni jestem zadowolony ze statusu HTTP 500, który jest zwracany, jeśli wystąpi nieoczekiwany wyjątek.

Chciałbym teraz dodać rejestrację dla tych nieoczekiwanych wyjątków, ale mimo wyszukiwania nie mogę dowiedzieć się, jak japowinien chodzić o tym.

Bezowocna próba

Próbowałem użyć aThread.UncaughtExceptionHandler i może potwierdzić, że jest on stosowany wewnątrz treści metody, ale jejuncaughtException Metoda nigdy nie jest wywoływana, ponieważ coś innego obsługuje nieprzechwycone wyjątki, zanim dotrą do mojego handlera.

Inne pomysły: # 1

Inną opcją, którą widziałem, niektórzy ludzie używająExceptionMapper, która łapie wszystkie wyjątki, a następnie odfiltrowuje WebApplicationExceptions:

@Provider
public class ExampleExceptionMapper implements ExceptionMapper<Throwable> {
    private static final Logger log = ...;

    public Response toResponse(Throwable t) {
        if (t instanceof WebApplicationException) {
            return ((WebApplicationException)t).getResponse();
        } else {
            log.error("Uncaught exception thrown by REST service", t);

            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                   // Add an entity, etc.
                   .build();
        }
    }
}

Chociaż takie podejście może działać, wydaje mi się, że niewłaściwe użycie tego, do czego mają być używane wyjątki ExceptionMappers, to znaczy odwzorowanie pewnych wyjątków na pewne odpowiedzi.

Inne pomysły: # 2

Większość przykładowego kodu JAX-RS zwracaResponse obiekt bezpośrednio. Zgodnie z tym podejściem mogę zmienić mój kod na taki jak:

public Response getUser(@PathParam("userId") Long userId) {
    try {
        User user;

        user = loadUserByIdAndThrowApplicableWebApplicationExceptionIfNotFound(userId);

        return Response.ok().entity(user).build();
    } catch (Throwable t) {
        return processException(t);
    }
}

private Response processException(Throwable t) {
    if (t instanceof WebApplicationException) {
        return ((WebApplicationException)t).getResponse();
    } else {
        log.error("Uncaught exception thrown by REST service", t);

        return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
               // Add an entity, etc.
               .build();
    }
}

Jednak nie podoba mi się pójście tą trasą, ponieważ mój rzeczywisty projekt nie jest tak prosty jak ten przykład i musiałbym zaimplementować ten sam wzorzec w kółko, nie wspominając już o konieczności ręcznego budowania odpowiedzi.

Co powinienem zrobić?

Czy istnieją lepsze metody dodawania rejestrowania dla nieprzechwyconych wyjątków? Czy istnieje „właściwy” sposób wdrożenia tego?

questionAnswers(5)

yourAnswerToTheQuestion