users@jersey.java.net

Re: [Jersey] Changing jersey-multipart to not use JavaMail

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 17 Mar 2009 17:34:25 +0100

On Mar 17, 2009, at 2:30 PM, Paul Sandoz wrote:

>
> On Mar 16, 2009, at 3:07 PM, Craig McClanahan wrote:
>
>> Paul Sandoz wrote:
>>> Hi,
>>>
>>> When using jersey-multipart we are getting out of memory issues
>>> because JavaMail buffers [1].
>>>
>>> I have been looking at the MIMEPull API [2]. It is a clean and
>>> simple API that supports pull-based streaming of body parts (if
>>> accessed in the serialized order) or buffering to disk.
>>>
>>> Craig has also proposed using Mime4J [3]. This API is a push-
>>> based streaming API, e.g. like SAX where as MIMEPull is like StAX.
>>> The last stable release of Mime4j is version 0.6
>>>
>>> From a quick look at both APIs i prefer the pull model of MIMEPull
>>> rather than the push model of Mime4J. The former makes it much
>>> easier to integrate into the existing code base.
>>>
>>> In addition to switching from JavaMail for parsing i propose that
>>> while we do that work we implement support for @FormDataParam for
>>> getting access to MIME body parts and deprecate the use of
>>> @FormParam.
>>>
>> I agree with your preference and the suggested approach. Pull will
>> definitely be easier to work with.
>>
>
> I have started work on this. Which has led to an "interesting" bug
> with the Client API not pushing out the correct content type set by
> the multipart writer (it looks like JavaMail is very forgiving when
> parsing where as MIMEPull requires a boundary string).
>

I have just committed the following:

  - Switched from JavaMail to MIMEPull. I changed the constructor of
BodyPartEntity to take a MIMEPart instance.
    Because MIMEPull caches to disk the code of BodyPartEntity is now
simplified. I decided to retain
    BodyPartEntity just in case we need to make changes to the
underlying MIME implementation in the future.

- The MultiPartReader now uses the CloseableService, available on the
server-side. Instances of MultiPart
   are added and are closed when the request goes out of scope. So
there is no need for developers to
   explicitly call "cleanup".

- It is now possible to directly return a MultiPart instance that was
obtained as a request entity,
   for example:

     @Consumes("multipart/mixed")
     @Produces("multipart/mixed")
     public MultiPart twelve(MultiPart multiPart) {
         return multiPart;
     }


Next steps:

- we should probably bump up the default in-memory threshold size from
4K. MIMEPull has a much higher
   default value, 1 meg, per attachment.

- Support @FormDataParam.

Paul.