【问题标题】:Soap envelope namespace prefix in Java web serviceJava Web 服务中的肥皂信封命名空间前缀
【发布时间】:2015-06-03 14:45:36
【问题描述】:

我正在尝试更改肥皂信封的前缀以响应来自的 Web 服务 S="http://schemas.xmlsoap.org/soap/envelope/" 到 肥皂=“http://schemas.xmlsoap.org/soap/envelope/”:

现在的响应如下所示:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <n:soaprequestResponse xmlns:n="http://tempuri.org/soaprequest">
         <n:soaprequestResult/>
      </n:soaprequestResponse>
   </S:Body>
</S:Envelope>

这就是它的样子:

<soap:Envelope xmlns:soap:="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <n:soaprequestResponse xmlns:n="http://tempuri.org/soaprequest">
         <n:soaprequestResult/>
      </n:soaprequestResponse>
   </soap:Body>
</soap:Envelope>

如何做到这一点?

编辑:

我添加了肥皂处理程序类,当我尝试获取信封时问题就开始了:

package org.tempuri.soaprequest;

import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;


public class SoapHandler implements SOAPHandler<SOAPMessageContext> {

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

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        if ((boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) { //Check here that the message being intercepted is an outbound message from your service, otherwise ignore.
            try {
                SOAPEnvelope msg = context.getMessage().getSOAPPart().getEnvelope(); //just trying to get envelope
            } catch (SOAPException ex) {
                ex.printStackTrace();
            }

        return true; //indicates to the context to proceed with (normal)message processing
    }

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

    @Override
    public void close(MessageContext context) {
          //do nothing

    }
}

SoapUI 抛出:

<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
    <faultcode>S:Server</faultcode>
        <faultstring>JVMVRFY012 stack shapeinconsistent;class=com/sun/xml/messaging/saaj/soap/SOAPDocumentImpl, method=createDocumentFragment()Lorg/w3c/dom/DocumentFragment;, pc=5
    </faultstring>
</S:Fault>

Tomcat 日志没有错误。

没有自定义肥皂处理程序就不会发生这种情况。

也许原因在于我实现 web 方法的方式。它用一个对象创建一个新线程来处理请求,然后返回空响应,从而释放客户端等待请求处理结束:

@WebResult(name="soaprequestResult", targetNamespace="http://tempuri.org/soaprequest")
public SoaprequestResponse.SoaprequestResult soaprequest(@WebParam(name="streams", targetNamespace="http://tempuri.org/soaprequest") SoaprequestStreams streams) {
    try {
        new Thread(new MyProcess(streams)).start();
        return new SoaprequestResponse().getSoaprequestResult();
    } catch(Exception e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        String stackTrace = sw.toString();
        return new SoaprequestResponse().getSoaprequestResult();
    }
}

MyProcess 是真正执行请求处理并执行 stmt.executeUpdate 的类。

【问题讨论】:

  • soap::Body 中的:: 是编辑错误,对吧?
  • 也许是个愚蠢的问题,但为什么呢?两者是相同的。尽管如此:stackoverflow.com/questions/12889943/…
  • @bvdb 感谢您的链接,但它解释了更改正文内容 ns 前缀

标签: java web-services


【解决方案1】:

我认为Customising JAX-WS prefix of a SOAP response 总结了您的选择。

选项 1:我认为您只需将其放在包裹上方即可。

@javax.xml.bind.annotation.XmlSchema(namespace = "http://schemas.xmlsoap.org/soap/envelope/",
   xmlns = { 
      @javax.xml.bind.annotation.XmlNs(prefix = "soap", 
         namespaceURI="http://schemas.xmlsoap.org/soap/envelope/")
    }
)

选项 2:或者(也在链接中提到),您可以使用 SOAPHandler。您可以添加一个配置文件来绑定这些处理程序。但实际上,您可以在运行时添加它们。我认为这需要一些解释:诀窍是获取BindingProvider 的实例。如果您是 Web 服务的消费者或提供者,情况就不同了。

如果您是服务器(即提供网络服务):

webservice = Class.forName(serviceClassName).newInstance();
Endpoint e = Endpoint.create(webservice);
BindingProvider bp = (BindingProvider)e.getBinding();
e.publish("http://localhost:" + serverPort + servicePath);

如果您是客户(即使用网络服务):

Service service = new Service(url, qname);
Port port = service.getPort();
BindingProvider bp = ((BindingProvider) port);

当你有 bindingprovider 后,你可以按如下方式绑定 handler。

List<Handler> chain = bp.getHandlerChain();
if (chain == null) chain = new ArrayList<Handler>();
chain.add(myCustomHandler);
bp.setHandlerChain(chain);

现在,对于链式处理程序本身,您应该实现SOAPHandler&lt;SOAPMessageContext&gt;。在那里,您可以随心所欲地操纵您的消息。 (有关示例,请参见上面的链接帖子)。

【讨论】:

  • 这适用于部署在 tomcat 8 的 web-service 吗?
  • 是的,这只是通用的 java web 服务功能。应该适用于所有 Web 容器。请注意,所有提到的类都在 javax.ws 包中。
  • @griboedov 那么,只有选项 2 有效吗? (然后我将删除选项 1)
  • 我尝试了顶部链接中解释的解决方案,我添加了肥皂处理程序类并添加了 handler-chain.xml,现在我得到:“JVMVRFY012 堆栈形状不一致;class=com/sun /xml/messaging/saaj/soap/SOAPDocumentImpl, method=createDocumentFragment()Lorg/w3c/dom/DocumentFragment;, pc=5" 在soap响应中。所以我正在努力解决它。
  • @bvdb 我可以确认它确实有效!还有两个……这是我正在玩的一个示例项目:
猜你喜欢
  • 2013-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
相关资源
最近更新 更多