在JAX-WS消息中删除XML声明

我正在尝试使用Java代码调用Web服务。 所以我使用JAX-WS和JAXB从wsdl文件生成我的对象。

当我调用webservice时,它会响应此错误:

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声明

  

当我从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-WSJAXB生成的。

提前致谢!

找到我自己的解决方案

首先,正如其他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"); 

我不明白为什么我们得到“XML声明必须结束”?>“”错误。 因为我的解决方案没有删除xml声明。 可能与xml结构有关(但我没有足够的知识来确认它)。

我需要参考http://blog.jdevelop.eu/?p=67post,让我参考这个解决方案,一些调试代码来自这篇文章。

接下来,我将完整的CustomHandler类放入其中,以便它可以容纳任何人。

 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 { 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 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 (eg 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; } }