Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 更改使用JAXWS生成的默认XML命名空间前缀_Java_Web Services_Jax Ws_Xml Namespaces_Webservice Client - Fatal编程技术网

Java 更改使用JAXWS生成的默认XML命名空间前缀

Java 更改使用JAXWS生成的默认XML命名空间前缀,java,web-services,jax-ws,xml-namespaces,webservice-client,Java,Web Services,Jax Ws,Xml Namespaces,Webservice Client,我正在使用JAXWS为我们正在构建的Java应用程序生成一个WebService客户端 当JAXWS构建用于SOAP协议的XML时,它会生成以下名称空间前缀: <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> <env:Body ...> <!-- body goes here --> </env:Body> </env:Enve

我正在使用JAXWS为我们正在构建的Java应用程序生成一个WebService客户端

当JAXWS构建用于SOAP协议的XML时,它会生成以下名称空间前缀:

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
   <env:Body ...>
       <!-- body goes here -->
   </env:Body>
</env:Envelope>
所以我的问题是:

我是否可以命令JAXWS(或任何其他Java WS客户端技术)使用
soapenv
而不是
env
作为
XMLNS
前缀来生成客户端?是否有API调用来设置此信息


谢谢

也许对你来说太晚了,我不确定这是否有效,但你可以试试

首先,您需要实现一个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
添加到客户端服务:

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

这篇文章,虽然对于最初的海报来说可能已经太晚了,但其目的是帮助可能遇到这种情况的其他人。在过去的几天里,我不得不解决这个问题。特别是,我需要更改SOAP信封中使用的前缀,因为服务提供商要求命名空间前缀符合非常特定的模式。要符合此模式,需要更改信封、头和体以及体元素的名称空间前缀(从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) {
  }
}
import javax.xml.namespace.QName;
导入javax.xml.soap.SOAPBody;
导入javax.xml.soap.SOAPElement;
导入javax.xml.soap.SOAPEnvelope;
导入javax.xml.soap.SOAPException;
导入javax.xml.soap.SOAPHeader;
导入javax.xml.soap.SOAPMessage;
导入javax.xml.ws.handler.MessageContext;
导入javax.xml.ws.handler.soap.SOAPHandler;
导入javax.xml.ws.handler.soap.SOAPMessageContext;
导入java.util.HashSet;
导入java.util.Iterator;
导入java.util.Set;
公共类MyMessageNamespaceMapper实现SOAPHandler{
@凌驾
公共集getHeaders(){
返回null;
}
@凌驾
公共布尔handleMessage(SOAPMessageContext上下文){
final Boolean outbound=(Boolean)context.get(MessageContext.MESSAGE\u outbound\u属性);
//仅处理出站消息
如果(出站){
试一试{
final SOAPMessage SOAPMessage=context.getMessage();
最终SOAPEnvelope SOAPEnvelope=soapMessage.getSOAPPart().getEnvelope();
final-SOAPHeader-SOAPHeader=soapMessage.getSOAPHeader();
final SOAPBody SOAPBody=soapMessage.getSOAPBody();
//步骤1:添加新的前缀/命名空间条目
soapEnvelope.addNamespaceDeclaration(“S1”http://schemas.xmlsoap.org/soap/envelope/");
soapEnvelope.addNamespaceDeclaration(“FOO-1”http://foo1.bar.com/ns");
//步骤2:设置所需的命名空间前缀
//为信封、标头和正文设置所需的命名空间前缀
soapEnvelope.setPrefix(“S1”);
soapHeader.setPrefix(“S1”);
soapBody.setPrefix(“S1”);
addDesiredBodyNamespaceEntries(soapBody.getChildElements());
//步骤3:删除JAX-WS添加的前缀/命名空间项
soapEnvelope.removeNamespaceDeclaration(“S”);
soapEnvelope.removeNamespaceDeclaration(“SOAP-ENV”);
移除不需要的ODynameSpace条目(soapBody.getChildElements());
//重要提示:“保存”更改
soapMessage.saveChanges();
}
捕获(SOAPE例外){
//处理错误
}
}
返回true;
}
私有void addDesiredBodyNamespaceEntries(迭代器子元素){
while(childElements.hasNext()){
最终对象childElementNode=childElements.next();
if(SOAPElement的childElementNode实例){
SOAPElement SOAPElement=(SOAPElement)子元素节点;
//设置所需的命名空间主体元素前缀
soapElement.setPrefix(“FOO-1”);
//在子元素中递归设置所需的命名空间前缀项
addDesiredBodyNamespaceEntries(soapElement.getChildElements());
}
}
}
private void移除不需要的ODynameSpace条目(迭代器子元素){
while(childElements.hasNext()){
最终对象childElementNode=childElements.next();
if(SOAPElement的childElementNode实例){
SOAPElement SOAPElement=(SOAPElement)子元素节点;
//我们删除JAX-WS在body元素中添加的任何前缀/名称空间条目,这些条目不是我们想要的
for(字符串前缀:getNamespacePrefixList(soapElement.getNamespacePrefixes())){
if(前缀!=null&!“FOO-1”。等于(前缀)){
removeNamespaceDeclaration(前缀);
}
}
//递归删除子元素中的前缀/命名空间项
移除不需要的ODynameSpace条目(soapElement.getChildElements());
}
}
}
私有集getNamespacePrefixList(迭代器namespacePrefixIter){
Set namespaceprefexset=new HashSet();
while(namespacePrefixIter.hasNext()){
添加((字符串)namespaceprefexister.next());
}
返回名称空间前缀集;
}
@凌驾
公共布尔handleFault(SOAPMessageContext上下文){
返回true;
}
@凌驾
公共无效关闭(MessageContext上下文){
}
}
在服务类实例(由JAX-WS/wsimport生成)上设置上面的处理程序解析器如下所示:

yourWebServiceClient.setHandlerResolver(new HandlerResolver() {
  @Override
  public List<Handler> getHandlerChain(PortInfo portInfo) {
    return Arrays.asList(new MyMessageNamespaceMapper());
  }
});
yourWebServiceClient.setHandlerResolver(新的HandlerResolver(){
@凌驾
公共列表getHandlerChain(PortInfo PortInfo){
返回Arrays.asList(新的MyMessageNamespaceMapper());
}
});

迂腐点:你不是在改变名称空间,而是在改变前缀。@skaffman同意。谢谢嗨:我也有同样的问题。你找到解决办法了吗。谢谢你,Kumar@Kumar:检查新答案。@bluwcarbon-有没有办法提供自定义名称空间,如ns:7和ns:8,而不是
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) {
  }
}
yourWebServiceClient.setHandlerResolver(new HandlerResolver() {
  @Override
  public List<Handler> getHandlerChain(PortInfo portInfo) {
    return Arrays.asList(new MyMessageNamespaceMapper());
  }
});