Джерси не подчиняется правилам типа ответного носителя от @Produces

Я могу неправильно интерпретировать спецификацию Джерси для типа носителя ответа, когда метод может создать один из нескольких. Согласно https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e1785, я думаю, что когда два типа мультимедиа, перечисленные в аннотации @Produces(..), соответствуют входящему заголовку Accept, Джерси будет учитывать любые веса, связанные с этими типами в аннотации, или выберет первый, если веса соответствуют не определить победителя.

В приведенном ниже коде показано, что на практике это не так. В последних двух случаях я ожидаю ответа JSON, когда запрос неоднозначен, но вместо этого получаю XML. Правильно ли я понимаю документацию? Или это, возможно, дефект Джерси?

Что я пробовал:

  1. Удалите аннотацию @XmlRootElement из модели. Затем два последних случая проходят, но второй случай расходится, потому что нет подходящего автора.
  2. Возвратите Object из метода ресурса. Результатом является отсутствие изменений в статусе прохождения/непрохождения дел.
  3. Удалите веса из аннотации @Produces(..) класса ресурсов (тип мультимедиа JSON по-прежнему указан первым). Результатом является отсутствие изменений в статусе прохождения/непрохождения дел.

Этот пример создан с использованием Джерси 2.10 и Java 1.8_05 в Ubuntu 14.04.

package demo;

import java.net.URI;
import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlRootElement;

import org.glassfish.jersey.jdkhttp.JdkHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

import com.sun.net.httpserver.HttpServer;

public class DemonstrateAmbiguousMediaType {

    private static final String BASE_URI = "http://localhost:8092/";

    public static void main(final String[] args) {

        final HttpServer server = startServer();

        try {

            /*
             * These cases work fine.
             */
            check("application/json", "application/json");
            check("application/xml", "application/xml");

            /*
             * These cases should pass according to Jersey
             * documentation for @Produces
             * https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e1785
             * but they do not.
             */
            check("application/json", "application/*");
            check("application/json", "*/*");

        } finally {
            server.stop(0);
        }

    }

    private static void check(final String expected, final String... acceptTypes) {

        final MediaType atype = fetchAs(acceptTypes).getMediaType();
        final String actual = atype.getType() + "/" + atype.getSubtype();

        System.out.println(Arrays.asList(acceptTypes) + ":"
            + (expected.equals(actual) ? "pass" : "fail"));

    }

    private static Response fetchAs(final String[] acceptable) {

        return ClientBuilder.newClient()
                            .target(BASE_URI)
                            .path("model")
                            .request()
                            .accept(acceptable)
                            .get();

    }

    private static HttpServer startServer() {
        final ResourceConfig config = new ResourceConfig(Resource.class);
        final HttpServer rval = JdkHttpServerFactory.createHttpServer(
                URI.create(BASE_URI), config, false);
        rval.setExecutor(Executors.newCachedThreadPool(new ThreadFactory() {

            @Override
            public Thread newThread(Runnable r) {
                final Thread rval = new Thread(r);
                rval.setDaemon(true);
                return rval;
            }
        }));
        rval.start();
        return rval;
    }

    @XmlRootElement
    public static class Model {

        public int a = 10;
        public String b = "Bbb";

    }

    @Path("/model")
    @Produces({ "application/json; q=0.9", "application/xml; q=0.5" })
    public static class Resource {

        @GET
        public Model getModel() {
            return new Model();
        }

    }

}

person aztecrex    schedule 30.06.2014    source источник
comment
Теперь я совершенно убежден, что это проблема с кодом или документацией Джерси, поэтому отправил отчет о проблеме. там.   -  person aztecrex    schedule 01.07.2014


Ответы (1)


Я неправильно прочитал спецификацию. В аннотациях @Produces(..) имя параметра качества qs, а не q. При правильном указании параметров качества все вышеперечисленные случаи проходят.

Однако при удалении параметров качества окончательные случаи не проходят. Согласно той же документации Джерси, следует выбрать первый из перечисленных, но это не так.

person aztecrex    schedule 03.07.2014