primefaces JSF P:fileUpload cannot get the response - jsf

I am facing a problem with <p:fileUpload> of PrimeFaces. I created a Facelet page to upload the Excel file as below:
<p:fileUpload fileUploadListener="#{blackListImportBean.xlsFileUpload}"
multiple="true" allowTypes="*.xls;*.xlsx" description="*.xls;*.xlsx"
sizeLimit="100000"/>
<h:commandButton actionListener="#{blackListImportBean.test}"
value="#{msg.SAVE}" action="test-page.xhtml" />
And bean java code as below:
public void xlsFileUpload(FileUploadEvent event){
// ...
}
public void test() {
// ...
}
When I click the button, the method test() is called and the method xlsFileUpload() is not invoked and an error prompts that it cannot find the method xlsFileUpload(), because the method need the parameter. When I remove the parameter, the page cannot find the method. Another issue which confused me is that I cannot get the upload file. I did it as per the documentation and I do not know what should I do.

Two questions:
1) Are you using Primefaces 2.X or 3.X?
2) What is on the stack trace? It probably contains the information as to why.
The file-upload component uploads the file on its own event sequence so that will get triggered when the user triggers the file upload. This can be automatic via the property auto="true". Alternatively it displays an "upload" button that causes the upload. As such, it is separated from the second action which is your test method.
Judging from the fact it can't find your method I would guess that either bean is unmanaged or that your environments are out of sync (clean build).
Also, try a simple test:
#ViewScope
public class TestBean
{
public void handleFileUpload(FileUploadEvent evt)
{
System.out.println("Handling Upload: " + evt.getFile());
UploadedFile upload = evt.getFile();
FacesContext.getCurrentInstance()
.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "File Uploaded", "This file is " + upload));
. . . //do whatever here....
}
}
//JSF Page
. . .
<h:form>
<p:messages id="messages" />
<p:fileUpload
fileUploadListener="#{testBean.handleFileUpload}"
multiple="true"
allowTypes="*.*;"
update="messages"
/>
</h:form>
. . .
If your filter is set you should see a series of messages displayed for each file that's uploaded. If not, you should get a useful error message. Also, be aware you need a fair amount of basic Apache libraries (CommonsFileUpload) on the path and odds are that this is causing your problem.

Don't forget to add this in your web.xml:
<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>

Related

Simple Jetty/JSF file upload won't submit

I've already looked at this one and the related tickets to no avail.
I have, what looks like the, simplest example possible
<h:form enctype="multipart/form-data" prependId="false">
<h:outputText value="File: "></h:outputText>
<h:inputFile value="#{configUploadController.uploadedFile}" />
<h:commandButton value="Save" type="submit" action="#{configUploadController.uploadFile}" style="color: red;"></h:commandButton>
</h:form>
I put a breakpoint in my uploadFile method but it never gits hit. when I remove the enctype from the form it does try to submit but then I get the obvious error...
javax.servlet.ServletException: Content-Type != multipart/form-data
And just for completeness, I remove the <h:inputFile> and enctype and can see my breakpoint being hit. When I set enctype to text/plain it DOESNT hit the breakpoint. However, when I set enctype to gibberish it DOES hit the breakpoint :(
Am I missing a dependency or config somewhere?
And in case it matters, my web.xml...
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
version="3.1">
<!-- File(s) appended to a request for a URL that is not mapped to a web
component -->
<welcome-file-list>
<welcome-file>status.xhtml</welcome-file>
</welcome-file-list>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
<listener>
<description>Initializes Oracle JSF</description>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<!-- Define the JSF servlet (manages the request processing life cycle for
JavaServer Faces) -->
<servlet>
<servlet-name>faces-servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<!-- Map following files to the JSF servlet -->
<servlet-mapping>
<servlet-name>faces-servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
jsf-api-2.2.15
jsf-impl-2.2.15
el-api-2.2
el-impl-2.2
jetty 9.4.18
javax.servlet-api-3.1.0
Instead of working around with a servlet (as per other answer) the actual problem was Jetty needs the multipart config setting up per multipart request.
Simple way to do this would be to add a filter that adds it as necessary, eg.
public class LoginFilter implements Filter {
private static final String MULTIPART_FORM_DATA = "multipart/form-data";
private static final MultipartConfigElement MULTI_PART_CONFIG =
new MultipartConfigElement(System.getProperty("java.io.tmpdir"));
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String contentType = request.getContentType();
if (contentType != null && contentType.startsWith(MULTIPART_FORM_DATA))
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, MULTI_PART_CONFIG);
filterChain.doFilter(request, response);
}
}
See also:
How to implement FileUpload in embedded Jetty?
So, I haven't spent the time to track down why but jetty doesn't appear to like multipart forms. I got round it by using a servlet. Solution looks like this...
I've gone with ajax approach and a HTML form so I can specify my action, that matches the servlets pattern...
<form action="upload/config" enctype="multipart/form-data" method="post">
<h:inputFile id="file" />
<br />
<h:commandButton type="submit" value="Upload">
<f:ajax execute="file" render="#all"/>
</h:commandButton>
</form>
And the servlet...
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.servlet.MultipartConfigElement;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.eclipse.jetty.server.Request;
#WebServlet("upload")
#MultipartConfig
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) {
try {
// This needed to get access to the parts
MultipartConfigElement multipartConfigElement = new MultipartConfigElement((String)null);
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, multipartConfigElement);
Part filePart = request.getPart("file");
try ( InputStream inputStream = filePart.getInputStream(); ) {
// Do what you want with your part
} catch (Exception e) {
resp.setStatus(500);
}
} catch (Exception e) {
resp.setStatus(500);
}
}
}

