これは私にとって本当に苛立たしいことなので、私が知っていることと今知らないことを説明しようと思います。投稿の下部にある私の更新を必ず確認してください。
まず、Spring-WSを使用してメッセージを処理する戦争があります。WebServiceTemplateを使用してメッセージを送信するクライアントもあります。Tomcat7にデプロイします。
現在の開発環境では、Tomcat7サーバーはJRE6u24を使用しています。ローカルでは、クライアントを使用してSOAPメッセージを送信するときに、同じバージョンを実行しています。すべてが期待どおりに機能します。
ローカルのJRE7u04を作成すると、500の応答が返され、サーバーに次のエラーが表示されます。
[2012-05-05 20:19:13,179] DEBUG - org.springframework.web.servlet.FrameworkServlet.processRequest(671) | Could not complete request
org.springframework.ws.soap.saaj.SaajSoapEnvelopeException: Could not access envelope: Unable to create envelope from given source: ; nested exception is com.sun.xml.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source:
at org.springframework.ws.soap.saaj.SaajSoapMessage.getSaajVersion(SaajSoapMessage.java:260)
at org.springframework.ws.soap.saaj.SaajSoapMessage.getImplementation(SaajSoapMessage.java:342)
at org.springframework.ws.soap.saaj.SaajSoapMessage.<init>(SaajSoapMessage.java:117)
at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:184)
at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:58)
at org.springframework.ws.transport.AbstractWebServiceConnection.receive(AbstractWebServiceConnection.java:90)
at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:86)
at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:57)
at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:222)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:684)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:471)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:402)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
at org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:195)
at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:159)
at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:141)
at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:90)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:417)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:964)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: com.sun.xml.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source:
at com.sun.xml.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:127)
at com.sun.xml.messaging.saaj.soap.ver1_2.SOAPPart1_2Impl.createEnvelopeFromSource(SOAPPart1_2Impl.java:84)
at com.sun.xml.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:150)
at org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion(SaajUtils.java:155)
at org.springframework.ws.soap.saaj.SaajSoapMessage.getSaajVersion(SaajSoapMessage.java:257)
... 39 more
Caused by: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: The markup in the document preceding the root element must be well-formed.
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:501)
at com.sun.xml.messaging.saaj.util.transform.EfficientStreamingTransformer.transform(EfficientStreamingTransformer.java:414)
at com.sun.xml.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:118)
... 43 more
Caused by: org.xml.sax.SAXParseException: The markup in the document preceding the root element must be well-formed.
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333)
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:484)
... 45 more
私は多くの潜在的な問題を経験しました。しかし、ある意味でSAAJの問題に絞り込んだと思います。
Spring-WSのSaajSoapMessageFactoryクラスには、次で始まるメソッドがあります。
public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
MimeHeaders mimeHeaders = parseMimeHeaders(inputStream);
try {
inputStream = checkForUtf8ByteOrderMark(inputStream);
SOAPMessage saajMessage = messageFactory.createMessage(mimeHeaders, inputStream);
postProcess(saajMessage);
return new SaajSoapMessage(saajMessage, langAttributeOnSoap11FaultString, messageFactory);
}
JRE 6でクライアントを使用して送信すると、createMessage呼び出し後のinputStreamは次のように始まります。
[60, 101, 110, 118, 58, 69, 110, 118, 101, 108, 111, 112, 101, 32, 120, 109, 108, 110, 115, 58, 101, 110, 118, 61, 34, 104, 116
これは次のように変換されます:<env:Envelope
...など。
ただし、JRE 7でクライアントを使用して送信すると、createMessage呼び出し後のinputStreamは次のように始まります。
[101, 110, 118, 58, 69, 110, 118, 101, 108, 111, 112, 101, 32, 120, 109, 108, 110, 115, 58, 101, 110, 118, 61, 34, 104, 116
ご覧のとおり、最初のバイトである左山かっこが欠落しています。私はそれにデバッグしようとしていますが、com.sun.xml.internalソースが不足しているため、非常に効果的です。
また、JRE 6では、checkForUtf8ByteOrderMark呼び出し後のPushbackInputStreamは、実際には最後のバイト配列のように見えます。
[60, 101, 110, 118, 58, 69, 110, 118, 101, 108, 111, 112, 101, 32, 120, 109, 108, 110, 115, 58, 101, 110, 118, 61, 34, 104, 116,
等
ただし、JRE 7を使用して送信する場合は、次のようになります。
[60, 0, 0, 0, 0, 0, 0, 0, 0
、など
現在、メソッド自体は同じフローに従っているように見えます。BOMがないことを確認してから、取得したものを元に戻して確認します(少なくとも、私にはそう見えます)。
だから、私は2つの質問があります:
1)何が起こっているのか誰か知っていますか?ここにベルを鳴らしているものはありますか?
2)これらのcom.sun.xml.internalパッケージのソースを取得するにはどうすればよいですか?
これはEclipseのTomcatでローカルに実行でき、問題はないようですが、おそらくそこではファンキーなクラス読み込みが行われていることはわかっています。
アップデート1:
私はいくつかのソースをコードに関連付けることができ、SOAPPart1_2Implでこのメソッドに入りました:
public void setContent(Source source) throws SOAPException {
try {
if (source instanceof StreamSource) {
InputStream is = ((StreamSource) source).getInputStream();
Reader rdr = ((StreamSource) source).getReader();
if (is != null) {
this.source = new JAXMStreamSource(is);
} else if (rdr != null) {
this.source = new JAXMStreamSource(rdr);
} else {
log.severe("SAAJ0544.soap.no.valid.reader.for.src");
throw new SOAPExceptionImpl("Source does not have a valid Reader or InputStream");
}
}
これで、InputStreamを設定する最初のパスを使用します。非常に興味深いのは、これが行われると、ソースに次のように始まるByteInputStreamがあることです。
[60, 0, 0, 101, 110, 118, 58, 69, 110, 118, 101, 108, 111, 112, 101, 32, 120, 109, 108, 110, 115, 58, 101,
等
私はこれに非常に混乱しています。これらの最初の3文字が正確にどうなるかを理解しようとします。おそらく、checkForUtf8ByteOrderMarkメソッドに何らかの副作用があります。
アップデート2:
さて、今私は本当にどこかに到達しています。そのJAXMStreamSourceクラスを調べたところ、次のメソッドを持つByteOutputStreamクラスが作成されました。
public void write(InputStream in) throws IOException {
if (in instanceof ByteArrayInputStream) {
int size = in.available();
ensureCapacity(size);
count += in.read(buf,count,size);
return;
}
while(true) {
int cap = buf.length-count;
int sz = in.read(buf,count,cap);
if(sz<0) return; // hit EOS
count += sz;
if(cap==sz)
// the buffer filled up. double the buffer
ensureCapacity(count);
}
}
「intsz=in.read(buf、count、cap);」の行 60の後の2つのゼロが追加される場所です。私はまだ、1.7を使用しているクライアントがこの効果をもたらした可能性がある理由と理由を理解しようとしています。