Java 更改使用JAXWS生成的默认XML命名空间前缀
我正在使用JAXWS为我们正在构建的Java应用程序生成一个WebService客户端 当JAXWS构建用于SOAP协议的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
<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());
}
});