Strange display of p:fileUpload component

I am trying to use the fileUpload component of PrimeFaces and everything is working BUT an empty error message is displayed when the component appeared with no content and i do not understand why.
And if i add a file to the component is disappeared well but it is still not pretty to have it when the component loads.
// View
<h:form>
<p:fileUpload fileUploadListener="#{bean.handleFileUpload}" />
</h:form>
// ManagedBean
public void handleFileUpload(FileUploadEvent event) {
UploadedFile file = event.getFile();
System.out.println("handleFileUpload : " + file);
}
The managed bean function is well called when I click on the upload button.
Hope some could understand my problem !
Thanks in advance

Google maps autocomplete with JSF error with ÄÖÜ

we're using google maps autocomplete in our JSF application, but when we choose a name with öäü the backingBean gets eg. Ã as value. We have set our meta info of the site to utf-8, but this didn't help in this case.
we added it like this:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places&key=AIzaSyChQPYNPhodC79W6-oGzlVgQJEwfFMG_bs" />
<script type="text/javascript" charset="utf-8">
function addGMapAutoComplete(componentId) {
var component = document.getElementById('createRequest:' + componentId);
if (component) {
new google.maps.places.Autocomplete(component);
}
}
</script>
and used as
<p:inputText id="pickupLocation"
value="#{createRequest.pickupLocation}" required="true"
onfocus="addGMapAutoComplete('location')"
style="width:350px" />
can anyone help with this issue?
This is a known issue with PrimeFaces. It's incorrectly using server's default encoding (which is often ISO-8859-1) for decoding POST request data of ajax requests, even though JSF/Facelets by itself already by default uses UTF-8 through all layers.
To overcome this, you need to manually set the POST request body encoding to UTF-8 by calling ServletRequest#setCharacterEncoding() with a value of "UTF-8" as early as possible in the request processing (before the parameters are ever parsed out of the POST request body). Most straightforward way would be using a servlet filter for this:
#WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
// ...
}
Or, if you happen to use JSF utility library OmniFaces already, then just use its ready-to-use CharacterEncodingFilter by adding the following entries to your webapp's web.xml:
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.omnifaces.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Servlet filter which is mapped on /home is not invoked when I open /home.xhtml

