È possibile che si stia interpretando erroneamente la specifica di Jersey per il tipo di supporto di una risposta quando un metodo può produrre uno di diversi. Secondo lo https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e1785, penso che quando due tipi di media elencati in un'annotazione @Produces(..)
corrispondano all'intestazione-in arrivo, Jersey onorerà tutti i pesi associati a tali tipi nell'annotazione o sceglierà la prima se i pesi non decideranno un vincitore.Jersey che non rispetta le regole del tipo di media di risposta da @Produces
Il codice seguente mostra come questo non sia il comportamento nella pratica. Negli ultimi due casi, mi aspetto una risposta JSON quando la richiesta è ambigua, ma ottengo invece XML. La mia comprensione della documentazione è errata? O forse questo è un difetto in Jersey?
cose che ho provato:
- Rimuovere il
@XmlRootElement
annotazioni dal modello. Gli ultimi passano due casi ma il secondo caso diverge perché non esiste uno scrittore adatto. - Restituisce
Object
dalla risorsa metodo. Il risultato non è un cambiamento nello stato pass/fail dei casi. - Rimuovere i pesi dall'annotazione
@Produces(..)
della classe di risorsa (il tipo di supporto JSON è ancora elencato per primo). Il risultato non modifica lo stato di pass/fail dei casi.
Questo esempio viene creato utilizzando Jersey 2.10 e Java 1.8_05 su 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();
}
}
}
Sono abbastanza convinto ora che si tratta di un problema con il codice o la documentazione di Jersey, quindi [archiviato un rapporto sul problema] (https://java.net/jira/browse/JERSEY-2564). – aztecrex