2013-03-11 5 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) 

Что случилось?

EDIT: Вот хостинг кода в моем главном классе:

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

Клиента запущенный с присвоенным MacOS Java 6 настроек. Я пытаюсь загрузить файл 400 Мб, и без включения TOM сервер упал с ошибкой OutOfMemory.

+0

Что такое среда исполнения JAX-WS? Как насчет памяти для вашего клиента? Массив байтов может содержать полный файл? –

+0

См. Edit, Я добавил некоторую информацию – skayred

+0

Мне всегда нравится проверять, что она использует MTOM с помощью Wireshark, из-за того, что клиент и сервер должны согласиться на ее использование. Как показано ниже, вы также можете сказать клиенту использовать больше кучи. – davidfmatheson

ответ

3

Вот некоторые предложения и замечания:

  1. Broken pipe исключение, когда сервер отвечает клиенту, но соединение клиента заканчивается на полпути.
  2. Это совершенно очевидно, так как ваш клиент разбился с ошибкой памяти и не смог обработать объем данных, полученных с сервера с заданным размером кучи (я вижу, что вы пытаетесь хранить данные в массиве байтов.).
  3. 1 и самый быстрый решение - увеличить размер кучи клиента VM на соответствующее значение.
  4. Другие и более практичные варианты (при условии, что ваш случай использования развлекает это) является для передачи данных в постоянном местоположении (например, файл). Таким образом, все данные не будут загружены в память

EDIT:

Если вы обратитесь к документации. Там есть класс StreamingDataHandler, который может использоваться для потоковой передачи данных. Это this particular link. Существует подтема под названием Streaming SOAP Attachments. Он дает и пример большой загрузки файлов, очень близко к вашему прецеденту. Мне кажется, вам нужно только изменить код на стороне клиента и использовать StreamingDataHandler вместо DataHandler

+0

Можете ли вы привести несколько примеров потоковой передачи? Я попытался сделать это в этих образцах кода. Кроме того, размер файла может быть различным - даже несколько гигабайт. – skayred

+0

Я отредактировал свой ответ. Пожалуйста, проверьте. – Santosh

+0

Я изменил свой код, как написано в статье, но все равно получаю OutOfMemory на клиенте :( – skayred