JAX-WS errors when SOAP body contains UTF-8 BOM

2019-04-10 13:53发布

问题:

I have developed a Web Service using JAX-WS (v2.1.3 - Sun JDK 1.6.0_05) deployed on WebLogic 10.3 that works just fine when I use a Java client or SoapUI or other Web Services testing tools. I need to consume this service using 2005 Microsoft SQL Server Reporting Services and I get the following error

Couldn't create SOAP message due to exception: XML reader error: unexpected character content

SEVERE: Couldn't create SOAP message due to exception: XML reader error: unexpected character content: "?"
com.sun.xml.ws.protocol.soap.MessageCreationException: Couldn't create SOAP message due to exception: XML reader error: unexpected character content: "?"
at com.sun.xml.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:292)
at com.sun.xml.ws.transport.http.HttpAdapter.decodePacket(HttpAdapter.java:276)
at com.sun.xml.ws.transport.http.HttpAdapter.access$500(HttpAdapter.java:93)
at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:432)
at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:244)
at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:134)
at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doGet(WSServletDelegate.java:129)
at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doPost(WSServletDelegate.java:160)
at com.sun.xml.ws.transport.http.servlet.WSServlet.doPost(WSServlet.java:75)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3498)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
Caused by: com.sun.xml.ws.streaming.XMLStreamReaderException: XML reader error: unexpected character content: "?"
at com.sun.xml.ws.streaming.XMLStreamReaderUtil.nextElementContent(XMLStreamReaderUtil.java:102)
at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:174)
at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:296)
at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:128)
at com.sun.xml.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:287)
... 22 more

If I use a HTTP proxy to sniff out what SSRS is sending to JAX-WS, I see EF BB BF as the beginning of the post body and JAX-WS doesn't like that. If I remove the special characters and resubmit the request using Fiddler, then the web-service invocation works.

Why does JAX-WS blow up with the standard UTF-8 BOM? Is there a workaround to get past this issue? Any suggestions would be greatly appreciated. Thanks

--Vinny

回答1:

We had a similar problem writing a .Net client to a 3rd party Java webservice, .Net included the Byte order mark and the Java service would throw an exception.

The 3rd party SOAP method took a single string as an argument, and that string was an XML document (I love people who don't really understand what problem SOAP is trying to solve!) By default .net added the UTF-8 byte order mark to the "payload" xml document, which is strictly correct, but in practice causes problems.

In our case we found two possible solutions from the client (.net) end. I'm not sure how easy this will be to do from SQL Reporting services though.

String.Trim() - The xml had to get put into a string before passing into the soap method, calling .Trim() removed the byte order mark. Easy.

The second method was to set the UTF encoding settings on the XmlWriterSettings slightly differently, something like the following:

XmlWriter xmlWriter = null;
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.Encoding = new UTF8Encoding(false);
xmlWriter = XmlWriter.Create(xmlSteam, settings);

The important bit is the "new UTF8Encoding(false);", that argument is "encoderShouldEmitUTF8Identifier" and pretty much solves the problem.



回答2:

One workaround idea: add filter on the web application that just consumes the BOM before passing on the request document to the JAX-WS service.