jax-ws : type de contenu Media Exception non pris en charge côté serveur

mon client soap fait une demande réussie et obtient 200 OK du serveur soap. Cependant, l'application génère une erreur en raison d'un en-tête de type de contenu manquant. J'ai essayé d'ajouter un en-tête de type de contenu dans le gestionnaire, mais cela n'est même pas invoqué (en utilisant le débogueur, je peux voir que la méthode n'est jamais utilisée pour les messages entrants, mais pour les messages sortants, elle est activée)

Voici le code du gestionnaire :

public class ClientHandler implements SOAPHandler<SOAPMessageContext> {
public boolean handleMessage(SOAPMessageContext context) {
if ((Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {
System.out.println(" here: in outbound call");
}
if (!(Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {
Map<String, List<String>> headers = (Map<String, List<String>>)context.get(MessageContext.HTTP_RESPONSE_HEADERS);
List<String> value = new ArrayList<String>();
value.add("text/xml");
if (headers!= null) {
headers.put("content-type", value);
} else {
Map<String, List<String>> brandNewHeaders = new HashMap<String, List<String>>();
brandNewHeaders.put("content-type", value);
context.put(MessageContext.HTTP_RESPONSE_HEADERS, brandNewHeaders);
}
}
return true;
}

Voici comment j'attache mon gestionnaire

WSGService service = new WSGService();
appPort = service.getWSGHttpPort();
final Binding binding = ((BindingProvider) provisionPort).getBinding();
BindingProvider bp = (BindingProvider)provisionPort;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, provisionurl);
List<Handler> handlerList = new ArrayList<>();
handlerList.add(new ClientHandler());
binding.setHandlerChain(handlerList);

Voici le journal que je reçois pour un appel réussi. REMARQUE Type de contenu vide sur l'en-tête de réponse, qui est à l'origine de cette erreur.

---[HTTP request - https://foobar/url]---
Accept: [text/xml, multipart/related]
Content-Type: [text/xml; charset=utf-8]
SOAPAction: ["/FOOBARWSG"]
User-Agent: [JAX-WS RI 2.2.4-b01]
<?xml version="1.0"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body>**BODY**</S:Body></S:Envelope>--------------------
---[HTTP response - https://foobar/url - 200]---
null: [HTTP/1.0 200 OK]
Access-Control-Allow-Headers: [Content-Type, Accept, Accept-Encoding, Content-Encoding, X-Client-UID, Authorization, X-Associated-Id]
Access-Control-Allow-Methods: [GET, POST, PUT, DELETE]
Access-Control-Allow-Origin: [*]
Access-Control-Expose-Headers: [WWW-Authenticate]
Connection: [close]
Content-Length: [2915]
content-type: []
Date: [Tue, 31 Jan 2017 06:24:05 GMT]
Server: [JBOSS Application Server]
X-WsgSource: [DUMMY,15,2017-01-31 06:24:05]
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns></SOAP-ENV:Body></SOAP-ENV:Envelope>--------------------
22:24:07,605 ERROR ErrorPageFilter:180 - Forwarding to error page from request [/dummy/customerType/null] due to exception [Unsupported Content-Type: Supported ones are: [text/xml]]
com.sun.xml.internal.ws.server.UnsupportedMediaException: Unsupported Content-Type: Supported ones are: [text/xml]

MODIFIER :

avec plus de débogage, j'ai pu changer manuellement le type de contenu pour inclure "text/xml" en réponse via la console de débogage intellij et tout s'est comporté comme prévu

J'ai changé contentType ci-dessous en "text/xml" qui avait une valeur vide dans le HttpTrasportPipe.class

this.checkStatusCode(responseStream, con);
Packet reply = request.createClientResponse((Message)null);
reply.wasTransportSecure = con.isSecure();
if(responseStream!= null) {
String contentType = con.getContentType();
if(contentType!= null && contentType.contains("text/html") && this.binding instanceof SOAPBinding) {
throw new ClientTransportException(ClientMessages.localizableHTTP_STATUS_CODE(Integer.valueOf(con.statusCode), con.statusMessage));
}
this.codec.decode(responseStream, contentType, reply);
}


Solution du problème

Vous pouvez ajouter un personnalisé com.sun.xml.internal.ws.api.pipe.TransportTubeFactorypour accéder à l' Codec.decodeappel dans HttpTransportPipe; voir la dernière partie de ma réponse sur cette question : UnsupportedMediaException -> comment obtenez-vous la réponse réelle ?

Dans cette question, nous étions plus intéressés par le corps de la réponse "défectueuse", mais vous pouvez utiliser le wrapper Codec tout aussi facilement pour annuler leContent-Type :

Extrait de mon CodecWrapper :

 @Override
public void decode(InputStream in, String contentType, Packet response) throws IOException {
// TODO: here you can access / change any of the parameters before sending it to the actual SOAP Codec
wrapped.decode(in, contentType, response);
}

Quelques remarques:


  • J'ai écrit la réponse référencée pour jaxws-rt, et selon votre message d'erreur, vous utilisez la version interne de JRE. Cela devrait fonctionner de la même manière. La seule différence réside dans les noms de packages.

  • vous avez de la chance que le type de contenu soit nul, sinon vous obtiendrez un ClientTransportExceptionqui est beaucoup plus difficile à contourner (sans copier beaucoup de code de HttpTransportPipe)

  • si vous pouvez trouver un moyen plus simple de proxy votre trafic HTTP et de réécrire le Content-Type de cette façon, ce serait plus propre. Voir par exemple la réponse acceptée ici: SOAP unsupported media exception text/plain Ceux pris en charge sont: [text/xml] sur la façon d'utiliser Apache httpd comme proxy inverse

Commentaires

Posts les plus consultés de ce blog

Erreur Symfony : "Une exception a été levée lors du rendu d'un modèle"

Détecter les appuis sur les touches fléchées en JavaScript

Une chaîne vide donne "Des erreurs ont été détectées dans les arguments de la ligne de commande, veuillez vous assurer que tous les arguments sont correctement définis"