I'd like to allow clients to select an error response format using HTTP content negotiation.
E.g. given an endpoint
@Produces("application/json")
class MyService {
@GET
public String getSomething() {
if (currentTimeMilis() % 2 == 0) throw new MyException();
return "{ hello:\"world\" }";
}
and exception mapper:
class MyExceptionMapper implements ExceptionMapper<MyException> {
@Override
public Response toResponse(MyException ex) {
return status(BAD_REQUEST)
.entity(new MyDto(randomUUID(), ex.getMessage()))
.build();
}
}
and having two body writers, MyBodyWriter
and standard JacksonJsonProvider
.
I'd like to invoke one of the writers depending on the contents of Accept header, e.g.
Accept: application/json
-> invokes JacksonJsonProvider
Accept: application/vnd-mycompany-error, application/json
-> invokes MyBodyWriter
I had tried different approaches but all of them fail because the matched HttpRule
implies an application/json
content type.
The only workaround I've found is to inject the request headers into ExceptionMapper
and set the content type explicitly there -- but I don't like it.
Maybe just a workaround, but ...
You could try to use a ContainerResponseFilter
, get all accpeted MediaTypes from the ContainerRequestContext
and limit the response MediaType by reset the entity with ContainerResponseContext.setEntity
.
There might be better solutions!
Used jersey 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 );
}
// ...
}
}
Hope this was helpfull somehow:)
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments