Пусть ExceptionMapper возвращает разные типы ответов в зависимости от того, откуда происходит исключение

У меня есть ExceptionMapper с именем NotFoundExceptionMapper, который мне нужно вести себя так:

@Provider
public class NotFoundExceptionMapper implements
    ExceptionMapper<NotFoundException> {

    public Response toResponse(NotFoundException e) {
        if(e originated from ClassA)
            // create a complex ResponseTypeA and return it
        if(e originated from ClassB)
            // create a complex ResponseTypeB and return it
        return DefaultResponseType;
    }    
}

Причина, по которой мне нужно что-то подобное, заключается в том, что на моем уровне REST каждый метод в классе ClassA по сути одинаково обрабатывает ошибки try & catch, что приводит к большому количеству избыточного кода. То же самое относится и к ClassB. Единственная разница между classA и ClassB состоит в том, что методы в classA должны возвращать тип ответа, отличный от методов в classB.

ExceptionMapper, кажется, отличный способ избежать избыточного кода обработки ошибок. Осталось только решить, откуда возникло исключение (ClassA или ClassB), выполнить универсальную обработку ошибок и вернуть правильный тип ответа.

У меня уже есть код для этого, но мне интересно, есть ли более элегантный способ сделать это. В Джерси есть еще много вещей, с которыми я не знаком, так что есть большая вероятность, что я что-то пропустил.

Код довольно прост и использует инъекцию UriInfo, чтобы определить, откуда возникло исключение.

Мой ExceptionMapper:

@Provider
public class NotFoundExceptionMapper implements
    ExceptionMapper<NotFoundException> {

    @Context
    UriInfo uriInfo;

    public Response toResponse(NotFoundException e) {
        // MyResponseBuilder decides which response type to return:
        return MyResponseBuilder.buildResponse(uriInfo, e, Response.Status.NOT_FOUND);
    }    
}

Класс MyResponseBuilder делает всю магию. Он анализирует UriInfo и возвращает правильный тип ответа.

public class MyResponseBuilder {
    public static Response buildResponse(UriInfo uriInfo, Exception e, Status status) {
        List<Object> matchedRes = uriInfo.getMatchedResources();
        if(matchedRes.size() == 1) {
            Object res = matchedRes.get(0);
            if(res.getClass() == ClassA.class) {
                ResponseTypeA resp = new ResponseTypeA();
                // populate resp with infos
                return Response.status(status).entity(resp).build();
            }
            else if(res.getClass() == ClassB.class) {
                ResponseTypeB resp = new ResponseTypeB();
                // populate resp with infos
                return Response.status(status).entity(resp).build();
            }
        }
        return Response.status(status).build(); // default response 
    }
}

И хотя это работает, это может в конечном итоге вызвать некоторые неприятные проблемы, если существует более одного сопоставленного ресурса, работающего с одним и тем же редактированием URI: выясняется, что спецификация Джерси не позволяет одному @Path иметь несколько ресурсов, поэтому ситуация не должна это произойдет, если обработано правильно (то есть найти правильный ресурс). Тем не менее, я не считаю это удовлетворительным решением.

Более элегантный способ решения этой проблемы заключается в том, чтобы каким-либо образом связать NotFoundExceptionMapper_ThatReturnsResponseTypeA непосредственно с ClassA, а другой NotFoundExceptionMapper_ThatReturnsResponseTypeB - с ClassB. Я не нашел никакого способа сделать это, хотя.

Есть ли способ?

0 ответов

Другие вопросы по тегам