简体   繁体   English

从JAX-WS服务返回大文件

[英]Return large file from JAX-WS service

I'm trying to return large file from JAX-WS service method, but getting strange client error. 我正在尝试从JAX-WS服务方法返回大文件,但出现奇怪的客户端错误。 Here is my code: 这是我的代码:

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

Implementation: 实现方式:

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 returns DataHandler with zipped data. getWorkArch返回带有压缩数据的DataHandler。 Here is client code: 这是客户端代码:

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

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

And when I'm trying to run it, I'm getting errors. 当我尝试运行它时,我遇到了错误。 Here is server stack trace: 这是服务器堆栈跟踪:

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)

And here is client stack trace: 这是客户端堆栈跟踪:

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)

What's wrong? 怎么了?

EDIT : Here is hosting code in my Main class: 编辑 :这是我的主类中的托管代码:

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

Client is runned with default MacOS java 6 settings. 客户端使用默认的MacOS Java 6设置运行。 I'm trying to download 400Mb file, and without TOM enabled, the server fell with OutOfMemory error. 我正在尝试下载400Mb文件,并且在未启用TOM的情况下,服务器因OutOfMemory错误而掉线。

Here are some suggestions and observations: 以下是一些建议和观察结果:

  1. Broken pipe exception is thrown when the server is responding to the client but client connection terminates midway . 服务器响应客户端但客户端连接中途终止时,将引发Broken pipe异常。
  2. This is quite obvious as your client crashed with out of memory error and its not able to handle the amount of data received from the server with the given heap-size (I see you are trying to hold the data in byte array.). 这非常明显,因为您的客户端崩溃时出现了内存不足错误,并且无法使用给定的堆大小来处理从服务器接收的数据量(我看到您正在尝试将数据保存在字节数组中。)。
  3. One and quickest solution is to increase the heap-size of the client VM to appropriate value. 一种最快的解决方案是将客户端VM 的堆大小增加到适当的值。
  4. Other and more practical option ( provided your use case entertains this ) is to stream the data in a persistent location (eg a file). 其他更实际的选择( 假设您的用例可以满足要求 )是在持久位置(例如文件) 中流式传输数据。 This way the entire data will not be loaded in the memory 这样,整个数据将不会加载到内存中

EDIT: 编辑:

If you check the documentation. 如果您检查文档。 There a StreamingDataHandler class which can be used to stream the data. 有一个StreamingDataHandler类,可用于流数据。 This this particular link . 这个特别的链接 There is a subtopic called Streaming SOAP Attachments . 有一个名为Streaming SOAP Attachments的子主题。 It gives and example of large file download, very close to your use case. 它提供了一个大文件下载的示例,非常接近您的用例。 I think you only need to change the client side code and use StreamingDataHandler instead of DataHandler 我认为您只需要更改客户端代码并使用StreamingDataHandler而不是DataHandler

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM