2010-10-02 7 views
11

Ich verwende JAXWS, um einen WebService-Client für eine Java-Anwendung zu generieren, die wir erstellen.Ändern des Standard-XML-Namespacepräfix, das mit JAXWS generiert wurde

Wenn JAXWS seine XMLs baut in SOAP-Protokoll verwenden, generiert es die folgende Namespacepräfix:

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

Mein Problem ist, dass meine Gesprächspartner (eine große Geldtransfergesellschaft), die den Server meines Client verwaltet, ist Verbindungs zu, weigert sich, den WebService-Anruf zu akzeptieren (bitte fragen Sie nicht, warum), es sei denn, die XMLNS (XML-Namespace-Präfix ist soapenv). Wie folgt aus:

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

Also meine Frage ist:

Gibt es eine Möglichkeit, ich JAXWS (oder eine andere Java-WS-Client-Technologie) Befehl Kunden zu generieren mit soapenv statt env als XMLNS Präfix? Gibt es einen API-Aufruf um diese Informationen zu setzen?

Danke!

+0

Punkt Pedanterie: Sie ändern den Namensraum nicht, Sie ändern das Präfix. – skaffman

+0

@skaffman Zustimmen. Vielen Dank! –

+0

Hallo: Ich habe auch das gleiche Problem. Hast du irgendeine Lösung gefunden? Ich danke Ihnen, Kumar –

Antwort

15

Vielleicht ist es spät für Sie und ich bin mir nicht sicher, ob das funktionieren könnte, aber Sie können es versuchen.

Zuerst müssen Sie einen SoapHandler implementieren, und in der handleMessage Methode können Sie die SOAPMessage ändern. Ich bin mir nicht sicher, ob Sie direkt, dass Präfix ändern können, aber Sie können versuchen:

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; 
    } 

    ... 
} 

Dann müssen Sie eine HandlerResolver erstellen:

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; 
    } 
} 

Und schließlich werden Sie Ihre HandlerResolver hinzufügen müssen Ihr Kundendienst:

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

Dieser Beitrag, während wahrscheinlich zu spät für das ursprüngliche Plakat, sollten andere helfen, die in diesen laufen können. Ich musste dieses Problem in den letzten Tagen lösen. Insbesondere musste ich die Präfixe ändern, die im SOAP-Envelope verwendet wurden, da der Dienstanbieter verlangte, dass die Namespacepräfixe einem sehr spezifischen Muster entsprechen. Die Anpassung an dieses Muster erforderte die Änderung des Namespacepräfix für die Elemente envelope, header und body sowie body (von den Standardwerten von JAX-WS). Hier eine übersicht der Lösung, die ich verwendet:

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) { 
    } 
} 

Einstellen des Handlers Resolver oben auf einer Instanz der Dienstklasse (erzeugt durch JAX-WS/wsimport) sieht wie folgt aus:

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