Настройка обработчика ошибок в JAX-RS/Jersey: коды 400 и 5xx
Быстрый ответ
Настройка обработки исключений в JAX-RS/Jersey предусматривает использование ExceptionMapper<ТипИсключения>
. Вам необходимо переопределить в нём метод toResponse
и сформировать нужный ответ. Вот пример, как обрабатывать общую ошибку:
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception exception) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Произвольное сообщение об ошибке")
.type("application/json")
.build();
}
}
Этот маппер будет перехватывать все исключения типа Exception
и возвращать ответ в формате JSON. Не забывайте о его обязательной регистрации в приложении.
Разбираемся с нюансами обработки ошибок
Применение WebApplicationException
WebApplicationException
можно расширить для генерации исключений с конкретным кодом статуса и сообщением:
public class YourFriendly404Exception extends WebApplicationException {
public YourFriendly404Exception(String message) {
super(Response.status(Response.Status.NOT_FOUND)
.entity(message)
.type(MediaType.TEXT_PLAIN)
.build());
}
}
Если требуется статус 404, будущие сообщения могут использовать этот класс исключения.
Составление специализированных ответов
В сложных случаях целесообразно использовать отдельный класс для ответов на исключения, например ErrorResponse
:
@XmlRootElement
public class ErrorResponse {
private int code;
private String message;
// Getters and setters are omitted for brevity
}
С помощью ErrorResponse
можно возвращать развернутый ответ при использовании ExceptionMapper
:
return Response.status(errorCode)
.entity(new ErrorResponse(errorCode, errorMessage))
.type(MediaType.APPLICATION_JSON)
.build();
Возможности наших Exception Mapper-ов Provider
При регистрации мапперов используйте аннотацию @Provider. Они специализируются на обработке конкретных исключений:
@Provider
public class SpecificExceptionMapper implements ExceptionMapper<SpecificException> {
// Переопределение метода toResponse
}
Контекст и заголовки – отдельная история
Добавляйте информацию в ответы с помощью заголовков:
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.header("X-Custom-Error", "Ошибка произошла!")
.entity(new ErrorResponse())
.type(MediaType.APPLICATION_JSON)
.build();
В заголовках можно передать дополнительные подробности об ошибках.
Искусство разработки стратегий обработки ошибок
Обработка ошибок требует тщательного подхода и внимания к деталям.
Персонализированные стратегии обработки ошибок
Применяйте разные стратегии для разных типов ошибок. Например, для NotFoundException
:
@Provider
public class NotFoundMapper implements ExceptionMapper<NotFoundException> {
@Override
public Response toResponse(NotFoundException exception) {
// Специфический ответ для 404
}
}
И по аналогии обрабатывайте другие типы исключений.
Индивидуализированная обработка исключений
Для более индивидуального подхода используйте ресурсы с @Path
:
@Path("/date/{dateString}")
public class DateResource {
@GET
public Response getDate(@PathParam("dateString") String dateString) {
try {
Date date = new SimpleDateFormat("yyyy-MM-dd").parse(dateString);
// Логика обработки даты
} catch (ParseException e) {
throw new CustomDateFormatException("Формат даты должен быть yyyy-MM-dd!");
}
}
}
Логирование – хроники ошибок
Регистрируйте ошибки в логе, это поможет отслеживать причины их возникновения:
@Provider
public class GlobalExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable exception) {
Logger.log(exception); // Запись исключения в лог
// Общий ответ при ошибке и возможно кружка кофе
}
}
Важно учесть, чтобы в логах не было перебора с информацией.
Визуализация
Представьте схему обработки исключений в виде маршрутной карты:
Jersey: "Ой! Ошибка. Как мне действовать дальше?"
🗺️ Карта обработки исключений:
– 404 Not Found: `->` "Непознанные земли. 🌫️"
– 500 Internal Server Error: `->` "Системный сбой. 🌋"
– 400 Bad Request: `->` "Непонятно, что в запросе. 🌲❓"
– 401 Unauthorized: `->` "Доступ запрещен. 🔑"
Каждой ошибке соответствует свой обработчик:
Навигация: 🗺️[Статус] -> [Обработчик 🔄]
# От хаоса к порядку.
Выбор стратегии обработки ошибок – своеобразное искусство.
Продвинутое управление ошибками – уверенность в завтрашнем дне
- Создавайте мапперы как для общих, так и для специфических исключений.
- Описывайте класс
ErrorResponse
для содержательных ответов. - Расширяйте исключения и создавайте собственные, где это уместно.
- Фиксируйте (логируйте) ошибки, но избегайте разглашения лишней информации.
- Используйте заголовки для уточнения информации об ошибках.
- Выбирайте типы медиа максимально точно.
С точностью анализируем параметры
Чистота API и кода достигается за счет точного парсинга и обработки параметров:
class DateParamConverter implements ParamConverter<Date> {
public Date fromString(String value) {
// Преобразование входного значения в java.util.Date
}
// Превращение строковой даты в объект java.util.Date!
}
Регистрируйте ParamConverterProvider
, чтобы применить его в вашем приложении.
Полезные материалы
- Глава 7. Представления и Ответы — документация Jersey по обработке исключений.
- JSR-000339 Java API для RESTful веб-сервисов 2.0 — спецификация JAX-RS, охватывающая детали обработки ошибок.
- Последние вопросы 'jax-rs+exception' — обсуждение реальных проблем и решений на Stack Overflow.
- ExceptionMapper (Java(TM) EE 7 Specification APIs) — JavaDoc интерфейса ExceptionMapper для обработки ошибок.
- 31.2 Проверка ресурсных данных с Bean Validation — руководство по JAX-RS от Oracle.
- Глава 29. Тестовая среда Jersey — инструкции по тестированию Jersey, включающие проверку исключений.