2013-10-02 66 views
3

我有一個奇怪的問題,似乎無法得到它的底部。基本上需要記錄正在發送到web服務並接收(消費者)的soap XML。我相信正確的方法是使用Apache提供的開箱即用攔截器。這些工作很好,但我們有一個特殊的情況,一個方法接受大量的參數/對象並返回大量的參數/對象,這些參數/對象顯然會創建一個大的soap請求/響應xml。 SOAP請求/響應總是被正確地打印然而被拋出下面的錯誤:當在JaxWSClient上啓用LoggingInInterceptor時出現「流被關閉」錯誤

Application配置

Spring配置:

<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

你用過AbstractSoapInterceptor嗎? –

回答

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,也許你會有更好的運氣。