Java Web 服务中的 Soap 信封命名空间前缀
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30623419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Soap envelope namespace prefix in Java web service
提问by griboedov
I am trying to change prefix for soap envelope in response of web-service from S="http://schemas.xmlsoap.org/soap/envelope/" to soap="http://schemas.xmlsoap.org/soap/envelope/":
我正在尝试更改soap信封的前缀以响应Web服务从S="http://schemas.xmlsoap.org/soap/envelope/"到soap="http://schemas.xmlsoap.org/soap/信封/”:
so here's how the response looks like now:
所以这是现在的响应:
<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>
and here's how it must look like:
这是它的样子:
<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>
How can this be attained?
如何做到这一点?
EDIT:
编辑:
I added soap handler class and the problem starts when I'm trying to get 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 throws:
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 log has no errors.
Tomcat 日志没有错误。
It doesn't occur without custom soap handler.
如果没有自定义肥皂处理程序,它就不会发生。
Perhaps the reason is in the way I implemented web method. It creates a new thread with an object that processes request and then returns empty response, thus releasing client from waiting for request processing is over:
也许原因在于我实现网络方法的方式。它创建一个带有对象的新线程,该对象处理请求,然后返回空响应,从而使客户端不再等待请求处理结束:
@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();
}
}
and MyProcess is class where request processing really is and stmt.executeUpdate is executed.
和 MyProcess 是请求处理真正所在的类,并且 stmt.executeUpdate 被执行。
采纳答案by bvdb
I think Customising JAX-WS prefix of a SOAP responsesummarizes your options.
我认为自定义 SOAP 响应的 JAX-WS 前缀总结了您的选择。
Option 1:I think you just need to put this above your package.
选项 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/")
}
)
Option 2: Alternatively (also mentioned in the link), you could use a SOAPHandler
. You could add a configuration file to bind these handlers. But in fact, you can just add them at runtime. I think this needs some explanation: The trick is to get an instance of the BindingProvider
. This is different if you are a consumer or provider of the webservice.
选项 2:或者(也在链接中提到),您可以使用SOAPHandler
. 您可以添加一个配置文件来绑定这些处理程序。但实际上,您可以在运行时添加它们。我认为这需要一些解释:诀窍是获取BindingProvider
. 如果您是 Web 服务的消费者或提供者,则情况有所不同。
If you are server(i.e. providing a webservice):
如果您是服务器(即提供网络服务):
webservice = Class.forName(serviceClassName).newInstance();
Endpoint e = Endpoint.create(webservice);
BindingProvider bp = (BindingProvider)e.getBinding();
e.publish("http://localhost:" + serverPort + servicePath);
If you are client(i.e. consuming a webservice):
如果您是客户(即使用网络服务):
Service service = new Service(url, qname);
Port port = service.getPort();
BindingProvider bp = ((BindingProvider) port);
When you have the bindingprovider, you can bind the handler as follows.
当您拥有 bindingprovider 时,您可以按如下方式绑定处理程序。
List<Handler> chain = bp.getHandlerChain();
if (chain == null) chain = new ArrayList<Handler>();
chain.add(myCustomHandler);
bp.setHandlerChain(chain);
Now, for the chained handler itself, you should implement SOAPHandler<SOAPMessageContext>
. There you can manipulate your messages however you like. (see linked post above for an example).
现在,对于链式处理程序本身,您应该实现SOAPHandler<SOAPMessageContext>
. 在那里,您可以随心所欲地处理您的消息。(有关示例,请参见上面的链接帖子)。