Джерси - согласование контента для обработки ошибок

Я хотел бы разрешить клиентам выбирать формат ответа об ошибке, используя согласование содержимого 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 );
        }
        // ...
    }
}

Надеюсь, это было как-то полезно:)

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