Пользовательская обработка ошибок Джерси, как поймать ответ на стороне клиента?


Я пробую некоторые пользовательские обработки ошибок на моем веб-сервисе. В моем веб-сервисе я создал пользовательский класс исключений, расширяющий WebApplicationException, как описано в JAX-RS / Jersey как настроить обработку ошибок?:

public class InternalServerErrorException extends WebApplicationException {
    public InternalServerErrorException(String message) {
        super(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
            .header("errorMessage", message).type(MediaType.TEXT_PLAIN).build());
        System.out.println(message);
    }
}

Для тестирования у меня есть простой страновой сервис, который дает список стран. Я убедился, что ошибка произойдет, чтобы проверить бросание InternalServerErrorException:

@GET
@Override
@Path("countries")
@Produces({"application/xml"})
public List<Country> findAll() {
    try {
        int i = Integer.parseInt("moo"); //<-- generate error
        List<Country> countries = super.findAll();
        return countries;
    } catch (Exception ex) {
        throw new InternalServerErrorException("I want this message to show at client side");
    }
}

У моего клиента есть соотечественник со следующим: метод:

public List<Country> findAll() throws ClientErrorException {
    WebTarget resource = webTarget;
    resource = resource.path("countries");
    return resource.request(javax.ws.rs.core.MediaType.APPLICATION_XML).get(new GenericType<List<Country>>(){});
}

И в моем контроллере я использую его так:

    try {
        CountryClientSSL cc = new CountryClientSSL();
        cc.setUsernamePassword(USERNAME, PASSWORD);
        ObservableList<Country> olCountries = FXCollections.observableArrayList(cc.findAll());

        tblCountries.setItems(olCountries);
        tcCountry.setSortType(SortType.ASCENDING);
        tblCountries.getSortOrder().add(tcCountry);
    } catch (Exception ex) {
        System.out.println(ex.getMessage());
    }
Поэтому каждый раз, когда я использую метод findAll() в моем клиенте, я вижу следующую информацию в моих выходных окнах: Info: I want this message to show at client side на стороне сервера и HTTP 500 Internal Server Error на стороне клиента.

Есть ли способ получить errorMessage на стороне клиента (в блоке catch) без использования Response в качестве возвращаемого типа?

Я пытаюсь добиться следующего: когда на стороне клиента возникает ошибка, пользователи могут отправить отладку сообщите моему экземпляру JIRA, который содержит много информации, такой как stacktrace клиента, дополнительную информацию о системе, которая вошла в систему... Было бы неплохо прикрепить туда же stacktrace сервера. Или есть лучшие способы достичь этого?

2 2

2 ответа:

Есть ли способ получить errorMessage на стороне клиента (в блоке catch) без использования Response в качестве возвращаемого типа?

Вы можете использовать response.readEntity(new GenericType<List<Country>>(){}). Таким образом, вы все еще будете иметь доступ к Response. Хотя в этом случае не будет никакого stacktrace. Существует только исключение на клиенте, когда вы пытаетесь использовать get(ParsedType). Причина в том, что с get(ParsedType) нет другого способа обработки состояния ошибки. Но с помощью Response разработчик должен выполнить проверку состояния. Так метод мог бы выглядеть более похожим на

public List<Country> findAll() throws ClientErrorException {
    WebTarget resource = webTarget;
    resource = resource.path("countries");
    Response response =  resource.request(javax.ws.rs.core.MediaType.APPLICATION_XML).get();
    if (response.getStatus() != 200) {
        System.out.println(response.getHeaderString("errorResponse"));
        return null;
    } else {
        return response.readEntity(new GenericType<List<Country>>(){});
    }
}

Хотя вместо заголовка я бы просто отправил сообщение в качестве тела ответа. Это всего лишь я

super(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
        .entity( message).type(MediaType.TEXT_PLAIN).build());

Сторона клиента

if (response.getStatus() != 200) {
    System.out.println(response.readEntity(String.class));
    return null;
}

Я не верю, что вы можете возвращать пользовательский контент (т. е. errorMessage) в любом типе ответа, кроме HTTP 200 (Response.ok().build).

Однако вы можете создавать исключения в коде сервера, а затем перехватывать их и преобразовывать в допустимые ответы с помощью ExceptionMapper. Смотрите этот вопрос для получения более подробной информации.