jsffile-uploadseamjsf-1.2seam2

enctype="multipart/form-data" does not submit data with Seam multipart-filter


Ever since I add the following config to the components.xml to customize an editor plugin, every form with enctype="multipart/form-data" in my app does not submit data. I can't find any source saying that this is conflicting.

    <web:multipart-filter create-temp-files="true"
                  max-request-size="1000000" 
                  url-pattern="*" />

I'm working with Seam 2.2.2 and Jsf 1.2

Update: I thought I could stop using forms with enctype="multipart/form-data". But I can't. I need some help and there goes more info.

First: the problem above only aplies to a4j forms and a4j commandButtons. As I said before, I add the above web:multipart-filter config at components.xml to make this editor plugin works (which is done via apache commons ServletFileUpload). I was taking the enctype config off the project forms to make everything work but there is one scenario that it was not possible. When I have to upload an image. But when I use url-pattern="*.seam":

<web:multipart-filter create-temp-files="true"
                  max-request-size="1000000" 
                  url-pattern="*.seam" />

Then the upload works, but the ServletFileUpload doesn't. If I don't use any web:multipart-filter this also occurs. (image upload ok, and plugin fails)

Now it is like this:

<h:form id="editPhoto" enctype="multipart/form-data">   

        <div id="photoAttribute" class="attribute-relationship spacer-top-bottom">
            <div class="label">
                <h:outputText>#{messages['person.photo.alter']} </h:outputText>
            </div>
            <s:fileUpload id="photoPerson" 
                    data="#{person.profilePhoto}" 
                    fileName="#{person.profilePhotoName}" 
                    fileSize="#{person.profilePhotoSize}"
                    accept="images/*">
            </s:fileUpload>
        </div>

        <h:commandButton id="editPersonButtonTop" 
            value="#{messages['button.savePhoto']}" 
            action="#{personController.prepareSavePhoto(person)}" 
            styleClass="button btn-info"  
            onclick="showAjaxStatus()"/>
</h:form>

It seems I am missing some ajax config here but I can't tell what it is. And also Why can't I have both the ServletFileUpload and the image upload together?

The ServletFileUpload is from commons-fileupload-1.3.1, and it works like this:

List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
processItems(items);
saveOpenAttachment();
...

private void processItems(List<FileItem> items)
{
    // Process the uploaded items
    Iterator<FileItem> iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = iter.next();

        if (!item.isFormField()) 
        {
            processUploadedFile(item);
        }
    }

}

private void processUploadedFile(FileItem item)
{
    setFileName(FilenameUtils.getName(item.getName()));
    try
    {
        InputStream fileContent = item.getInputStream();
        byte[] bytes = IOUtils.toByteArray(fileContent);
        setFileData(bytes);
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    setFileContentType(item.getContentType());
}

I appreciate if somebody can tell how I manage to make ServletFileUpload works with the previous components config or How to have the form to submit the data.

My components.xml:

<core:init debug="true" jndi-pattern="@jndiPattern@"/>

<web:rewrite-filter view-mapping="*.seam"/> 

<web:multipart-filter create-temp-files="true"  
                  max-request-size="1024000" url-pattern="*.seam"/> 

<core:manager concurrent-request-timeout="10000" 
             conversation-timeout="3720000" 
             conversation-id-parameter="cid"
             parent-conversation-id-parameter="pid"
             default-flush-mode="MANUAL"/>

<persistence:managed-persistence-context name="entityManager"
                                 auto-create="true"
                  persistence-unit-jndi-name="java:/SinapseEntityManagerFactory"/>                          

<security:identity authenticate-method="#{authenticatorContext.authenticate}" remember-me="true" />

<international:time-zone-selector time-zone-id="GMT-3"/>
<international:locale-selector name="defaultLocale" locale-string="pt" scope="application" />
<international:locale-selector locale-string="pt" />

<event type="org.jboss.seam.security.notLoggedIn">
    <action execute="#{redirect.captureCurrentView}"/>
</event>
<event type="org.jboss.seam.security.postAuthenticate">
    <action execute="#{redirect.returnToCapturedView}"/>
</event>

<async:quartz-dispatcher/>  

<cache:jboss-cache-provider configuration="ehcache.xml" />
<transaction:ejb-transaction/>

Solution

  • To solve my problem, I changed the apache-commons FileUpload solution to handle the request like Seam multipart filter does:

    ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    try
    {
      if (!(request instanceof MultipartRequest))
      {
         request = unwrapMultipartRequest(request);
      }
    
      if (request instanceof MultipartRequest)
      {
         MultipartRequest multipartRequest = (MultipartRequest) request;
    
         String clientId = "upload";
         setFileData(multipartRequest.getFileBytes(clientId));
         setFileContentType(multipartRequest.getFileContentType(clientId));
         setFileName(multipartRequest.getFileName(clientId));
         saveOpenAttachment();
      }
    }
    

    This way, I could take off the web:multipart-filter config that was breaking the other requests.