Java 更改由 JAXWS 生成的默认 XML 命名空间前缀
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3846121/
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
Changing the default XML namespace prefix generated with JAXWS
提问by Pablo Santa Cruz
I am using JAXWS to generate a WebService client for a Java Application we're building.
我正在使用 JAXWS 为我们正在构建的 Java 应用程序生成一个 WebService 客户端。
When JAXWS build its XMLs to use in SOAP protocol, it generates the following namespace prefix:
当 JAXWS 构建其 XML 以在 SOAP 协议中使用时,它会生成以下名称空间前缀:
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body ...>
<!-- body goes here -->
</env:Body>
</env:Envelope>
My problem is that my Counterpart (a big money transfer company) which manages the server my client is connecting to, refuses to accept the WebService call (please don't ask my why) unless the XMLNS (XML namepspace prefix is soapenv
). Like this:
我的问题是,我的 Counterpart(一家大型汇款公司)管理我的客户端所连接的服务器,拒绝接受 WebService 调用(请不要问我为什么),除非 XMLNS(XML 命名空间前缀是soapenv
)。像这样:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body ...>
<!-- body goes here -->
</soapenv:Body>
</soapenv:Envelope>
So my question is:
所以我的问题是:
Is there a way I command JAXWS (or any other Java WS client technology) to generate clients using soapenv
instead of env
as the XMLNS
prefix? Is there an API callto set this information?
有没有办法命令 JAXWS(或任何其他 Java WS 客户端技术)使用soapenv
而不是env
作为XMLNS
前缀来生成客户端?是否有API 调用来设置此信息?
Thanks!
谢谢!
采纳答案by Denian
Maybe it's late for you and I'm not sure if this may work, but you can try.
也许对你来说已经晚了,我不确定这是否可行,但你可以试试。
First you need to implement a SoapHandler and, in the handleMessage
method you can modify the SOAPMessage
. I'm not sure if you can modify directly that prefix but you can try:
首先,您需要实现一个 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;
}
...
}
Then you need to create a HandlerResolver
:
然后你需要创建一个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;
}
}
And finally you'll have to add your HandlerResolver
to your client service:
最后,您必须将您的添加HandlerResolver
到您的客户服务中:
Service service = Service.create(wsdlLoc, serviceName);
service.setHandlerResolver(new MyHandlerResolver());
回答by bluecarbon
This post, while likely too late for the original poster, is intended to help others who may run into this. I had to solve this problem in the last few days. In particular, I needed to change the prefixes used in the SOAP envelope because the service provider required that the namespace prefixes conform to a very specific pattern. Conforming to this pattern required changing the namespace prefix for the envelope, header and body, and body elements (from the standard ones put in by JAX-WS). Here is an outline of the solution I used:
这篇文章虽然对于原始海报来说可能为时已晚,但旨在帮助可能遇到此问题的其他人。最近几天我不得不解决这个问题。特别是,我需要更改 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) {
}
}
Setting the handler resolver above on an instance of the service class (generated by JAX-WS/wsimport) looks like this:
在服务类的实例(由 JAX-WS/wsimport 生成)上设置上述处理程序解析器如下所示:
yourWebServiceClient.setHandlerResolver(new HandlerResolver() {
@Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
return Arrays.asList(new MyMessageNamespaceMapper());
}
});