fileUpload doesn't fire event in PrimeFaces 3.5 with JSF 2.2 - jsf

I can't make fileUpload component on PrimeFaces 3.5 to fire the event. I have read many posts about that topic and followed advise there but still it doesn't work. I tried all of the modes (simple, auto, advanced) with no success.
If I use standard inputFile tag from the JSF specification it works properly.
This is my web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>redmond</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</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>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/home.xhtml</welcome-file>
</welcome-file-list>
</web-app>
And this is part of my view page with the fileUpload tag:
<h:form enctype="multipart/form-data">
<p:dialog id="basicDialog" header="Add pictures" widgetVar="dlg1" >
<p:fileUpload fileUploadListener="#{galleryManagedBean.addPicturesToGallery}" multiple="true"/>
</p:dialog>
</h:form>
The extract from managed bean with the method that is called from the tag:
#Named(value = "galleryManagedBean")
#RequestScoped
public class GalleryManagedBean {
public void addPicturesToGallery(FileUploadEvent event)
{
System.out.println("Triggered upload");
}
}
Also I would like to add that the Http POST request is fired properly after I checked it using the debugger tool in Chrome.
I have added necessary libraries to the classpath i.e. :
commons-fileupload-1.3.jar
commons-io-2.4.jar

This is caused by a change in FacesServlet of JSF 2.2. Since that version, FacesServlet natively supports file uploads (specifically: multipart/form-data HTTP requests) thanks to the presence of the new Servlet 3.0 specific #MultipartConfig annotation. Also, a new <h:inputFile> component was been introduced to offer a file upload component in the standard JSF component set.
This all conflicts with PrimeFaces file upload facility in older PrimeFaces 3.x versions which didn't take this new JSF 2.2 feature into account at all. The PrimeFaces 3.x file upload filter parsed and consumed the entire request while it should leave this job up to the FacesServlet. This caused the FacesServlet to be unable to properly decode the HTTP request (determining the submitted values and actions).
PrimeFaces 4.0, which is designed specifically for JSF 2.2, has taken this all into account. In this changeset of the PrimeFaces file upload filter you can see the changes done to recognize JSF 2.2 and bypass the parsing in the filter. Theoretically, it should also suffice to entirely remove the file upload filter registration from web.xml so that this isn't used anymore.
It should work fine if you upgrade to PrimeFaces 4.0. It has coincidentally been officially released just 2 days ago, so you're pretty on time for that. 

Related

<t:inputFileUpload> not working anymore after migration JSF 1.2 to JSF 2.2

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.

Why does <h:link> change destination extension from .html to .xhtml?

I'm using JSF 2.1 and I'm experiencing some problems with the <h:link> tag. I'm trying to have the link's outcome point from my XHTML file to a plain HTML file. However, when I run my web application, the .html extension in link's generated URL is automatically converted to a .xhtml extension.
Here is my Facelet file:
<h:body>
<h:form>
<h:link value="animation" outcome="#{contentForm.ccAnimationLink}"/>
</h:form>
<h:body>
Here is my contentForm bean:
package my.app.content;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class ContentForm implements Serializable {
private static final long serialVersionUID = -8463354828156798513L;
private String ccAnimationLink = "";
#PostConstruct
public void init() {
ccAnimationLink = "/content/cc/CC_animation/story.html";
}
public String getCcAnimationLink() {
return ccAnimationLink;
}
public void setCcAnimationLink(String ccAnimationLink) {
this.ccAnimationLink = ccAnimationLink;
}
}
Now, when I run this application, I get the following error:
Unable to find matching navigation case from view ID '/content/modifiedcc.xhtml' for outcome '/content/cc/CC_animation/story.html'
I made sure that I had the URL correct, so I created a story.xhtml file in that location as well. With that file there it runs without errors.
If I pull the source for the generated page, I can see that the <h:link> was correctly changed to an "a href" tag, as follows:
animation
For some reason though the URL changes from story.html, like I have it in my bean, to story.xhtml.
How can I make sure that it stays as story.html and not change it to xhtml?
Here is my web.xml file as well:
<display-name>MyWebApp</display-name>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<welcome-file-list>
<welcome-file>jsf/login/login.xhtml</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
I tried adding the following to the web.xml, this didn't make a difference:
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
I'm sure this has a very simple solution which I'm just missing right now. Help would be highly appreciated. I hope the question is clear.
JSF 2.0+ has introduced <h:link> component that takes a navigation case outcome in its outcome attribute and autogenerates the right URL on its own. This is why you had the error without adding yet another mapping for the faces servlet: just reread the error. It is useful for creation of inter-JSF application navigation.
Alternatively, there has always been a <h:outputLink> component that takes an URL in its value attribute instead. It is useful for creation of navigation external to a JSF application.
Be sure to read the classics from BalusC on the issue: When should I use h:outputLink instead of h:commandLink?.
That said, consider the following components:
<h:link outcome="/destination" value="link" />
<h:outputLink value="/destination.html">
outputLink
</h:outputLink>
The former component will translate its outcome into an actual URL, by appending a faces servlet mapping, while the latter one will leave its value as-is.
So, your problem will be solved by using the following component:
<h:outputLink value="#{contentForm.ccAnimationLink}">
Animation
</h:outputLink>

JSF template not applied

