我有一个奇怪的问题,似乎无法得到它的底部。基本上需要记录发送到Web服务和接收(使用者)的soap XML。我相信正确的方法是使用Apache提供的开箱即用的拦截器。这些工作正常但是我们有一个特殊的情况,一个方法接受大量的参数/对象并返回大量的参数/对象,这显然会创建一个大的soap请求/响应xml。肥皂请求/响应始终正确打印,但是引发了以下错误:
应用程序配置
Spring config:
<jaxws:client id="serviceClient"
serviceClass="com.services.stubs.ServiceAPI"
address="${service.url}">
<jaxws:inInterceptors>
<ref bean="incomingInterceptor"/>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<ref bean="outgoingInterceptor"/>
</jaxws:outInterceptors>
</jaxws:client>
我的拦截器类:
public class OutLoggingInterceptor extends LoggingOutInterceptor
{
public OutLoggingInterceptor()
{
super(Phase.PRE_STREAM);
}
}
public class InLoggingInterceptor extends LoggingInInterceptor
{
public InLoggingInterceptor()
{
super(Phase.RECEIVE);
}
}
抛出错误:
org.apache.cxf.interceptor.Fault: stream is closed
at org.apache.cxf.interceptor.LoggingInInterceptor.logging(LoggingInInterceptor.java:167) ~[cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.interceptor.LoggingInInterceptor.handleMessage(LoggingInInterceptor.java:78) ~[cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:811) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1590) [cxf-rt-transports-http-2.7.6.jar:2.7.6]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1486) [cxf-rt-transports-http-2.7.6.jar:2.7.6]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1305) [cxf-rt-transports-http-2.7.6.jar:2.7.6]
at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:50) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:223) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:623) [cxf-rt-transports-http-2.7.6.jar:2.7.6]
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:541) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:474) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:377) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:330) [cxf-api-2.7.6.jar:2.7.6]
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) [cxf-rt-frontend-simple-2.7.6.jar:2.7.6]
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134) [cxf-rt-frontend-jaxws-2.7.6.jar:2.7.6]
答案 0 :(得分:0)
我可以提出几种解决方案。如果他们中的任何一个为您工作,请告知。
1)你为什么要从LoggingOutInterceptor中继承子类呢?如果只需要指定添加它的阶段,只需在Spring上下文配置中使用适当的构造函数。
2)当我使用Apache CXF实现SOAP服务时,我遇到了类似的错误。 A在拦截链中有2个自定义拦截器。其中一个是读取消息的输入流来解析它以执行一些自定义操作。问题是Xerces在解析后关闭了输入流,因此其他拦截器正在获取已经关闭的输入流。
对我有用的唯一解决方案是使用this解决方案复制输入流。
类似的东西:
// Exception handling ommitted
InputStream originalStream = soapMessage.getContent(InputStream.class);
// Reading contents of original stream into memory
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = originalStream.read(buffer)) > -1) {
baos.write(buffer, 0, len);
}
baos.flush();
baos.close();
// Open new InputStreams using the recorded bytes
InputStream streamForThisInterceptor = new ByteArrayInputStream(baos.toByteArray());
InputStream streamForOtherInterceptors = new ByteArrayInputStream(baos.toByteArray());
// Replacing stream for other interceptors
soapMessage.setContent(InputStream.class, streamForOtherInterceptors);
糟糕的解决方案,但它是唯一有效的解决方案。
3)你也可以尝试使用Apache commons-io中的CloseShieldInputStream,也许你会有更好的运气。