2010-10-02 3 views
11

J'utilise JAXWS pour générer un client WebService pour une application Java que nous sommes en train de créer.Modification du préfixe d'espace de nom XML par défaut généré avec JAXWS

Lorsque JAXWS construire ses XMLs à utiliser dans le protocole SOAP, il génère le préfixe d'espace de noms suivant:

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> 
    <env:Body ...> 
     <!-- body goes here --> 
    </env:Body> 
</env:Envelope> 

Mon problème est que mon Contrepartie (une grande société de transfert d'argent) qui gère le serveur mon client se connecte à, refuse d'accepter l'appel WebService (s'il vous plaît ne demandez pas mon pourquoi) à moins que le XMLNS (préfixe d'espace de nom XML est soapenv). Comme ceci:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soapenv:Body ...> 
     <!-- body goes here --> 
    </soapenv:Body> 
</soapenv:Envelope> 

Ma question est la suivante:

Est-il possible que je commande JAXWS (ou toute autre technologie de client Java WS) pour générer des clients à l'aide soapenv au lieu de env comme préfixe XMLNS? Y at-il un API appel pour définir cette information?

Merci!

+0

Point pedantry: Vous ne changez pas l'espace de noms, vous changez le préfixe. – skaffman

+0

@skaffman D'accord. Merci! –

+0

Salut: J'ai aussi le même problème. Avez-vous trouvé une solution? En vous remerciant, Kumar –

Répondre

15

Peut-être qu'il est tard pour vous et je ne sais pas si cela peut fonctionner, mais vous pouvez essayer. D'abord vous devez implémenter un SoapHandler et, dans la méthode handleMessage, vous pouvez modifier le SOAPMessage. Je ne sais pas si vous pouvez modifier directement ce préfixe mais vous pouvez essayer:

public class MySoapHandler implements SOAPHandler<SOAPMessageContext> 
{ 

    @Override 
    public boolean handleMessage(SOAPMessageContext soapMessageContext) 
    { 
    try 
    { 
     SOAPMessage message = soapMessageContext.getMessage(); 
     // I haven't tested this 
     message.getSOAPHeader().setPrefix("soapenv"); 
     soapMessageContext.setMessage(message); 
    } 
    catch (SOAPException e) 
    { 
     // Handle exception 
    } 

    return true; 
    } 

    ... 
} 

Ensuite, vous devez créer un HandlerResolver:

public class MyHandlerResolver implements HandlerResolver 
{ 
    @Override 
    public List<Handler> getHandlerChain(PortInfo portInfo) 
    { 
    List<Handler> handlerChain = Lists.newArrayList(); 
    Handler soapHandler = new MySoapHandler(); 
    String bindingID = portInfo.getBindingID(); 

    if (bindingID.equals("http://schemas.xmlsoap.org/wsdl/soap/http")) 
    { 
     handlerChain.add(soapHandler); 
    } 
    else if (bindingID.equals("http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")) 
    { 
     handlerChain.add(soapHandler); 
    } 

    return handlerChain; 
    } 
} 

Et enfin, vous devrez ajouter votre HandlerResolver à votre service client:

Service service = Service.create(wsdlLoc, serviceName); 
service.setHandlerResolver(new MyHandlerResolver()); 
1

ce poste, alors probablement trop tard pour l'affiche originale, est destinée à aider les autres qui peuvent rencontrer ce. J'ai dû résoudre ce problème ces derniers jours. En particulier, je devais changer les préfixes utilisés dans l'enveloppe SOAP parce que le fournisseur de service exigeait que les préfixes d'espace de noms se conforment à un modèle très spécifique. La conformité à ce modèle nécessitait de changer le préfixe d'espace de nommage pour l'enveloppe, l'en-tête et le corps, et les éléments de corps (à partir des éléments standard mis en place par JAX-WS). Voici un aperçu de la solution je:

import javax.xml.namespace.QName; 
import javax.xml.soap.SOAPBody; 
import javax.xml.soap.SOAPElement; 
import javax.xml.soap.SOAPEnvelope; 
import javax.xml.soap.SOAPException; 
import javax.xml.soap.SOAPHeader; 
import javax.xml.soap.SOAPMessage; 
import javax.xml.ws.handler.MessageContext; 
import javax.xml.ws.handler.soap.SOAPHandler; 
import javax.xml.ws.handler.soap.SOAPMessageContext; 
import java.util.HashSet; 
import java.util.Iterator; 
import java.util.Set; 

public class MyMessageNamespaceMapper implements SOAPHandler<SOAPMessageContext> { 

    @Override 
    public Set<QName> getHeaders() { 
    return null; 
    } 

    @Override 
    public boolean handleMessage(SOAPMessageContext context) { 
    final Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 
    // only process outbound messages 
    if (outbound) { 
     try { 
     final SOAPMessage soapMessage = context.getMessage(); 
     final SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope(); 
     final SOAPHeader soapHeader = soapMessage.getSOAPHeader(); 
     final SOAPBody soapBody = soapMessage.getSOAPBody(); 

     // STEP 1: add new prefix/namespace entries 
     soapEnvelope.addNamespaceDeclaration("S1", "http://schemas.xmlsoap.org/soap/envelope/"); 
     soapEnvelope.addNamespaceDeclaration("FOO-1", "http://foo1.bar.com/ns"); 

     // STEP 2: set desired namespace prefixes 
     // set desired namespace prefix for the envelope, header and body 
     soapEnvelope.setPrefix("S1"); 
     soapHeader.setPrefix("S1"); 
     soapBody.setPrefix("S1"); 
     addDesiredBodyNamespaceEntries(soapBody.getChildElements()); 

     // STEP 3: remove prefix/namespace entries entries added by JAX-WS 
     soapEnvelope.removeNamespaceDeclaration("S"); 
     soapEnvelope.removeNamespaceDeclaration("SOAP-ENV"); 
     removeUndesiredBodyNamespaceEntries(soapBody.getChildElements()); 

     // IMPORTANT! "Save" the changes 
     soapMessage.saveChanges(); 
     } 
     catch (SOAPException e) { 
     // handle the error 
     } 
    } 

    return true; 
    } 

    private void addDesiredBodyNamespaceEntries(Iterator childElements) { 
    while (childElements.hasNext()) { 
     final Object childElementNode = childElements.next(); 
     if (childElementNode instanceof SOAPElement) { 
     SOAPElement soapElement = (SOAPElement) childElementNode; 

     // set desired namespace body element prefix 
     soapElement.setPrefix("FOO-1"); 

     // recursively set desired namespace prefix entries in child elements 
     addDesiredBodyNamespaceEntries(soapElement.getChildElements()); 
     } 
    } 
    } 

    private void removeUndesiredBodyNamespaceEntries(Iterator childElements) { 
    while (childElements.hasNext()) { 
     final Object childElementNode = childElements.next(); 
     if (childElementNode instanceof SOAPElement) { 
     SOAPElement soapElement = (SOAPElement) childElementNode; 

     // we remove any prefix/namespace entries added by JAX-WS in the body element that is not the one we want 
     for (String prefix : getNamespacePrefixList(soapElement.getNamespacePrefixes())) { 
      if (prefix != null && ! "FOO-1".equals(prefix)) { 
      soapElement.removeNamespaceDeclaration(prefix); 
      } 
     } 

     // recursively remove prefix/namespace entries in child elements 
     removeUndesiredBodyNamespaceEntries(soapElement.getChildElements()); 
     } 
    } 
    } 

    private Set<String> getNamespacePrefixList(Iterator namespacePrefixIter) { 
    Set<String> namespacePrefixesSet = new HashSet<>(); 
    while (namespacePrefixIter.hasNext()) { 
     namespacePrefixesSet.add((String) namespacePrefixIter.next()); 
    } 
    return namespacePrefixesSet; 
    } 

    @Override 
    public boolean handleFault(SOAPMessageContext context) { 
    return true; 
    } 

    @Override 
    public void close(MessageContext context) { 
    } 
} 

Réglage du résolveur de gestionnaire ci-dessus sur une instance de la classe de service (généré par JAX-WS/wsimport) ressemble à ceci:

yourWebServiceClient.setHandlerResolver(new HandlerResolver() { 
    @Override 
    public List<Handler> getHandlerChain(PortInfo portInfo) { 
    return Arrays.asList(new MyMessageNamespaceMapper()); 
    } 
}); 
Questions connexes