Изменение префикса пространства имен XML по умолчанию, созданного с помощью JAXWS - PullRequest
14 голосов
/ 02 октября 2010

Я использую JAXWS для создания клиента WebService для создаваемого нами Java-приложения.

Когда JAXWS создает свои XML-файлы для использования в протоколе SOAP, он генерирует следующий префикс пространства имен:

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

Моя проблема в том, что мой Counterpart (крупная компания по переводу денег), которая управляет сервером, к которому подключается мой клиент, отказывается принимать вызов WebService (, пожалуйста, не спрашивайте, почему ), если толькоXMLNS (префикс пространства имен XML - soapenv).Например:

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

Итак, мой вопрос:

Есть ли способ, которым я приказываю JAXWS (или любой другой технологии клиента Java WS) генерировать клиентов, используя soapenv вместо * 1015?* как префикс XMLNS?Есть ли вызов API для установки этой информации?

Спасибо!

Ответы [ 2 ]

17 голосов
/ 24 января 2011

Возможно, вам уже поздно, и я не уверен, что это может сработать, но вы можете попробовать.

Сначала вам нужно реализовать SoapHandler, а в методе handleMessage вы можете изменить SOAPMessage.Я не уверен, что вы можете изменить этот префикс напрямую, но вы можете попробовать:

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

  ...
}

Затем вам нужно создать 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;
  }
}

И, наконец, вынеобходимо добавить HandlerResolver к вашему клиентскому сервису:

Service service = Service.create(wsdlLoc, serviceName);
service.setHandlerResolver(new MyHandlerResolver());
6 голосов
/ 10 апреля 2017

Этот пост, хотя и слишком поздно для оригинального постера, предназначен для помощи другим, кто может столкнуться с этим. Я должен был решить эту проблему в последние несколько дней. В частности, мне нужно было изменить префиксы, используемые в конверте SOAP, потому что поставщик услуг требовал, чтобы префиксы пространства имен соответствовали очень специфическому шаблону. В соответствии с этим шаблоном требовалось изменить префикс пространства имен для элементов envelope, header и body и body (по сравнению со стандартными, введенными JAX-WS). Вот схема решения, которое я использовал:

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

Установка описанного выше обработчика обработчика для экземпляра класса обслуживания (сгенерированного JAX-WS / wsimport) выглядит следующим образом:

yourWebServiceClient.setHandlerResolver(new HandlerResolver() {
  @Override
  public List<Handler> getHandlerChain(PortInfo portInfo) {
    return Arrays.asList(new MyMessageNamespaceMapper());
  }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...