I'm running into a problem with JSF and templating. I'm following this tutorial but the only output I see is the one I'm defining in my index.xhtml with
<ui:composition template="/WEB-INF/templates/BasicTemplate.xhtml">
<ui:define name="content">
my custom content
</ui:define>
without adding the footer and header even though I'm not defining/overwriting the default one in my index file.
If I view the source in the browser it's showing up the same way as in my index.xhtml with ui:composition etc. So it looks like it's not "converting" it to HTML.
The relevant parts of my web.xml:
<servlet>
<description>Controller Servlet for data input</description>
<display-name>InputServlet</display-name>
<servlet-name>InputServlet</servlet-name>
<servlet-class>form.controller.InputServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>InputServlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
My directory structure looks like this:
http://i.imgur.com/ZslOQNr.png
Thanks!
You're using the wrong servlet.
JSF comes with its own servlet, the FacesServlet.
Get rid of the InputServlet from web.xml altogether and map JSF's FacesServlet as follows:
<servlet>
<servlet-name>facesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
That should do it.
See also:
Our JSF wiki page - contains a Hello World and several links to sane tutorials

Basic JSF with Session doesn't work in glassfish

I wanted to test Session replication of session and application scoped beans of JSF 2 in a clustered environment, currently trying with glassfish. To do so I created a simple application that I deployed to the server first to verify it's working (it doesn't).
Here is what I did so far:
Setup a Ubuntu Virtual Machine in Oracle VirtualBox
download glassfish as zip-file and unzip it in the home directory
start glassfish
deploy the JSF-app as war-file
go to the page of the app: localhost:8080/jsftest/index.jsf
try to set a variable saved in session/application scope
Depending on javax.faces.STATE_SAVING_METHOD in web.xml the result:
server: viewExpiredException is thrown
client: value is not stored and default value is shown
To create the app I did the following:
create new dynamic web project in eclipse
unzip all files from myfaces core in WEB-INF/lib
set the classes-folder to WEB-INF/classes
write beans and a .xhtml as below
The session scoped bean (application scoped is similiar):
#ManagedBean(name = "sessbean")
#SessionScoped
public class MySessionScopeBean implements Serializable{
private static final long serialVersionUID = -4733271400646173098L;
private String value = "default session data";
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
The index.xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>JSF 2.0 Hello World</title>
</h:head>
<h:body>
<h3>JSF 2.0 Hello World Example - hello.xhtml</h3>
<h:outputText value="Session id: #{sessionScope['id']}" />
<h:form>
<h:panelGroup>
<h:outputText value="Session Variable:"/>
<br/>
<h:inputText value="#{sessbean.value}"/>
</h:panelGroup>
<h:commandButton value="submit"/>
</h:form>
<h:form>
<h:panelGroup>
<h:outputText value="Application Variable:"/>
<br/>
<h:inputText value="#{appbean.value}"/>
</h:panelGroup>
<h:commandButton value="submit"/>
</h:form>
</h:body>
</html>
So this very basic example doesn't work. Any suggestions?
Also the Session-ID is not shown by #{sessionScope['id']}, don't know if that is the way to do it.
Got it working by removing parts of the (generated) web.xml file. The working file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>jsftest</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
</web-app>
What I stripped out (don't know which part caused the failure):
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<description>
This parameter tells MyFaces if javascript code should be allowed in
the rendered HTML output.
If javascript is allowed, command_link anchors will have javascript code
that submits the corresponding form.
If javascript is not allowed, the state saving info and nested parameters
will be added as url parameters.
Default is 'true'</description>
<param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<description>
If true, rendered HTML code will be formatted, so that it is 'human-readable'
i.e. additional line separators and whitespace will be written, that do not
influence the HTML code.
Default is 'true'</description>
<param-name>org.apache.myfaces.PRETTY_HTML</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<description>
If true, a javascript function will be rendered that is able to restore the
former vertical scroll on every request. Convenient feature if you have pages
with long lists and you do not want the browser page to always jump to the top
if you trigger a link or button action that stays on the same page.
Default is 'false'
</description>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>

tomcat7+El2.2+jsf1.2 not working

expression language is not working in tomcat7 with jsf1.2 .#{message.name_prompt} is ouputed as #{message.name_prompt}.
i tried to replace the el-api.jar in the tomcat lib folder with el-api-2.2.jar and put the el-impl-2.2.jar in the WEB-INF/lib folder, adding
<context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
to the web.xml. stilll the same.
my tomcat exact version is *7.0.21*this is the web.xml with the default tomcat setting:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>BasicExamples</display-name>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
</web-app>
update:
now i find that the expression language is not working on the form page but the message expression language is working as #{message.result_text}=>You entered the following information : ,but still managed bean not working.
and El is working fine with jsf2.0
You don't need to install/add anything to get EL 2.2 to work in Tomcat 7. It already ships with EL 2.2. Remove those JARs and the context param.
Given your symptoms
#{message.name_prompt} is ouputed as #{message.name_prompt}
I have the impression that you're talking about using EL in template text something like:
<p>This is EL in template text #{message.name_prompt}</p>
This is not an EL 2.2 feature. This is a Facelets feature. Facelets is the successor of JSP. You need to replace JSP by Facelets in order to be able to use EL in template text like that. For JSF 1.2, you can use Facelets 1.1.
Otherwise, when you want to stick to JSP, you really need to use <h:outputText>:
<p>This is EL in template text <h:outputText value="#{message.name_prompt}" /></p>
The only new EL 2.2 feature is the ability to invoke action methods with arguments, e.g.:
<h:dataTable value="#{bean.list}" var="item">
<h:column>
<h:commandButton value="Edit" action="#{bean.edit(item)}" />
</h:column>
</h:dataTable>
See also:
Difference between JSP EL, JSF EL and Unified EL
Migrating from JSF 1.2 to JSF 2.0

Resources