I am new to Java Enterprise Edition. I started learning from some YouTube videos, and recently started reading http://docs.oracle.com/javaee/6/tutorial/doc/ I finished chapter 15.
I tried to make my own filter.
I didn't use Java Servlet class. Because I want to use JSF pages, and as far as I know it is only possible to use Managed Beans with JSF pages, Whereas Servlet classes work with JSP. It is OK.
As far as I know the usefulness of login filter:
https://stackoverflow.com/tags/servlet-filters/info
[...] This is particularly useful when you have multiple pages for which
you'd like to check the logged-in user. Instead of copypasting the
same logic over all pages, you can use a Filter to have it in a single
place.
It is useful (as I know) in the case when a user type the URL directly into the browser for a page which require logged in user, so the filter will redirect him to the login page or continue if he is logged in.
I searched for any simple example to learn from but didn't find. I will put my simple example:
I have two JSF pages
one is named home.xhtml (which require logged in user)
the other one is named login.xhtml (filter must redirect to it if non-logged users seek home)
login.xhtml:
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="name:"/> <h:inputText value="#{user.name}"/>
<h:outputLabel value="password:"/> <h:inputSecret value="#{user.password}"/>
</h:panelGrid>
<h:commandButton id="btn" value="login" action="#{user.login()}"/>
</h:form>
home.xhtml:
<h:body>
Hello #{user.name}. You are welcome
</h:body>
User:
#ManagedBean
#SessionScoped
public class User implements Serializable
{
String name;
String password;
Authentication authentication;
public User()
{
authentication = new Authentication();
}
//Getters and Setters for name and password.
public String login()
{
if (this.getName().equals("user") &&(this.getPassword().equals("1234")))
{
authentication.setLoggedIn(true);
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("auth", authentication);
return "home";
}
else
{
authentication.setLoggedIn(false);
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("auth", authentication);
return "login";
}
}
}
Authentication:
#ManagedBean
#SessionScoped
public class Authentication implements Serializable
{
private boolean authenticated;
public Authentication()
{
authenticated = false;
}
public boolean isLoggedIn()
{
return authenticated;
}
public void setLoggedIn(boolean authenticated)
{
this.authenticated = authenticated;
}
}
LoginFilter:
#WebFilter(value = "/home")
public class LoginFilter implements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{
//throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException
{
HttpServletRequest req = (HttpServletRequest) request;
Authentication auth = (Authentication) req.getSession().getAttribute("auth");
if (auth != null && auth.isLoggedIn())
{
System.out.println("Filter is working");
chain.doFilter(request, response);
} else
{
System.out.println("Filter is working");
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect(req.getContextPath() + "/login.xhtml");
}
}
#Override
public void destroy()
{
//throw new UnsupportedOperationException("Not supported yet.");
}
}
faces-config:
<navigation-rule>
<from-view-id>/login.xhtml</from-view-id>
<navigation-case>
<from-outcome>home</from-outcome>
<to-view-id>/home.xhtml</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
web.xml:
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</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>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/login.xhtml</welcome-file>
</welcome-file-list>
Now when I type the URL of home.xhtml page (after clearing history & cookies) into the browser it is assumed to redirect me to login page. But instead it goes to home with empty value for name:
Hello #{user.name}. You are welcome is rendered as Hello . You are welcome
Even System.out.println("Filter is working"); not print anything.
Are you sure the filter is called? If there is nothing printed to System.out I guess not. The problem might be the servlet mapping.
You specified this:
#WebFilter(value = "/home")
public class LoginFilter implements Filter {...}
I think this only matches the url /home. Try to use /* or /home* (which is very limiting, I would not recommend it) instead.
Another thing: If you get Hello #{user.name}. You are welcome as output, then the FacesServlet is probably not called. This might have two reasons:
You use the wrong mapping. Try to call the page with /faces/home.xhtml or /home.jsf instead. The url depends on the type of mapping you have in the web.xml.
The FacesServlet is not configured correctly/at all in the web.xml.

JSF Datatable Binding not working properly

I am creating a simple JSF application that is having only one JSP page (1 dropdown, 1 datatable & 1 submit button).
When i select the value from dropdown, i populate the table with an arraylist to display table data. The table is editable. Now when i click submit, i need to get the entire table into a list. For this i have used the binding attribute of datatable. But the issue is that null is returned from getValue.
Please help me with this issue as i have wasted lots of time.
class UserBean {
.....
private HtmlDataTable _dataTable;
public void setDataTable(HtmlDataTable dataTable)
{
this._dataTable = dataTable;
}
public HtmlDataTable getDataTable()
{
return _dataTable;
}
...................
public String submit() {
List<User> userDetails = (ArrayList<User>)((HtmlDataTable)getDataTable()).getValue();
System.out.println(userDetails);
return "";
}
}
// JSP Page
<h:dataTable id="erdatatable"
var="row" value="#{UserBean.userDetails}"
binding="#{UserBean.dataTable}">
....
</h:dataTable>
<h:commandButton value="Submit" action="#{UserBean.submit}"></h:commandButton>
// faces.config
<managed-bean>
<managed-bean-name>UserBean</managed-bean-name>
<managed-bean-class>com.datatable.UserBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
// web.xml
<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>
You can try changing managed-bean-scope to session. The request scope of the UserBean class ends when you invoke the action (dropdown select) and populates the datatable. When you press the submit button again, a new instance of UserBean is created.
If you only need the data from the table, you don't need (and probably shouldn't) bind it at all. Your userDetails will contain all the data, as edited by the user, without any extra work.
If you use the session scope, you will have bugs as soon as someone opens your application in two tabs, chooses something from the dropdown on one of them and then presses the button on the second one. A common solution is to use view scope (which does not work well with binding, but - as I stated - you should not have used it at all)

Resources