Hi,

My earlier message was probably not clear enough.

This email pertains to the situation when a form uses "multipart/form-data"
as the enctype because it contains a "file" type input field needed for file
upload. My comments relate to how the DiskMultipartRequestHandler class
handles the multipart data especially when the request is forwarded from one
servlet to another.

Consider that an Action's perform method returns an ActionForward to another
Action in the same servlet. The first Action's form would have got a form
populated with all the multipart form data but the second Action's form does
not have the form data to populate the form. This is because, unlike the
request parameters, the multipart formdata is 'read-once-only' (because once
the data is read off the ServletInputStream, it is gone! It cannot be read
again).

Currently, the code to populate the form does something like this:
1. RequestUtils:populate() - decides that the incoming data is multipart
data (because the request's contentType is 'multipart/form-data' and the
method is 'post')
2. identifies the MultipartRequestHandler to process the formdata and
invokes handleRequest() on it
3. the DiskMultipartRequestHandler class's handleRequest() method
instantiates a MultiPartIterator to actually read the form data and process
it
4. when the MultiPartIterator does not find the data, it throws a
ServletException with "MultipartIterator: no multipart request data sent"

In a typical 'forward()' situation, the first Action reads and processes all
the multipart form data and passes it to the second Action via an attribute.
The second Action ignores the form object and gets the required data from
the attribute.
The current Struts implementation makes this impossible because the
exception is thrown before the second Action is called.

The solution that I propose is:
The step (4) should silently ignore the error if there is no multipart form
data instead of throwing the ServletException. And a null ActionForm object
should be given to the Action's perform() method if there was any error in
reading the multipart form data.

The Action can decide whether it is really an error condition and process
accordingly.

Comments anyone?

Thanks
Azariah

>  -----Original Message-----
> From:         Azariah Jeyakumar  
> Sent: Thursday, May 17, 2001 5:11 PM
> To:   '[EMAIL PROTECTED]'
> Cc:   Martin Cooper; '[EMAIL PROTECTED]'; Azariah Jeyakumar
> Subject:      Re: How does one forward a POST request when 
> the POST data has already been processed?
> 
> Hi,
> I am facing the exact same problem that has been described below.
> Once the first servlet has read and used up the data in the 
> request's ServletInputStream, any other JSP or servlet to 
> which the request is forwarded to will face an inconsistent 
> situtaion: The contentType, method, etc say that some POST 
> data should be expected, but there is no real POST data 
> because the upstream servlet has already read the data.
> May be the first servlet can communicate to the second 
> servlet via a special request attribute that the inputStream 
> has been read?
> In a framework environment such as struts, this is a bigger 
> problem because the second servlet (which is comprised of 
> ActionServlet, RequestUtils, DiskMultipartRequestHandler, 
> MultipartIterator classes) has no generalized way of knowing 
> that the request's input stream has been read already and 
> Struts tries to process direct requests from the browser in 
> the same way as forwarded requests.
> Thanks
> Azariah
> 
> Re: How does one forward a POST request when the POST data 
> has al read y been processed?
> 
        > * From: Duane Morse 
        > * Subject: Re: How does one forward a POST request when the 
        >   POST data has al read y been processed? 
        > * Date: Thu, 30 Nov 2000 09:20:33 -0800 
> 
> That's exactly what's happening, which is the reason for my 
> question.  If
> one
> wants to separate business processing from presentation, 
> using servlets and
> EJBs
> for the former and JSPs for the latter, then how does one 
> dispatch to the
> JSP
> when the data the JSP needs is in special request attributes? 
>  My JSP is
> making
> no calls to retrieve form variables, but apparently Tomcat 
> 3.2b8 is trying
> to set
> things up so it could -- since the servlet has already 
> processed the input,
> that's
> an error.  So is there NO way to divide the labor in this 
> fashion?  How do
> you
> EVER have servlets (and JSPs) pass work among themselves if 
> the framework is
> going
> to do this sort of thing?  The first time a servlet opens the 
> input stream
> and
> reads the POST data, all subsequent servlets and JSPs are screwed.
> 
> -----Original Message-----
> From: Albert Wong [<mailto:[EMAIL PROTECTED]>]
> Sent: Wednesday, November 29, 2000 5:06 PM
> To: [EMAIL PROTECTED]
> Subject: Re: How does one forward a POST request when the 
> POST data has
> al read y been processed?
> 
> 
> Typically information to be displayed by the JSP is 
> communicated via the
> ServletRequest.setAttribute and the RequestDispatcher.  For example,
> ServletA performs the business logic and stores the results using
> setAttribute(java.lang.String name, java.lang.Object o), and 
> the servlet or
> jsp retreives the information using 
> getAttribute(java.lang.String name).
> 
> If your servlet performing the business logic already called
> ServletResponse.getOutputStream() or 
> ServletResponse.getWriter() before
> calling RequestDispatcher.forward then that might explain the 
> behavior your
> experiencing with Tomcat (it's not allowed by the Servlet Spec).
> 
> 
> -----Original Message-----
> From: Duane Morse [<mailto:[EMAIL PROTECTED]>]
> Sent: Wednesday, November 29, 2000 3:27 PM
> To: [EMAIL PROTECTED]
> Subject: How does one forward a POST request when the POST data has
> alread y been processed?
> 
> 
> I ran into a problem with the Tomcat 3.2-b8 release, and it 
> has implications
> beyond the Tomcat
> implementation; hence my posting here.
> 
> I have a servlet which processes a form which uses the POST 
> method, and it
> forwards the request
> to another servlet (in this case,  a JSP) after adding a data 
> structure to
> the request object which
> the target servlet should use to format the response page.  
> This is your
> classic "let JSP handle
> the presentation" mode of operations.  Since the real 
> response data is in my
> own data object,
> the target servlet ignores the original input.  Tomcat's 
> problem with this
> is that it apparently tries to
> prepare the target for processing POST data, but the data has 
> already been
> read, so it gets a
> "short data" error (i.e., CONTENT_LENGTH is n, but the number 
> of data bytes
> in the stream is 0).
> 
> I can't see any way of changing the method type or the 
> content length in the
> request object before
> forwarding it.  How should I invoke a servlet in a manner that doesn't
> potentially confuse the servlet container?
> 
> Duane Morse, Eldorado Computing Inc., Phoenix AZ
> 

Reply via email to