Nicht mehr überschreiben einen Antwort-header mit einem Jersey-client-filter
Ich versuche, mit der Jersey-client-API zu konsumieren ein Drittel-party-REST-Dienst. Ich Plane, verwenden Sie das automatische POJO deserialisation gehen von JSON-Antworten zu Java-Objekten.
Leider, die Dritte party-service liefert die Antworten, die mit dem Inhaltstyp "text/javascript"
. Meine Jersey-client, nicht zu verstehen, dies sollte berücksichtigt werden als JSON-Objekt und nicht zu deserialise das Objekt.
Schrieb ich ein einfaches Jersey-server-Anwendung, um zu überprüfen, dass durch eine änderung des content type von "text/javascript"
zu "application/json"
dass die deserialisation funktioniert.
Bewaffnet mit diesen Informationen, ich über die Verwendung einer Jersey-client-filter zum ändern der Antwort-Header. Der code stammt aus einer Bemerkung des Autors der diese Frage. In der Tat, die Frage wird sein, genau die gleiche wie meine - aber die Beantworter mis-beantwortet die Frage und zeigt, wie Sie die Anfrage Header (anstatt der Antwort - Header). Der ursprüngliche Autor war in der Lage zu verwenden, die Antwort auf seine Lösung, aber, scheint es, dass seine angegebenen Lösung nicht funktioniert.
Den filter-code:
client.addFilter(new ClientFilter() {
@Override public ClientResponse handle(ClientRequest cr)
throws ClientHandlerException {
ClientResponse response = getNext().handle(cr);
response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
return response;
}
});
Ausgeführt, wenn jedoch ein UnsupportedOperationException
ausgelöst:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.clear(Collections.java:1035)
at com.sun.jersey.core.util.StringKeyIgnoreCaseMultivaluedMap.putSingle(StringKeyIgnoreCaseMultivaluedMap.java:78)
at com.sun.jersey.core.util.StringKeyIgnoreCaseMultivaluedMap.putSingle(StringKeyIgnoreCaseMultivaluedMap.java:56)
at App$1.handle(App.java:49)
at com.sun.jersey.api.client.Client.handle(Client.java:648)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680)
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:507)
at App.main(App.java:63)
Den zurückgegebenen Header angezeigt werden, eingewickelt in eine unmodifiable collection.
Dann versuchte ich zu kopieren Sie alle überschriften auf eine neue Kollektion, aber es gibt keine Möglichkeit, dass ich sehen kann, um set eine Karte der Header in die Antwort.
Endlich, dachte ich, vielleicht kann ich eine neue erstellen ClientResponse
mit meinem geänderten Header. Allerdings wird der Konstruktor ClientResponse
hat diese Signatur:
public ClientResponse(int status,
InBoundHeaders headers,
InputStream entity,
MessageBodyWorkers workers)
Es ist trivial zu kopieren status
, headers
und entity
Variablen aus dem original. Aber ich sehe keinen Weg, um einen Verweis auf die workers
Feld.
Wie kann ich einen Jersey-client-filter zum ändern der Antwort-header aus "text/javascript"
zu "application/json"
so, dass mein POJO deserialisation funktionieren???
- Das ist ein gangbarer work-around: Deserialisieren JSON-Objekt mit Jersey. Es löst nicht das Kopf-Problem, aber es erlaubt den POJO deserialisation in nur einem zusätzlichen Schritt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Habe ich nicht eine Antwort auf deine eigentliche Frage, aber ich denke, ich sehe, wie Sie bekommen können, dass die Arbeitnehmer Beispiel, wenn Sie wollen, um zu versuchen, erstellen Sie eine neue Antwort in deinem filter.
Den "Arbeitnehmer" - Objekt, das Sie benötigen, erscheint ein singleton. Wenn Sie können, besorgen Sie sich Ihre com.Sonne.jersey.api.client.Client-Instanz, die Sie abrufen können, die Arbeitnehmer-Objekt. In meinem Fall, die Jersey-client-code ist in einem unit test die Unterklassen JerseyTest. JerseyTest definiert eine Methode "client()" gibt das Client-Objekt. Ich habe folgenden test-code (naja nicht genau aber schließen):
Dann setze ich einen Haltepunkt im Konstruktor von ClientResponse (dies ist die ursprüngliche ClientResponse zurückgegeben Jersey. Ich habe nicht versucht zu Klonen, weil ich nicht brauchen, um für meinen test). Die Arbeiter die an den Konstruktor übergeben wurde die gleiche Instanz. Also, auch wenn Sie nicht bekommen kann den Arbeitnehmer-Objekt aus dem response-Objekt, Sie sollten in der Lage sein, um es an anderer Stelle.
In Jersey 2, registriert eine Implementierung eines ClientResponseFilter mit der ClientConfig zur Manipulation der HTTP-Header der eingehenden Antworten.
Zum Beispiel, dies scheint gut zu funktionieren mit Jersey 2.3.1 für die Manipulation von HTTP-header:
Der Jersey Dokumentation an Filtern und Abscheidern ist nicht perfekt, aber es hat einige links zu den javadocs für die relevanten Klassen: https://jersey.java.net/documentation/latest/filters-and-interceptors.html
Bin ich immer der XML-Antworten von einem service, der antwortet mit XML-Inhalt, aber es fehlt ein "Content-Type: application/xml" - header. Wahrscheinlich ein besserer Ansatz wäre, sich zu registrieren MessageBodyReaders, aber der obige Ansatz funktioniert, während ich Spiele mit sich herum, die service-API.
Guido ' s Antwort bietet die Einsicht erforderlich, um erstellen Sie eine neue
ClientResponse
Objekt und zurück statt. Aus Gründen, ich habe noch nicht die Mühe gemacht, auf die Spur, die Schaffung einer neuenInboundHeaders
hinzufügen alle vorhandenen Header, und ändern dann die einzelnen header in Frage immer noch nicht mit einemUnsupportedOperationException
. Als solche, um re-write-Header, wir iterieren über die original-Header und bauen Sie den richtigen Satz schrittweise:1.14
. Ich weiß nicht, was hat sich geändert in2.0
. Bitte postet eine Antwort wenn Sie herausfinden, oder einen link zu der neuen Frage wenn Sie Fragen, eine neue.In Jersey 2 verwenden, sollten Sie
ClientResponseFilter
. Dann können Sie einfach anrufenresponseContext.getHeaders().putSingle(...)
.Unter Java 8 mit einem lambda:
Wenn Sie wollen, wieder verwenden Sie einen vorhandenen filter Instanz, registrieren Sie es einfach auf die
Client
statt auf dieClientConfig
.Der alte Weg (Jersey-1.9):
Neue Art (Trikot-2.3):
Ist das nicht der beste Lösung, aber es kann Ihnen helfen, zu migrieren.