2013-03-11 34 views
0

我試圖從JAX-WS服務方法返回大文件,但得到奇怪的客戶端錯誤。這裏是我的代碼:從JAX-WS服務返回大文件

@WebService(targetNamespace = "http://java.CAEServer", portName = "CAEInstance") 
public interface Instance { 
    @WebMethod(action = "http://java.CAEServer/getResultsArch") 
    DataHandler getResultsArch(org.caebeans.caeserver.Instance instance); 
} 

實現:

MTOM(enabled = true, threshold = 2048) 
@BindingType(SOAPBinding.SOAP11HTTP_MTOM_BINDING) 
@StreamingAttachment(parseEagerly=true, memoryThreshold=4000L) 
@WebService(endpointInterface = "org.caebeans.wsrf.Instance") 
public class InstanceImpl implements Instance { 
    @Override 
    public DataHandler getResultsArch(org.caebeans.caeserver.Instance instance) { 
     try { 
      return workStorageManager.getWorkPackage(instance.getId()); 
     } catch (Exception e) { 
      logger.fatal("Failed to zip work", e); 
      throw new RuntimeException("Failed to zip results"); 
     } 
    } 
} 

getWorkArch與壓縮數據返回的DataHandler。這裏是客戶端代碼:

Instance instanceTransport = new InstanceImplService().getInstanceImplPort(); 
SOAPBinding binding = (SOAPBinding) ((BindingProvider) instanceTransport).getBinding(); 
binding.setMTOMEnabled(true); 

byte[] resultArch = instanceTransport.getResultsArch(instance); 

而當我試圖運行它,我得到錯誤。這裏是服務器堆棧跟蹤:

java.io.IOException: Broken pipe 
at sun.nio.ch.FileDispatcher.write0(Native Method) 
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:29) 
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:69) 
at sun.nio.ch.IOUtil.write(IOUtil.java:40) 
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:336) 
at sun.net.httpserver.Request$WriteStream.write(Request.java:397) 
at sun.net.httpserver.ChunkedOutputStream.writeChunk(ChunkedOutputStream.java:108) 
at sun.net.httpserver.ChunkedOutputStream.write(ChunkedOutputStream.java:77) 
at sun.net.httpserver.PlaceholderOutputStream.write(ExchangeImpl.java:390) 
at com.sun.xml.internal.ws.transport.http.server.ServerConnectionImpl$2.write(ServerConnectionImpl.java:163) 
at javax.activation.DataHandler.writeTo(DataHandler.java:294) 
at com.sun.xml.internal.ws.encoding.MtomCodec$ByteArrayBuffer.write(MtomCodec.java:189) 
at com.sun.xml.internal.ws.encoding.MtomCodec.encode(MtomCodec.java:156) 
at com.sun.xml.internal.ws.encoding.SOAPBindingCodec.encode(SOAPBindingCodec.java:249) 
at com.sun.xml.internal.ws.transport.http.HttpAdapter.encodePacket(HttpAdapter.java:328) 
at com.sun.xml.internal.ws.transport.http.HttpAdapter.access$100(HttpAdapter.java:82) 
at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:470) 
at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:233) 
at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(WSHttpHandler.java:95) 
at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(WSHttpHandler.java:80) 
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65) 
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:65) 
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68) 
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:557) 
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65) 
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:529) 
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:680) 

,這裏是客戶端堆棧跟蹤:

xception in thread "main" java.lang.OutOfMemoryError: Java heap space 
at com.sun.xml.internal.org.jvnet.staxex.ByteArrayOutputStreamEx.readFrom(ByteArrayOutputStreamEx.java:60) 
at com.sun.xml.internal.org.jvnet.staxex.Base64Data.get(Base64Data.java:225) 
at com.sun.xml.internal.org.jvnet.staxex.Base64Data.length(Base64Data.java:266) 
at com.sun.xml.internal.ws.encoding.MtomCodec$MtomXMLStreamReaderEx.getTextCharacters(MtomCodec.java:508) 
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleCharacters(StAXStreamConnector.java:312) 
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:176) 
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:351) 
at com.sun.xml.internal.bind.v2.runtime.BridgeImpl.unmarshal(BridgeImpl.java:109) 
at com.sun.xml.internal.bind.api.Bridge.unmarshal(Bridge.java:222) 
at com.sun.xml.internal.ws.client.sei.ResponseBuilder$DocLit.readResponse(ResponseBuilder.java:514) 
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:110) 
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78) 
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107) 
at $Proxy31.getResultsArch(Unknown Source) 
at Main.main(Main.java:73) 

有什麼不對?

編輯:這裏是我的主類的託管代碼:

Endpoint instanceEndpoint = Endpoint.publish(serverHost + INSTANCE_PATH, instance); 

客戶端的默認MacOS的Java 6中設置拼命地跑。我試圖下載400Mb文件,並且沒有啓用TOM,服務器崩潰時發生OutOfMemory錯誤。

+0

什麼是JAX-WS運行時?你的客戶的記憶呢?字節數組可能包含完整的文件? – 2013-03-11 14:54:05

+0

請參閱編輯,我已經添加了一些信息 – skayred 2013-03-11 15:12:00

+0

由於客戶端和服務器必須同意使用Wireshark,我總是希望驗證它是否使用MTOM。如下所示,您還可以告訴客戶端使用更多的堆空間。 – davidfmatheson 2013-03-11 15:38:45

回答

3

這裏有一些建議和意見:當服務器響應客戶端,但客戶端連接中途終止

  1. Broken pipe拋出異常。
  2. 這是非常明顯的,因爲你的客戶端因內存不足錯誤而崩潰,並且它無法處理從給定堆大小的服務器接收到的數據量(我看到你試圖將數據保存在字節數組中。 )。
  3. 一和最快解決方法是將增加客戶端VM的堆大小到適當的值。
  4. 其他更實際的選擇(提供您的使用案例招待這)是在持久的位置(例如文件)以流數據。這樣,整個數據不會在內存中加載

編輯:

如果您查看文檔。有一個StreamingDataHandler類可用於流式傳輸數據。這this particular link。有一個子主題叫做流式SOAP附件。它給出了大文件下載的例子,非常接近你的用例。 我認爲你只需要更改客戶端代碼並使用StreamingDataHandler而不是DataHandler

+0

你能提供一些流式的例子嗎?我已經嘗試在這些代碼示例中執行此操作。此外,文件大小可以是多種 - 甚至幾個gy。 – skayred 2013-03-11 15:28:54

+0

我已經編輯我的答案。請檢查。 – Santosh 2013-03-11 15:42:29

+0

我已經改變了我的代碼寫的文章,但客戶仍然得到內存溢出:( – skayred 2013-03-12 13:41:17