users@jax-ws.java.net

Problems with JAX-WS2.1 / Out of Memory - possible Solution

From: Christian Bomhardt <christian.bomhardt_at_etu.uni-karlsruhe.de>
Date: Wed, 25 Apr 2007 17:59:29 +0200

Hello,

I'm using JAX-WS 2.1
( <project name="JAX-WS 2.1.1 RC1 RI On Sun Java System App Server
8.1/8.2/9.0/9.0 U1, GF v1, GF v2 M1, M2" default="help" basedir=".">)

and have lot's of trouble uploading large (>2GB, but already stalls at
300 MB) files:

I receive a OutOfMemory-Exception:

Here's my server and client code, my analysis of the problem follows:

Client Code:
try
     {
     PlayoutBackendService service = new PlayoutBackendService();
     //
     PlayoutServer pServer = service.getPlayoutServerPort();

     SOAPBinding
binding=(SOAPBinding)((BindingProvider)pServer).getBinding();

//enable chunking - the problem is not better without chunking !
((BindingProvider)pServer).getRequestContext().put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE,8196);
     System.out.println("Is MTOM enabled? "+binding.isMTOMEnabled());

     if (pServer==null)
     {
     System.out.println("TEST FAILURE: Couldnt get port!");
     System.exit(-1);
     }
     System.out.println("befor Upload");
     pServer.uploadTest(new MyDataHandler(new
FileDataSource("name_of_large_file"))); //MyDataHandler is just a
wrapper with every method overwritten with
system.out.println([methodname]) super(...) to see what's going on
during file transfer over the wire - a regular DataHandler yields the
same results
     System.out.println("after upload");
     }
catch (Exception ex)
     {
     System.out.println("Error!");
     ex.printStackTrace();
     }
System.out.println("Done!");
System.exit(3);


Here is my Server code:
@WebMethod
public boolean uploadTest(@WebParam(name="dHandler")
     @XmlAttachmentRef()
     DataHandler data)
{
try
     {
     InputStream is = data.getInputStream();

     // Open a file output stream to recieve the data.
     FileOutputStream fos = new FileOutputStream(new File("c:/upload.txt"));

     // Create a 2k buffer to use by default.
     byte[] buffer = new byte[1024];

     // Determine the number of bytes available.
     int available = is.available();

     // Loop until no more bytes are avialable.
     while (available > 0)
     {
     // Resize the buffer as needed.
     if (available < buffer.length)
         {
         buffer = new byte[available];
         }

     // Read the data into the buffer.
     is.read(buffer);

     // Write the data to the file.
     fos.write(buffer);

     // Get the number of bytes available.
     available = is.available();
     }
     fos.close();
     System.out.println("Transfer done.");
     }
catch (Exception ex)
     {
     System.out.println("Exce: " + ex.toString());
     }

return false;
}



My Analysis: everything runs fine, Fiber.__doRun(Tube) is executed,
HttpTransportPipe.process(Packet) is called,
SwACodec(MimeCodec).encode is called - here the Problems start, as far
as I think: the attachment stream should be send without encoding, right?

At least, SwaCodec calls DataHandlerAttachment.writeTo, here
DataHandlerAttachment.asByteArray is called, (for obvious reasons)
resulting in Out of Memory....

Please, tell me, am I doing something wrong or is the implementation not
perfect? I thought, the datahandler has to stream has bytes directly out
to the http connection, thus that only a limited amount of bytes has to
be kept in memory and the complete stream never has to be read.

Thanks a lot!

Christian