David Obber
David Obber

Reputation: 131

Different Jersey 2 response depending on media type (JSON/XML)

In a RESTful Glassfish 4 application (JERSEY 2.22.2, MOXY as JSON Provider), we have a resource method that is able to produce both JSON and XML outputs.

The method response passes through a MessageBodyWriter, but it's used to build an Object Graph only in certain cases. In these cases, independently from the requested media type from the client, the graph is applied correctly.

On the other hand, when the isWriteable() method of our MessageBodyWirter returns false, therefore passing on to the next writer in the writers list of the MessageBodyFactory, the behavior is different between a JSON media type request and an XML media type request (i.e. Accept: application/json and Accept: application/xml respectively in the request headers).

In the first case, the FilteringMoxyJsonProvider is selected as response writer, because the EntityFilteringFeature is registered. The response is written based on the entity filtering annotations.

Though when the client asks for an XML response, another MessageBodyWriter (org.glassfish.jersey.jaxb.internal.XmlRootElementJaxbProvider) is selected. This is due to the ordering of the WriterModels in the MessageBodyFactory in which the FilteringMoxyJsonProvider is positioned after XmlRootElementJaxbProvider.

In this situation the XML response is written without having any filters applied to it.

We tried to look for a way to change the writers order, also tried to access to the EntityFieldProcessor class, without luck.

Is it possible to have both scenarios (i.e. JSON and XML response requests) work in the same way? Is it possible to exclude some writers from being registered or to change their order in the MessageBodyFactory?

Any help will be appreciated.

    //Configuration 
    public class ApplicationConfigVersione1 extends ResourceConfig { 
    ....

    register(EntityFilteringFeature.class); 
    register(MyCustomWriter.class);


    ------------------------

    @Produces({"application/json", "application/xml"})
    public class MyCustomWriter implements MessageBodyWriter<MyCustomObject> {
    ....


    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
                Annotation[] annotations, MediaType mediaType) {
        if (mustUseCustomWriter()) {
                return true;
            } else {
          return false;
        //In this case, with request header accept=application/xml, the xml response is not filtered.
        }
    }



    @Override
    public void writeTo(MyCustomObject customObject, Class<?> type, Type genericType, Annotation[] annotations, 
    MediaType mediaType,
        MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
            throws IOException, WebApplicationException {

            objectGraph = buildObjectGraph();

            marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, objectGraph);
            marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType.toString());

            //**** objectGraph applies to XML and JSON media types
            marshaller.marshall(object, entityStream);

Upvotes: 1

Views: 479

Answers (1)

Nigel Whitaker
Nigel Whitaker

Reputation: 21

I have also tried to use Jersey's Entity Filtering mechanism with resources producing both application/json and application/xml responses and see different result information according to the repsonse type.

I suspect this closed/wont-fix github issue for the moxy component is the cause of the behaviour we are seeing with filtering: https://github.com/jersey/jersey/issues/3036

Upvotes: 1

Related Questions