Lesen Sie den Antworttext im JAX-RS-Client aus einer Post-Anfrage

75

Da wir eine Art Proxy zwischen einer mobilen App und einem Webdienst haben, sind wir verwirrt über die Antwort bei der Ausgabe einer Post-Anfrage. Wir erhalten eine Antwort mit dem Status 200: OK. Der JSON-Antworttext kann jedoch nicht gefunden / extrahiert werden.

    Client client = ClientBuilder.newClient();
    WebTarget webTarget = client.target(WEBSERVICE_BASE_LOCATION + "mobileDevices?operatorCode=KPNSCP");
    String jsonString = "{\"osVersion\":\"4.1\",\"apiLevel\":16,\"devicePlatform\":\"ANDROID\"}";
    Builder builder = webTarget.request();
    Response response = builder.post(Entity.json(jsonString));

Wir verwenden JAX-RS. Kann jemand bitte einige Hinweise geben, um den JSON-Body ( String) aus der Serverantwort zu extrahieren ?

user2657714
quelle
3
Wir mussten es ändern in: String output = response.readEntity(String.class);Damit es funktioniert. Danke vielmals!
user2657714

Antworten:

166

Versuche dies:

String output = response.getEntity(String.class);

BEARBEITEN

Vielen Dank an @Martin Spamer , dass es nur für Jersey 1.x Gläser funktioniert. Für Jersey 2.x verwenden

String output = response.readEntity(String.class);
Juned Ahsan
quelle
45
Dies funktioniert nur mit Jax 1.x ab Jersey: 2.x, das das OP verwendet (Wir können dies an seiner Verwendung von ClientBuilder.newClient () erkennen;). Die Antwort istresponse.readEntity(String.class);
Martin Spamer
3
Dies funktioniert nicht für jaxrs-ri-2.16, hier erhalten Sie org.glassfish.jersey.client.HttpUrlConnector$2@1255b1d1als Ausgabe.
col.panic
danke, ich habe mich lange damit beschäftigt, als ich getEntity () zum Lesen des Antwortnachrichtentexts verwendete. getEntity () funktioniert nur mit Jersey 1.x und Jersey 2.0 unterstützt response.readEntity (), um den Text der Antwortnachricht abzurufen.
spectre007
Beachten Sie, dass Sie com.owlike.genson.stream.JsonStreamException: Readen value can not be converted to Stringden Antwortstrom manuell lesen müssen , wenn Sie eine erhalten , um die JSON-Zeichenfolge abzurufen. Das ist mir mit Jersey 1.19 passiert.
dvlcube
17

Ich habe gerade eine Lösung für jaxrs-ri-2.16 gefunden - einfach verwenden

String output = response.readEntity(String.class)

Dies liefert den Inhalt wie erwartet.

col.panic
quelle
14
Jersey-Entwickler machen mich verrückt. Die Benennung jeder Versionsmethode und / oder der gesamte Workflow ändern sich drastisch. Es ist wie ein Miner-Spiel. Finde alle Minen von Grund auf neu.
Alfishe
2
Magst du Agility nicht? :)
Launisch
8
@Whimusical Ich denke, er mag Abwärtskompatibilität :)
Hristo Vrigazov
13

Für meinen Anwendungsfall funktionierte keine der vorherigen Antworten, da ich einen serverseitigen Komponententest schrieb, der aufgrund der folgenden Fehlermeldung fehlschlug, wie in der Frage " Client-Antwortobjekt für Glassfish Jersey kann nicht verspottet werden" beschrieben :

java.lang.IllegalStateException: Method not supported on an outbound message.
at org.glassfish.jersey.message.internal.OutboundJaxrsResponse.readEntity(OutboundJaxrsResponse.java:145)
at ...

Diese Ausnahme trat in der folgenden Codezeile auf:

String actJsonBody = actResponse.readEntity(String.class);

Die Lösung bestand darin, die Problemcodezeile in Folgendes umzuwandeln:

String actJsonBody = (String) actResponse.getEntity();
entpnerd
quelle
3
getEntity liest keinen Backing InputStream automatisch, seien Sie also vorsichtig.
Ben
4

Ich hatte auch das gleiche Problem, als ich versuchte, einen Unit-Test-Aufrufcode auszuführen, der verwendet readEntity. Kann nicht getEntityim Produktionscode verwendet werden, da dies nur ein ByteInputStreamund nicht den Inhalt des Körpers zurückgibt und ich auf keinen Fall Produktionscode hinzufügen kann, der nur in Komponententests getroffen wird.

Meine Lösung bestand darin, eine Antwort zu erstellen und dann einen Mockito-Spion zu verwenden, um die readEntityMethode zu verspotten :

Response error = Response.serverError().build();
Response mockResponse = spy(error);
doReturn("{jsonbody}").when(mockResponse).readEntity(String.class);

Beachten Sie, dass Sie die when(mockResponse.readEntity(String.class)Option nicht verwenden können, da dies dasselbe auslöst IllegalStateException.

Hoffe das hilft!

Cheefachi
quelle
1
Vielen Dank! Sie sind wahrscheinlich die erste Person, die die Frage des OP tatsächlich versteht. Für alle anderen Ersthelfer da draußen: Es interessiert niemanden, wie schlau Sie sind. Sie wollen ihr Problem beheben. Sie interessieren sich nicht dafür, warum Sie mit Jersey in einem Unit-Test nicht readResponse aufrufen können.
John Calcote
0

Gemäß der Dokumentation gibt die Methode getEntity in Jax rs 2.0 einen InputStream zurück. Wenn Sie in InputStream in String mit JSON-Format konvertieren müssen, müssen Sie die beiden Formate umwandeln. In meinem Fall habe ich beispielsweise die nächste Methode implementiert:

    private String processResponse(Response response) {
    if (response.getEntity() != null) {
        try {
            InputStream salida = (InputStream) response.getEntity();
            StringWriter writer = new StringWriter();
            IOUtils.copy(salida, writer, "UTF-8");
            return writer.toString();
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }
    return null;
}

warum ich diese Methode implementiert habe. Da in verschiedenen Blogs gelesen wird, dass viele Entwickler das gleiche Problem mit der Version in jaxrs haben, verwenden sie die nächsten Methoden

String output = response.readEntity(String.class)

und

String output = response.getEntity(String.class)

Der erste funktioniert mit dem Trikot-Client aus der Bibliothek com.sun.jersey und der zweite mit dem Trikot-Client aus org.glassfish.jersey.core.

Dies ist der Fehler, der mir angezeigt wurde: org.glassfish.jersey.client.internal.HttpUrlConnector $ 2 kann nicht in java.lang.String umgewandelt werden

Ich benutze die folgende Maven-Abhängigkeit:

<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.28</version>

Was ich nicht weiß, ist, warum die readEntity-Methode nicht funktioniert. Ich hoffe, Sie können die Lösung verwenden.

Carlos Cepeda

MonkeySoft Kolumbien
quelle
0

Als ich die Überarbeitung des Codes erkannte, fand ich die Ursache dafür, dass die Lesemethode bei mir nicht funktionierte. Das Problem war, dass eine der Abhängigkeiten, die mein Projekt verwendete, Trikot 1.x. Aktualisieren Sie die Version, passen Sie den Client an und es funktioniert.

Ich benutze die folgende Maven-Abhängigkeit:

<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.28</version>

Grüße

Carlos Cepeda

MonkeySoft Kolumbien
quelle