2013-05-20 2 views
0

J'ai trouvé un certain nombre de threads sur la façon de récupérer la réponse XML d'un client JAX-WS. Dans mon cas, le client est généré à partir du WSDL via le produit JDeveloper d'Oracle et va appeler un point de terminaison de service Document/Literal écrit en .NET. Ce que je veux faire est d'obtenir la réponse XML de l'appel du client appelant, pas de l'intérieur d'un gestionnaire.Comment récupérer le corps de réponse XML d'un client JAX-WS?

Le fil le plus proche que j'ai vu à cette question était: http://www.coderanch.com/t/453537/Web-Services/java/capture-SoapRequest-xml-SoapResponse-xml

Je ne pense pas que je veux générer un appel d'expédition parce que le schéma XML du point de terminaison pour le paquet SOAP est assez complexe, et le proxy automatique rend l'appel trivial. À moins qu'il y ait un autre moyen de peupler le (s) bean (s) généré (s), puis d'invoquer une méthode qui produit simplement le XML et ensuite je lance l'appel?

private void storeSOAPMessageXml(SOAPMessageContext messageContext) { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    SOAPMessage soapMessage = messageContext.getMessage(); 
    try { 
     soapMessage.writeTo(baos); 
     String responseXml = baos.toString(); 
     log.debug("Response: " + responseXml); 
     PaymentGatewayXMLThreadLocal.set(responseXml); 
    } catch (SOAPException e) { 
     log.error("Unable to retrieve SOAP Response message.", e); 
    } catch (IOException e) { 
     log.error("Unable to retrieve SOAP Response message.", e); 
    } 
} 

Ma pensée était de stocker la réponse à l'appel dans un ThreadLocal dans le gestionnaire, puis le lire après l'appel. Est-ce raisonnable? Ainsi, après le gestionnaire fait le code ci-dessus dans le handleMessage et HandleFault, le code appelant client invoque cette méthode:

@Override  
public String getSOAPResponseXML(Object clientstub) { 
    String returnValue = PaymentGatewayXMLThreadLocal.get(); 
    return returnValue; 
} // getSOAPResponseXML 

Il semble qu'il peut y avoir une autre façon après tout. Après avoir lu jax-ws-handlers, j'ai vu que le gestionnaire peut introduire une variable étendue d'application. J'ai changé le gestionnaire de le faire:

private void storeSOAPMessageXml(SOAPMessageContext messageContext) { 
String xml = getSOAPMessageXml(messageContext); 
// YourPayXMLThreadLocal.set(xml); 
// put it into the messageContext as well, but change scope 
// default of handler Scope, and client can't read it from responsecontext! 
messageContext.put(SOAP_RESPONSE_XML, xml); 
messageContext.setScope(SOAP_RESPONSE_XML, MessageContext.Scope.APPLICATION); 
} // storeSOAPMessageXml 

Le client se contente de lire comme ceci:

@Override  
public String getSOAPResponseXML(Object clientstub) { 
    String returnValue = null; 
    // works (assuming a threadlocal is ok) 
    // returnValue = YourPayXMLThreadLocal.get(); 

    BindingProvider bindingProvider = (BindingProvider) clientstub; 
    // Thought this would work, but it doesn't - it returns null.   
    // Map<String, Object> requestContext = bindingProvider.getRequestContext(); 
    // String returnValue = (String) requestContext.get(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML); 

    // this works!! 
    Map<String, Object> responseContext = bindingProvider.getResponseContext(); 
    System.out.println("has key? " + responseContext.containsKey(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML));   
    returnValue = (String) responseContext.get(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML); 
    return returnValue; 
} // getSOAPResponseXML 

Répondre

0

Si vous voulez juste voir la demande, vous pouvez utiliser la propriété système

-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true 

Si vous voulez réellement faire quelque chose à la demande, alors un gestionnaire semble la solution naturelle. Peut-être utiliser le contexte de demande pour transmettre des valeurs au gestionnaire? Sur le client:

((BindingProvider) port).getRequestContext().put("KEY", "VALUE"); 

Dans le gestionnaire:

String value = (String) messageContext.get("KEY"); 
+1

Je ne veux pas seulement le voir, je veux l'enregistrer dans la base de données en fonction d'un identifiant de transaction # connu par le client. Je crée cette entrée de journal AVANT d'envoyer la demande. Le gestionnaire ne connaitrait pas cet ID de transaction (il ne fait pas partie de la demande - c'est mon journal). Je veux connaître la réponse SOAP résultante de l'appel. Dans Apache Axis, j'ai répondu à un autre therad [ici] (http://stackoverflow.com/questions/3842900/is-it-possible-to-access-the-raw-soa-xml-message-in-a-jax -rpc-java-client/16572303 # 16572303). J'ai pensé qu'une nouvelle pile de client WS faciliterait cela. Donc, threadlocal est ok? – user1955401

+0

Le client jax-ws démasque la réponse de savon dans un objet fortement typé à partir de la passerelle de paiement. Malheureusement, nous avons déjà rencontré des situations où les codes d'erreur et les chaînes de caractères non documentés étaient plus longs que prévu/documentés. Alors nos routines pour simplement persister la réponse échoueraient.C'est alors que la colonne de réponse fail-safe (clob) a été ajoutée au journal. Si je suivais votre route, mon gestionnaire devrait être capable de persister cette réponse, comme lorsque j'ai essayé de mettre la paire KEY/VALUE dans le gestionnaire et de lire dans le client qu'elle était nulle. J'utilise MyBatis/Spring aussi si cela aide. – user1955401

0

Malheureusement, la seule façon d'obtenir le XML avant de l'envoyer et sans utiliser un message Handlers est marshall votre auto (voir JAXB). Cela vous donnera une représentation XML des données, mais il pourrait ne pas ressembler exactement au message envoyé au WS. Des différences peuvent survenir dans la façon dont les espaces de noms sont utilisés, mais surtout, vous n'obtiendrez pas toute l'enveloppe SOAP, seulement les données XML pour l'en-tête que vous choisissez de rassembler.

+0

J'ai vu une réponse [ici] (http://stackoverflow.com/questions/12013476/how-can-i-pass-data-back-from-a-soap-handler-to-a-webservice-client?rq = 1) à ce sujet. Je ne veux définitivement pas le xml ** avant ** l'envoyer. Je veux la réponse. SOAPFaults et d'autres erreurs empêchent le client WS de désorganiser l'objet Java fortement typé. Donc, j'aimerais avoir la charge utile de la réponse ** XML **. Cela revient à ma question initiale: Y at-il une raison quelconque que je ne pouvais pas mettre dans un ThreadLocal dans le gestionnaire pour récupérer du client? Merci encore pour toute l'aide. – user1955401

Questions connexes