2014-06-30 15 views
5

Mogę błędnie interpretować specyfikację Jersey dla typu nośnika odpowiedzi, gdy metoda może wytworzyć jedną z kilku. Według https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e1785, uważam, że gdy dwa typy mediów wymienione w adnotacji @Produces(..) pasują do nadchodzącego nagłówka Accept, Jersey będzie honorować wszelkie wagi powiązane z tymi typami w adnotacji lub wybierze pierwszą wagę, jeśli wagi nie decydują o zwycięzcy.Jersey nie przestrzega reguł typu nośnika odpowiedzi z @Produces

Poniższy kod pokazuje, jak to nie jest zachowanie w praktyce. W dwóch ostatnich przypadkach oczekuję odpowiedzi JSON, gdy żądanie jest niejednoznaczne, ale zamiast tego otrzymuję XML. Czy moje zrozumienie dokumentacji jest nieprawidłowe? A może to wada na Jersey?

Czego próbowałem:

  1. Zdjąć @XmlRootElement adnotacji z modelu. Ostatnie dwie sprawy przechodzą następnie, ale drugi przypadek rozbiega się, ponieważ nie ma odpowiedniego pisarza.
  2. Powrót Object z metody zasobów . Wynik nie powoduje zmiany stanu przekazania/niepowodzenia spraw.
  3. Usuń ciężary z adnotacji @Produces(..) klasy zasobów (typ nośnika JSON jest nadal wyświetlany jako pierwszy). Wynik nie powoduje zmiany statusu przekazania/niepowodzenia spraw.

Ten przykład jest zbudowany przy użyciu oprogramowania Jersey 2.10 i Java 1.8_05 w systemie 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(); 
     } 

    } 

} 
+0

Jestem przekonany, że jest to problem związany z kodem Jersey lub dokumentacją, dlatego [złożył raport o problemie] (https://java.net/jira/browse/JERSEY-2564). – aztecrex

Odpowiedz

2

Źle odczytałem specyfikację. W adnotacjach @Produces(..) nazwa parametru jakości to qs, a nie q. Gdy parametry jakości są określone prawidłowo, wszystkie powyższe przypadki mijają.

Po usunięciu parametrów jakości ostateczne przypadki nie są jednak przekazywane. Zgodnie z tą samą dokumentacją z Jersey należy wybrać pierwszą listę, ale tak nie jest.