I'm trying to upload a file using PrimeFaces, but the fileUploadListener method isn't being invoked after the upload finishes.
Here is the view:
<h:form>
<p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload}"
mode="advanced"
update="messages"
sizeLimit="100000"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>
<p:growl id="messages" showDetail="true"/>
</h:form>
And the bean:
#ManagedBean
#RequestScoped
public class FileUploadController {
public void handleFileUpload(FileUploadEvent event) {
FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
I've placed a breakpoint on the method, but it's never called. When using mode="simple" and ajax="false", it is been invoked, but I want it to work in the advanced mode. I'm using Netbeans and Glassfish 3.1.
How to configure and troubleshoot <p:fileUpload> depends on PrimeFaces and JSF version.
All PrimeFaces versions
The below requirements apply to all PrimeFaces versions:
The enctype attribute of the <h:form> needs to be set to multipart/form-data. When this is absent, the ajax upload may just work, but the general browser behavior is unspecified and dependent on form composition and webbrowser make/version. Just always specify it to be on the safe side.
When using mode="advanced" (i.e. ajax upload, this is the default), then make sure that you've a <h:head> in the (master) template. This will ensure that the necessary JavaScript files are properly included. This is not required for mode="simple" (non-ajax upload), but this would break look'n'feel and functionality of all other PrimeFaces components, so you don't want to miss that anyway.
When using mode="simple" (i.e. non-ajax upload), then ajax must be disabled on any PrimeFaces command buttons/links by ajax="false", and you must use <p:fileUpload value> with <p:commandButton action> instead of <p:fileUpload listener>.
So, if you want (auto) file upload with ajax support (mind the <h:head>!):
<h:form enctype="multipart/form-data">
<p:fileUpload listener="#{bean.upload}" auto="true" /> // For PrimeFaces version older than 8.x this should be fileUploadListener instead of listener.
</h:form>
public void upload(FileUploadEvent event) {
UploadedFile uploadedFile = event.getFile();
String fileName = uploadedFile.getFileName();
String contentType = uploadedFile.getContentType();
byte[] contents = uploadedFile.getContents(); // Or getInputStream()
// ... Save it, now!
}
Or if you want non-ajax file upload:
<h:form enctype="multipart/form-data">
<p:fileUpload mode="simple" value="#{bean.uploadedFile}" />
<p:commandButton value="Upload" action="#{bean.upload}" ajax="false" />
</h:form>
private transient UploadedFile uploadedFile; // +getter+setter
public void upload() {
String fileName = uploadedFile.getFileName();
String contentType = uploadedFile.getContentType();
byte[] contents = uploadedFile.getContents(); // Or getInputStream()
// ... Save it, now!
}
Do note that ajax-related attributes such as auto, allowTypes, update, onstart, oncomplete, etc are ignored in mode="simple". So it's needless to specify them in such case.
Also note that the UploadedFile property is declared transient just to raise awareness that this is absolutely not serializable. The whole thing should be placed in a request scoped bean instead of a view or even session scoped one. If this is the case, then you can safely remove the transient attribute.
Also note that you should immediately read and save the file contents inside the abovementioned methods and not in a different bean method invoked by a later HTTP request. This is because technically speaking the uploaded file contents is request scoped and thus unavailable in a later/different HTTP request. Any attempt to read it in a later request will most likely end up with java.io.FileNotFoundException on the temporary file and only cause confusion.
PrimeFaces 8.x or newer
Configuration is identical to the 5.x version info below, but if your listener is not called, check if the method attribute is called listener and not fileUploadListener like as in versions before 8.x.
PrimeFaces 5.x
This does not require any additional configuration if you're using at least JSF 2.2 and your faces-config.xml is also declared conform at least JSF 2.2 version. You do not need the PrimeFaces file upload filter at all and you also do not need the primefaces.UPLOADER context parameter in web.xml. In case it's unclear to you how to properly install and configure JSF depending on the target server used, head to How to properly install and configure JSF libraries via Maven? and "Installing JSF" section of our JSF wiki page.
If you're however not using JSF 2.2 yet and you can't upgrade JSF 2.0/2.1 to 2.2 yet (should be effortless though when already on a Servlet 3.0 compatible container), then you need to manually register the below PrimeFaces file upload filter in web.xml (it will parse the multi part request and fill the regular request parameter map so that FacesServlet can continue working as usual):
<filter>
<filter-name>primeFacesFileUploadFilter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
</filter-mapping>
The <servlet-name> value of facesServlet must match exactly the value in the <servlet> entry of the javax.faces.webapp.FacesServlet in the same web.xml. So if it's e.g. Faces Servlet, then you need to edit it accordingly to match.
PrimeFaces 4.x
The same story as PrimeFaces 5.x applies on 4.x as well.
There's only a potential problem in getting the uploaded file content by UploadedFile#getContents(). This will return null when native API is used instead of Apache Commons FileUpload. You need to use UploadedFile#getInputStream() instead. See also How to insert uploaded image from p:fileUpload as BLOB in MySQL?
Another potential problem with native API will manifest is when the upload component is present in a form on which a different "regular" ajax request is fired which does not process the upload component. See also File upload doesn't work with AJAX in PrimeFaces 4.0/JSF 2.2.x - javax.servlet.ServletException: The request content-type is not a multipart/form-data.
Both problems can also be solved by switching to Apache Commons FileUpload. See PrimeFaces 3.x section for detail.
PrimeFaces 3.x
This version does not support JSF 2.2 / Servlet 3.0 native file upload. You need to manually install Apache Commons FileUpload and explicitly register the file upload filter in web.xml.
You need the following libraries:
commons-fileupload.jar
commons-io.jar
Those must be present in the webapp's runtime classpath. When using Maven, make sure they are at least runtime scoped (default scope of compile is also good). When manually carrying around JARs, make sure they end up in /WEB-INF/lib folder.
The file upload filter registration detail can be found in PrimeFaces 5.x section here above. In case you're using PrimeFaces 4+ and you'd like to explicitly use Apache Commons FileUpload instead of JSF 2.2 / Servlet 3.0 native file upload, then you need next to the mentioned libraries and filter also the below context param in web.xml:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>
Troubleshooting
In case it still doesn't work, here are another possible causes unrelated to PrimeFaces configuration:
Only if you're using the PrimeFaces file upload filter: There's another Filter in your webapp which runs before the PrimeFaces file upload filter and has already consumed the request body by e.g. calling getParameter(), getParameterMap(), getReader(), etcetera. A request body can be parsed only once. When you call one of those methods before the file upload filter does its job, then the file upload filter will get an empty request body.
To fix this, you'd need to put the <filter-mapping> of the file upload filter before the other filter in web.xml. If the request is not a multipart/form-data request, then the file upload filter will just continue as if nothing happened. If you use filters that are automagically added because they use annotations (e.g. PrettyFaces), you might need to add explicit ordering via web.xml. See How to define servlet filter order of execution using annotations in WAR
Only if you're using the PrimeFaces file upload filter: There's another Filter in your webapp which runs before the PrimeFaces file upload filter and has performed a RequestDispatcher#forward() call. Usually, URL rewrite filters such as PrettyFaces do this. This triggers the FORWARD dispatcher, but filters listen by default on REQUEST dispatcher only.
To fix this, you'd need to either put the PrimeFaces file upload filter before the forwarding filter, or to reconfigure the PrimeFaces file upload filter to listen on FORWARD dispatcher too:
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
There's a nested <h:form>. This is illegal in HTML and the browser behavior is unspecified. More than often, the browser won't send the expected data on submit. Make sure that you are not nesting <h:form>. This is completely regardless of the form's enctype. Just do not nest forms at all.
If you're still having problems, well, debug the HTTP traffic. Open the webbrowser's developer toolset (press F12 in Chrome/Firebug23+/IE9+) and check the Net/Network section. If the HTTP part looks fine, then debug the JSF code. Put a breakpoint on FileUploadRenderer#decode() and advance from there.
Saving uploaded file
After you finally got it to work, your next question shall probably be like "How/where do I save the uploaded file?". Well, continue here: How to save uploaded file in JSF.
You are using prettyfaces too? Then set dispatcher to FORWARD:
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
One point I noticed with Primefaces 3.4 and Netbeans 7.2:
Remove the Netbeans auto-filled parameters for function handleFileUpload i.e. (event) otherwise event could be null.
<h:form>
<p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload(event)}"
mode="advanced"
update="messages"
sizeLimit="100000"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>
<p:growl id="messages" showDetail="true"/>
</h:form>
Looks like javax.faces.SEPARATOR_CHAR must not be equal to _
Putting p:fileUpload inside a h:form solved the problem at my case.
I had same issue with primefaces 5.3 and I went through all the points described by BalusC with no result. I followed his advice of debugging FileUploadRenderer#decode() and I discovered that my web.xml was unproperly set
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>auto|native|commons</param-value>
</context-param>
The param-value must be 1 of these 3 values but not all of them!! The whole context-param section can be removed and the default will be auto
bean.xhtml
<h:form enctype="multipart/form-data">
<p:outputLabel value="Choose your file" for="submissionFile" />
<p:fileUpload id="submissionFile"
value="#{bean.file}"
fileUploadListener="#{bean.uploadFile}" mode="advanced"
auto="true" dragDropSupport="false" update="messages"
sizeLimit="100000" fileLimit="1" allowTypes="/(\.|\/)(pdf)$/" />
</h:form>
Bean.java
#ManagedBean
#ViewScoped
public class Submission implements Serializable {
private UploadedFile file;
//Gets
//Sets
public void uploadFasta(FileUploadEvent event) throws FileNotFoundException, IOException, InterruptedException {
String content = IOUtils.toString(event.getFile().getInputstream(), "UTF-8");
String filePath = PATH + "resources/submissions/" + nameOfMyFile + ".pdf";
MyFileWriter.writeFile(filePath, content);
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
event.getFile().getFileName() + " is uploaded.", null);
FacesContext.getCurrentInstance().addMessage(null, message);
}
}
web.xml
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<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>
Neither of the suggestions here were helpful for me. So I had to debug primefaces and found the reason of the problem was:
java.lang.IllegalStateException: No multipart config for servlet fileUpload
Then I have added section into my faces servlet in the web.xml. So that has fixed the problem:
<servlet>
<servlet-name>main</servlet-name>
<servlet-class>org.apache.myfaces.webapp.MyFacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<multipart-config>
<location>/tmp</location>
<max-file-size>20848820</max-file-size>
<max-request-size>418018841</max-request-size>
<file-size-threshold>1048576</file-size-threshold>
</multipart-config>
</servlet>
For people using Tomee or Tomcat and can't get it working, try to create context.xml in META-INF and add allowCasualMultipartParsing="true"
<?xml version="1.0" encoding="UTF-8"?>
<Context allowCasualMultipartParsing="true">
<!-- empty or not depending your project -->
</Context>
With JBoss 7.2(Undertow) and PrimeFaces 6.0 org.primefaces.webapp.filter.FileUploadFilter should be removed from web.xml and context param file uploader should be set to native:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>native</param-value>
</context-param>
I had the same issue, due to the fact that I had all the configuration that describe in this post, but in my case was because I had two jQuery imports (one of them was PrimeFaces's bundled jQuery) which caused conflicts to upload files.
Manually adding / loading jQuery with PrimeFaces results in Uncaught TypeErrors
Been try to learn JSF, and sometimes I see the URL is *.jsf and sometimes is *.xhtml or /faces/*. Can someone fill my knowledge, please? When I create a JSF using Facelet, the file extension is .xhtml, so where does .jsf URL extension come from?
The .jsf extension is where the FacesServlet is during the JSF 1.2 period often mapped on in the web.xml.
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
The .xhtml extension is of the actual Facelets file as you've physically placed in the webcontent of your webapp, e.g. Webapp/WebContent/page.xhtml.
If you invoke this page with the .jsf extension, e.g. http://localhost:8080/webapp/page.jsf then the FacesServlet will be invoked, locate the page.xhtml file and parse/render its JSF components. If the FacesServlet isn't invoked, then the enduser would end up getting the raw XHTML source code (which can be seen by rightclick, View Source).
Sometimes a *.faces extension or /faces/* foldermapping is been used. But this was from back in the JSF 1.0/1.1 ages. You're free to choose and use whatever mapping you'd like to let FacesServlet listen on, even if it's a nothing-saying *.xyz. The actual page itself should always have the .xhtml extension, but this is configureable by the following <context-param> in web.xml:
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xml</param-value>
</context-param>
This will change the FacesServlet to locate page.xml instad of (default) page.xhtml.
More recently, with JSF/Facelets 2.0 a *.xhtml mapping is been used. In JSF/Facelets 1.x it was not possible to use the same mapping extension as the physical file. It would result in an infinite loop. But since JSF/Facelets 2.0 it is possible and this allows you to call the page by http://localhost:8080/webapp/page.xhtml.
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
This way you don't need to configure some security restrictions to hide the raw source files away for cases whenever the enduser changes for example .jsf in URL to .xhtml in browser address bar. Only tooling (IDEs and plugins) and learning resources still need to catch up the advocated move from *.jsf to *.xhtml. As per JSF 2.3, the FacesServlet will by default be autoregistered on *.xhtml too (next to /faces/*, *.faces and *.jsf). This is backported to Mojarra 2.2.11.
See also:
Can we use regular expressions in web.xml URL patterns?
Set default home page via <welcome-file> in JSF project
JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output
What is the difference between creating JSF pages with .jsp or .xhtml or .jsf extension
Which XHTML files do I need to put in /WEB-INF and which not?
Customize FacesServlet <url-pattern> to get rid of .xhtml extension
I am upgrading my application from JSF 1.2 to JSF 2.2 and using Tomahawk 1.1.14 version.
After upgrading, <t:inputFileUpload> tag has stopped working and value of the component is not bound to backingbean property any more.
web.xml
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/facelets/tags/tomahawk.taglib.xml</param-value>
</context-param>
However, I saw on myfaces site that the above parameter is deprecated. Is there any other way to include tag libraries or is it not even required with JSF 2.2?
<filter>
<filter-name>MyFacesExtensionsFilter</filter-name>
<filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
<init-param>
<param-name>uploadMaxFileSize</param-name>
<param-value>50m</param-value>
</init-param>
<init-param>
<param-name>uploadThresholdSize</param-name>
<param-value>1024k</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFacesExtensionsFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>MyFacesExtensionsFilter</filter-name>
<url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>MyFacesExtensionsFilter</filter-name>
<url-pattern>*.faces</url-pattern>
</filter-mapping>
Before this filter, I do have another filter in my web.xml and it is
<filter>
<filter-name>AjaxAnywhere</filter-name>
<filter-class>org.ajaxanywhere.AAFilter</filter-class>
<init-param>
<param-name>preSendHandlerClass</param-name>
<param-value>org.ajaxanywhere.jsf.MyFacesClientStateSavingPreSendHandler</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>AjaxAnywhere</filter-name>
<url-pattern>*.faces</url-pattern>
</filter-mapping>
Can anyone please help me if I need to do any more configuration changes for Tomahawk to work with JSF 2.2?
Thanks!
Since JSF 2.2, the FacesServlet will automatically parse multipart/form-data requests all by itself with help of new Servlet 3.0 #MultiartConfig annotation. Also, since JSF 2.2 there is (finally!) a standard file upload component, the <h:inputFile>.
The MyFaces extensions filter and Tomahawk file upload component is basically incompatible with JSF 2.2. The filter would consume and parse the request its own way and the FacesServlet would end up getting no request data at all (and therefore not be able to continue the JSF lifecycle "as usual"). Removing the filter alone would also not work as <t:inputFileUpload> is internally relying on the semantics/specifics of the MyFaces extensions filter.
Your best bet is really to just remove the filter from the web.xml altogether and replace the <t:inputFileUpload> by <h:inputFile>. It must be bound to a javax.servlet.http.Part property which offers a.o. getInputStream() which you can just continue using the same way as before with <t:inputFileUpload>.
<h:inputFile value="#{bean.uploadedFile}" />
private Part uploadedFile;
public void save() {
String name = uploadedFile.getSubmittedFileName();
String type = uploadedFile.getContentType();
long size = uploadedFile.getSize();
InputStream content = uploadedFile.getInputStream();
// ...
}
The upload maximum and threshold size configuration of the filter can be migrated to <multipart-config> entry of the <servlet> entry of the FacesServlet in web.xml like below:
<servlet>
<servlet-name>facesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<multipart-config>
<max-file-size>52428800</max-file-size>
<file-size-threshold>1048576</file-size-threshold>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
See also:
How to upload file using JSF 2.2 <h:inputFile>? Where is the saved File?
Unrelated to the concrete problem, the facelets.LIBRARIES is Facelets 1.x specific. During the JSF 1.x era, Facelets was a standalone view technology. Since JSF 2.0, Facelets is embedded in JSF itself and all its context parameters are migrated from facelets.XXX to javax.faces.FACELETS_XXX. You can find them all in a.o Overview of all JSF-related web.xml context parameter names and values. However, you don't need to explicitly register that Tomahawk taglib as well. Just get rid of it.
I'm asking myself which way is the best for servlet mapping in jsf? And Why?
Especially I'm wondering always about the different suffix of the facelet resources and the suffix of the url-pattern of the servlet-mapping. My servlet mapping is always coherent to the suffix of my resources.
For Example if I'm using xhtml as facelets my servlet mapping does it also:
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
But I see examples where the resources are xhtml files and the servlet mapping is on jsf?
For Example:
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
So which way is the best way?
And also I'm wondering why the second way working at all?
For now you won't need an answer on which servlet mapping to use, I think. You would probably be better of with some reading first.
I have taken the liberty to find two related questions which might open your eyes a little considering JSF and the file extension.
What is the difference between creating JSF pages with .jsp or .xhtml or .jsf extension
JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?
I have an h:selectOneMenu and an a4j:commandButton, the latter of which reRenders a component called content which looks like this:
<rich:panel id="content">
<a4j:include viewId="#{MyBacking.viewId}" />
</rich:panel>
When the response is rendered and the component loads the content of the new JSP page, the tabs contained in that page use a skin that is different from the rest of the app (I think default blue).
I've noticed that after the included code is loaded, if I hit refresh, although this causes the bean to reissue the page contents, the skin is properly assigned.
My web xml says:
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>glassX</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.CONTROL_SKINNING</param-name>
<param-value>enable</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.CONTROL_SKINNING_CLASSES</param-name>
<param-value>enable</param-value>
</context-param>
Is this effect because RichFaces is in some way not in control of the rendering of the tabs at this point?
How can I ensure the tabs conform to the skin? All the documentation is relating to overriding a skin, and I'd rather not have to override and skin with the skin that it should already have.
Thanks
I am not sure if it will solve your problem, however you can try to force Richfaces to avoid using the default skin by setting a specific web.xml parameter:
<context-param>
<param-name>org.richfaces.LoadStyleStrategy</param-name>
<param-value>ALL</param-value>
</context-param>
You can find more details about this property here.
edited, to set the correct param-value, as stated in the comments.
I've just noticed I'd included a styleClass parameter - and because the jsp is now included didn't have access to the css facet reference.