删除 JAX-WS 消息中的 XML 声明
Removing XML declaration in JAX-WS message
我正在尝试使用 Java 代码调用网络服务。
所以我使用 JAX-WS 和 JAXB 从 wsdl 文件生成我的对象。
当我调用 Web 服务时,它响应此错误:
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: The [javax.xml.transform.TransformerException] occurred during XSLT transformation: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: The XML declaration must end with "?>".
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: The [javax.xml.transform.TransformerException] occurred during XSLT transformation: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: The XML declaration must end with "?>".
at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:189)
at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:122)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
因此,我使用 wireshark 分析了正在发送的 xml 消息。并尝试用 soapUI 重新发送它。
并发现我的 xml 包含 xml 声明
<?xml version='1.0' encoding='UTF-8'?>
当我将它从 SoapUI 中删除并重新发送时。消息正常。
我的 java 代码是这样的:
public static Data receiveSIBS(webserviceclient.Data input) {
webserviceclient.Starter service = new webserviceclient.Starter();
webserviceclient.PortType port = service.getSOAPEventSource();
BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
return port.receiveSIBS(input);
}
如何在没有此 xml 声明的情况下在 Java 中生成消息?
因为 xml 消息全部由 JAX-WS 和 JAXB.
生成
在此先致谢!
找到我自己的解决方案!
首先,如其他 post 所述,我实现了一个 SOAPHandler 来编辑这两个属性:
soapMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-16");
soapMsg.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");
但是虽然这两个属性在handleMessage()方法中改变了消息实例,但不会像这样发送,而是发送默认xml声明的消息。
解决方案是设置这两个 NamespaceDeclaration,而不是设置此属性:
SOAPEnvelope env = sp.getEnvelope();
env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
env.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
我不明白为什么会出现 "The XML declaration must end with "?>"" 错误。因为我的解决方案没有删除 xml 声明。可能与 xml 结构有关(但我没有足够的知识来确认它)。
我需要参考 http://blog.jdevelop.eu/?p=67 post 让我找到这个解决方案,一些调试代码来自这个 post.
接下来我将完整的 CustomHandler class 放入其中,这样它就可以容纳任何人。
import java.io.ByteArrayOutputStream;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/**
*
* @author Daniel Chang Yan
*/
public class CustomHandler implements SOAPHandler<SOAPMessageContext> {
public boolean handleMessage(SOAPMessageContext context) {
Boolean isOutbound
= (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (isOutbound != null && isOutbound) {
SOAPMessage soapMsg = context.getMessage();
try {
//Properties always rewritten by jaxws, no matter what is set here
//soapMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-16");
//soapMsg.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");
// get SOAP-Part
SOAPPart sp = soapMsg.getSOAPPart();
//edit Envelope
SOAPEnvelope env = sp.getEnvelope();
env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
env.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
} catch (SOAPException e) {
throw new RuntimeException(e);
}
// print SOAP-Message
System.out.println("Direction=outbound (handleMessage)...");
dumpSOAPMessage(soapMsg);
} else {
// INBOUND
System.out.println("Direction=inbound (handleMessage)...");
SOAPMessage msg = ((SOAPMessageContext) context).getMessage();
dumpSOAPMessage(msg);
}
return true;
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext context) {
System.out.println("ServerSOAPHandler.handleFault");
boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
System.out.println("Direction=outbound (handleFault)...");
} else {
System.out.println("Direction=inbound (handleFault)...");
}
if (!outbound) {
try {
SOAPMessage msg = ((SOAPMessageContext) context).getMessage();
dumpSOAPMessage(msg);
if (context.getMessage().getSOAPBody().getFault() != null) {
String detailName = null;
try {
detailName = context.getMessage().getSOAPBody().getFault().getDetail().getFirstChild().getLocalName();
System.out.println("detailName=" + detailName);
} catch (Exception e) {
}
}
} catch (SOAPException e) {
e.printStackTrace();
}
}
return true;
}
public void close(MessageContext mc) {
}
/**
* Dump SOAP Message to console
*
* @param msg
*/
private void dumpSOAPMessage(SOAPMessage msg) {
if (msg == null) {
System.out.println("SOAP Message is null");
return;
}
//System.out.println("");
System.out.println("--------------------");
System.out.println("DUMP OF SOAP MESSAGE");
System.out.println("--------------------");
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
msg.writeTo(baos);
System.out.println(baos.toString(getMessageEncoding(msg)));
// show included values
String values = msg.getSOAPBody().getTextContent();
System.out.println("Included values:" + values);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Returns the message encoding (e.g. utf-8)
*
* @param msg
* @return
* @throws javax.xml.soap.SOAPException
*/
private String getMessageEncoding(SOAPMessage msg) throws SOAPException {
String encoding = "utf-8";
if (msg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING) != null) {
encoding = msg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING).toString();
}
return encoding;
}
}
我正在尝试使用 Java 代码调用网络服务。 所以我使用 JAX-WS 和 JAXB 从 wsdl 文件生成我的对象。
当我调用 Web 服务时,它响应此错误:
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: The [javax.xml.transform.TransformerException] occurred during XSLT transformation: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: The XML declaration must end with "?>".
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: The [javax.xml.transform.TransformerException] occurred during XSLT transformation: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: The XML declaration must end with "?>".
at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:189)
at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:122)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
因此,我使用 wireshark 分析了正在发送的 xml 消息。并尝试用 soapUI 重新发送它。
并发现我的 xml 包含 xml 声明
<?xml version='1.0' encoding='UTF-8'?>
当我将它从 SoapUI 中删除并重新发送时。消息正常。
我的 java 代码是这样的:
public static Data receiveSIBS(webserviceclient.Data input) {
webserviceclient.Starter service = new webserviceclient.Starter();
webserviceclient.PortType port = service.getSOAPEventSource();
BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
return port.receiveSIBS(input);
}
如何在没有此 xml 声明的情况下在 Java 中生成消息? 因为 xml 消息全部由 JAX-WS 和 JAXB.
生成在此先致谢!
找到我自己的解决方案!
首先,如其他 post 所述,我实现了一个 SOAPHandler 来编辑这两个属性:
soapMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-16");
soapMsg.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");
但是虽然这两个属性在handleMessage()方法中改变了消息实例,但不会像这样发送,而是发送默认xml声明的消息。
解决方案是设置这两个 NamespaceDeclaration,而不是设置此属性:
SOAPEnvelope env = sp.getEnvelope();
env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
env.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
我不明白为什么会出现 "The XML declaration must end with "?>"" 错误。因为我的解决方案没有删除 xml 声明。可能与 xml 结构有关(但我没有足够的知识来确认它)。
我需要参考 http://blog.jdevelop.eu/?p=67 post 让我找到这个解决方案,一些调试代码来自这个 post.
接下来我将完整的 CustomHandler class 放入其中,这样它就可以容纳任何人。
import java.io.ByteArrayOutputStream;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/**
*
* @author Daniel Chang Yan
*/
public class CustomHandler implements SOAPHandler<SOAPMessageContext> {
public boolean handleMessage(SOAPMessageContext context) {
Boolean isOutbound
= (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (isOutbound != null && isOutbound) {
SOAPMessage soapMsg = context.getMessage();
try {
//Properties always rewritten by jaxws, no matter what is set here
//soapMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-16");
//soapMsg.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");
// get SOAP-Part
SOAPPart sp = soapMsg.getSOAPPart();
//edit Envelope
SOAPEnvelope env = sp.getEnvelope();
env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
env.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
} catch (SOAPException e) {
throw new RuntimeException(e);
}
// print SOAP-Message
System.out.println("Direction=outbound (handleMessage)...");
dumpSOAPMessage(soapMsg);
} else {
// INBOUND
System.out.println("Direction=inbound (handleMessage)...");
SOAPMessage msg = ((SOAPMessageContext) context).getMessage();
dumpSOAPMessage(msg);
}
return true;
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext context) {
System.out.println("ServerSOAPHandler.handleFault");
boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
System.out.println("Direction=outbound (handleFault)...");
} else {
System.out.println("Direction=inbound (handleFault)...");
}
if (!outbound) {
try {
SOAPMessage msg = ((SOAPMessageContext) context).getMessage();
dumpSOAPMessage(msg);
if (context.getMessage().getSOAPBody().getFault() != null) {
String detailName = null;
try {
detailName = context.getMessage().getSOAPBody().getFault().getDetail().getFirstChild().getLocalName();
System.out.println("detailName=" + detailName);
} catch (Exception e) {
}
}
} catch (SOAPException e) {
e.printStackTrace();
}
}
return true;
}
public void close(MessageContext mc) {
}
/**
* Dump SOAP Message to console
*
* @param msg
*/
private void dumpSOAPMessage(SOAPMessage msg) {
if (msg == null) {
System.out.println("SOAP Message is null");
return;
}
//System.out.println("");
System.out.println("--------------------");
System.out.println("DUMP OF SOAP MESSAGE");
System.out.println("--------------------");
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
msg.writeTo(baos);
System.out.println(baos.toString(getMessageEncoding(msg)));
// show included values
String values = msg.getSOAPBody().getTextContent();
System.out.println("Included values:" + values);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Returns the message encoding (e.g. utf-8)
*
* @param msg
* @return
* @throws javax.xml.soap.SOAPException
*/
private String getMessageEncoding(SOAPMessage msg) throws SOAPException {
String encoding = "utf-8";
if (msg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING) != null) {
encoding = msg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING).toString();
}
return encoding;
}
}