Джерси - согласование контента для обработки ошибок
Я хотел бы разрешить клиентам выбирать формат ответа об ошибке, используя согласование содержимого HTTP.
Например, учитывая конечную точку
@Produces("application/json")
class MyService {
@GET
public String getSomething() {
if (currentTimeMilis() % 2 == 0) throw new MyException();
return "{ hello:\"world\" }";
}
и картограф исключения:
class MyExceptionMapper implements ExceptionMapper<MyException> {
@Override
public Response toResponse(MyException ex) {
return status(BAD_REQUEST)
.entity(new MyDto(randomUUID(), ex.getMessage()))
.build();
}
}
и имея двух авторов тела, MyBodyWriter
и стандарт JacksonJsonProvider
,
Я хотел бы вызвать одного из авторов в зависимости от содержимого заголовка Accept, например
Accept: application/json
-> вызываетJacksonJsonProvider
Accept: application/vnd-mycompany-error, application/json
-> вызываетMyBodyWriter
Я пробовал разные подходы, но все они терпят неудачу, потому что совпали HttpRule
подразумевает application/json
Тип содержимого.
Единственный обходной путь, который я нашел, - это вставить заголовки запроса в ExceptionMapper
и явно указывать тип содержимого - но мне это не нравится.
1 ответ
Может быть, просто обходной путь, но...
Вы можете попробовать использовать ContainerResponseFilter
получить все аккредитованные MediaTypes из ContainerRequestContext
и ограничить ответ MediaType путем сброса объекта с ContainerResponseContext.setEntity
,
Там могут быть лучшие решения!
Используется майка 2.12:
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.List;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
import path.to.MyException;
@Provider
public class EntityResponseFilter implements ContainerResponseFilter {
@Override
public void filter( ContainerRequestContext reqc , ContainerResponseContext resc ) throws IOException {
List<MediaType> mediaTypes = reqc.getAcceptableMediaTypes();
MediaType mediaType = new MediaType("application", "vnd-mycompany-error");
if( mediaTypes.contains( mediaType) && resc.getEntity() instanceof MyDao /* or MyDto, or null, or whatever */) {
resc.setEntity( resc.getEntity(), new Annotation[0], mediaType );
}
// ...
}
}
Надеюсь, это было как-то полезно:)