2

I'm trying to use <p:fileUpload> to upload a file. Here's the view:

  <h:form enctype="multipart/form-data">
     <p:growl id="messages" showDetail="true" />
     <p:fileUpload
                fileUploadListener="#{viewscopedBean.handleFileUpload}"
                mode="advanced" dragDropSupport="true" multiple="true"
                update="messages" />
  </h:form>

Bean:

@ManagedBean
@ViewScoped
public class ViewscopedBean implements Serializable{
    private List<UploadedFile> uploadedFiles; //to remember which files have been uploaded

    public ViewscopedBean() {
            super();
            System.out.println("@constructor");
            uploadedFiles = new ArrayList<UploadedFile>();
    }

    public void handleFileUpload(FileUploadEvent event) { 
           System.out.println("! HANDLE FILE UPLOAD !");
           // do something
    }  
    public List<UploadedFile> getUploadedFiles() {
            return uploadedFiles;
    }

    public void setUploadedFiles(List<UploadedFile> uploadedFiles) {
            this.uploadedFiles = uploadedFiles;
    }
} 

web.xml

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>
        org.primefaces.webapp.filter.FileUploadFilter
    </filter-class>
    <init-param>
        <param-name>thresholdSize</param-name>
        <param-value>512000</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

When I click on the upload button, the progressbar is filling up to 100% (like it does something), but then the page is reloaded (constructor is being called for every uploaded file) - the handleFileUpload method is never called.

There aren't any errors or warnings, it just doesn't do what it should. I have JSF 2.0 and use Primefaces 4, maybe there is a problem?

How is this caused and how can I solve it?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Niko
  • 1,054
  • 5
  • 25
  • 52

1 Answers1

2

First things first, ensure that you have commons-fileupload and its compile-time dependency commons-io on your classpath. The handler not being called suggests that you have these dependencies missing.

Since 4.0, there is now an optional context-param which specifies the server-side engine for handling FileUpload uploads:

<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>auto|native|commons</param-value>
</context-param>

In the absence of the context-param, PrimeFaces otherwise selects the most appropriate uploader engine by detection.

Given that you are not using JSF 2.2, this means that it will first select auto, and therefore will redirect to use commons.

So you can see how important it is that you have commons-fileupload and commons-io in your project.

When I copied and pasted your code into a Primefaces 3.5 project containing these dependencies, your code worked for me. The constructor was called once and only once, and the handle method was called each time I uploaded a file.

I repeated the test using 4.0 and again, the constructor was called once and only once.

Here's the configuration that I used in web.xml (needed by commons-fileupload):

<filter>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>

Here's the backing bean:

package uk;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;

    @ManagedBean(name = "tempBean")
    @ViewScoped
    public class TempBean {

        private List<UploadedFile> uploadedFiles; //to remember which files have been uploaded

        public TempBean() {
                super();
                System.out.println("@constructor");
                uploadedFiles = new ArrayList<UploadedFile>();
        }

        public void handleFileUpload(FileUploadEvent event) { 
               System.out.println("! HANDLE FILE UPLOAD !");
               // do something
        }  
        public List<UploadedFile> getUploadedFiles() {
                return uploadedFiles;
        }

        public void setUploadedFiles(List<UploadedFile> uploadedFiles) {
                this.uploadedFiles = uploadedFiles;
        }

    }

Here's the page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions">

<h:body>

    <h:form enctype="multipart/form-data">
     <p:growl id="messages" showDetail="true" />
     <p:fileUpload
                fileUploadListener="#{tempBean.handleFileUpload}"
                mode="advanced" dragDropSupport="true" multiple="true"
                update="messages" />
  </h:form>
</h:body>
</html>

And finally here is the snippet of my POM that contains the dependencies and versions for Apache Commons:

<dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3</version>
    </dependency>
8bitjunkie
  • 12,793
  • 9
  • 57
  • 70
  • 1
    hi, great tip; the problem with ajax was solved by setting primefaces.UPLOADER to common. But one problem stays: when I upload e.g. 3 files, the handleFileUpload works correctly, but the array list just contains one value (like the other two are discarded). do you know why? – Niko Nov 24 '13 at 14:01
  • @Niko the listener is called once per uploaded file. – 8bitjunkie Nov 25 '13 at 13:27
  • 1
    yep, thats true. but why does the list only contain ONE value when I upload three files (handleupload is invoked 3 times)? is this an ajax issue that it loses its state? – Niko Nov 30 '13 at 13:02