JAX-RS (Джерси) пользовательское исключение с XML или JSON
У меня есть служба REST, построенная с использованием Джерси.
Я хочу иметь возможность установить MIME моих собственных создателей исключений в зависимости от MIME, который был отправлен на сервер. application/json
возвращается при получении json и application/xml
при получении xml.
Теперь я жестко код application/json
, но это делает XML-клиенты оставленными в темноте.
public class MyCustomException extends WebApplicationException {
public MyCustomException(Status status, String message, String reason, int errorCode) {
super(Response.status(status).
entity(new ErrorResponseConverter(message, reason, errorCode)).
type("application/json").build());
}
}
В каком контексте я могу получить доступ к текущим запросам Content-Type
?
Спасибо!
Обновление на основе ответа
Для всех, кто интересуется полным решением:
public class MyCustomException extends RuntimeException {
private String reason;
private Status status;
private int errorCode;
public MyCustomException(String message, String reason, Status status, int errorCode) {
super(message);
this.reason = reason;
this.status = status;
this.errorCode = errorCode;
}
//Getters and setters
}
Вместе с ExceptionMapper
@Provider
public class MyCustomExceptionMapper implements ExceptionMapper<MyCustomException> {
@Context
private HttpHeaders headers;
public Response toResponse(MyCustomException e) {
return Response.status(e.getStatus()).
entity(new ErrorResponseConverter(e.getMessage(), e.getReason(), e.getErrorCode())).
type(headers.getMediaType()).
build();
}
}
Где ErrorResponseConverter - это пользовательский JAXB POJO
Ответы
Ответ 1
Вы можете попробовать добавить поле/свойство @javax.ws.rs.core.Context javax.ws.rs.core.HttpHeaders в свой корневой класс ресурсов, параметр метода ресурса или пользовательский javax.ws.rs. ext.ExceptionMapper и вызов HttpHeaders.getMediaType().
Ответ 2
headers.getMediaType() отвечает типом носителя Entity, а не заголовком Accept. Соответствующий способ преобразования исключения - это заголовок Accept, чтобы ваш клиент получал ответ в запрошенном формате. Учитывая вышеупомянутое решение, если ваш запрос выглядит следующим образом (обратите внимание на заголовок JSON accept, но XML Entity), вы получите XML обратно.
POST http://localhost:8080/service/giftcard/invoice?draft=true HTTP/1.1
Accept: application/json
Authorization: Basic dXNlcjp1c2Vy
Content-Type: application/xml
User-Agent: Jakarta Commons-HttpClient/3.1
Host: localhost:8080
Proxy-Connection: Keep-Alive
Content-Length: 502
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><sample><node1></node1></sample>
Правильная реализация снова используется для использования заголовка Accept:
public Response toResponse(final CustomException e) {
LOGGER.debug("Mapping CustomException with status + \"" + e.getStatus() + "\" and message: \"" + e.getMessage()
+ "\"");
ResponseBuilder rb = Response.status(e.getStatus()).entity(
new ErrorResponseConverter(e.getMessage(), e.getReason(), e.getErrorCode()));
List<MediaType> accepts = headers.getAcceptableMediaTypes();
if (accepts!=null && accepts.size() > 0) {
//just pick the first one
MediaType m = accepts.get(0);
LOGGER.debug("Setting response type to " + m);
rb = rb.type(m);
}
else {
//if not specified, use the entity type
rb = rb.type(headers.getMediaType()); // set the response type to the entity type.
}
return rb.build();
}