Primefaces FileUpload not working with PrettyFaces and Spring Boot
I am using springboot 1.5.2.RELEASE
with JSF 2.2.14
and primefaces 6.1
and prettyfaces 3.4.1.Final
my pom file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>myapp</artifactId>
<version>1</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.14</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.14</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.1</version>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-servlet</artifactId>
<version>3.4.1.Final</version>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-config-prettyfaces</artifactId>
<version>3.4.1.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/bouncycastle/bcprov-jdk15 -->
<dependency>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk15</artifactId>
<version>140</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.jcr/jcr -->
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.jackrabbit/jackrabbit-core -->
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-core</artifactId>
<version>2.15.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.jackrabbit/jackrabbit-api -->
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-api</artifactId>
<version>2.15.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.jackrabbit/jackrabbit-jcr-commons -->
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-commons</artifactId>
<version>2.15.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.jackrabbit/jackrabbit-jcr2dav -->
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr2dav</artifactId>
<version>2.15.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-rmi</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
<build>
<finalName>myapp</finalName>
<plugins>
<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId>
<configuration> <source>1.6</source> <target>1.6</target> </configuration>
</plugin> -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF8</argLine>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
</repository>
<repository>
<id>org.jboss.repository.releases</id>
<name>JBoss Maven Release Repository</name>
<url>https://repository.jboss.org/nexus/content/repositories/releases</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
my springboot config class looks like this:
package com.myapp;
import java.util.Collections;
import javax.faces.webapp.FacesServlet;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.CustomScopeConfigurer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import com.ocpsoft.pretty.faces.annotation.URLMapping;
import com.ocpsoft.pretty.faces.annotation.URLMappings;
@SpringBootApplication
@URLMappings(mappings = { @URLMapping(id = "login", pattern = "/login", viewId = "/faces/public/login.xhtml")})
public class Application extends SpringBootServletInitializer {
private static final Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
@Bean
public ServletContextInitializer servletContextCustomizer() {
return new ServletContextInitializer() {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
servletContext.setInitParameter("primefaces.CLIENT_SIDE_VALIDATION", Boolean.TRUE.toString());
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", Boolean.TRUE.toString());
servletContext.setInitParameter("primefaces.FONT_AWESOME", Boolean.TRUE.toString());
servletContext.setInitParameter("primefaces.UPLOADER", "commons");
}
};
}
@Bean
public static CustomScopeConfigurer customScopeConfigurer() {
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
configurer.setScopes(Collections.<String, Object>singletonMap(FacesViewScope.NAME, new FacesViewScope()));
return configurer;
}
@Bean
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(servlet, "*.jsf");
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean FileUploadFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new org.primefaces.webapp.filter.FileUploadFilter());
registration.setName("PrimeFaces FileUpload Filter");
registration.addUrlPatterns("/*");
registration.setDispatcherTypes(DispatcherType.FORWARD, DispatcherType.REQUEST);
registration.addServletRegistrationBeans(servletRegistrationBean());
registration.setOrder(2);
return registration;
}
@Bean
public FilterRegistrationBean hiddenHttpMethodFilterDisabled(
@Qualifier("hiddenHttpMethodFilter") HiddenHttpMethodFilter filter) {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter);
filterRegistrationBean.setEnabled(false);
return filterRegistrationBean;
}
}
xhtml page to download:
<?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:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<h:body>
<ui:composition template="/template/commonLayout.xhtml">
<ui:define name="content">
<h:form enctype="multipart/form-data">
<p:commandButton value="test" action="#{testBean.test}"/>
<p:fileUpload fileUploadListener="#{testBean.handleFileUpload}" mode="advanced" dragDropSupport="false"
multiple="true" update="messages" />
<h:messages id="messages"></h:messages>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
bean file upload support is as follows:
package com.myapp.beans;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import org.primefaces.event.FileUploadEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("testBean")
@Scope("view")
public class TestBean implements Serializable {
private static final long serialVersionUID = -3568561158943789169L;
private static final Logger log = LoggerFactory.getLogger(TestBean.class);
public void handleFileUpload(FileUploadEvent event) {
log.info("####### handleFileUpload,file: " + event.getFile().getFileName());
}
}
I run on tomcat 9.0.0.M21
, and when I select a file and click on upload, I get no client-side errors and no server-side errors, and the file doesn't upload, although when I turned on render debug it prints that the file was uploaded:
2017-06-27 07:32:04,926 DEBUG o.p.webapp.filter.FileUploadFilter - Parsing file upload request
2017-06-27 07:32:04,969 DEBUG o.p.webapp.filter.FileUploadFilter - File upload request parsed succesfully, continuing with filter chain with a wrapped multipart request
but the code in the listener in the backup bean was not called.
it seems like the problem is with surfaces, when i remove it from the project the filter works fine.
I also tried the context.xml solution for the surfaces problem:
<?xml version="1.0" encoding="UTF-8"?>
<Context allowCasualMultipartParsing="true">
</Context>
and the problem is not resolved.
please advise how to fix this.
source to share
I realized there are two solutions:
1- Create DispatcherType for simple FORWARD loading filters ONLY
@Bean
public FilterRegistrationBean FileUploadFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new org.primefaces.webapp.filter.FileUploadFilter());
registration.setName("PrimeFaces FileUpload Filter");
registration.setDispatcherTypes(DispatcherType.FORWARD);
return registration;
}
@Bean
public FilterRegistrationBean hiddenHttpMethodFilterDisabled(
@Qualifier("hiddenHttpMethodFilter") HiddenHttpMethodFilter filter) {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter);
filterRegistrationBean.setEnabled(false);
return filterRegistrationBean;
}
2- If you want the type of the firstfaces filter manager to be FORWARD and REQUEST, you must explicitly define the pretty face rewrite filter:
@Bean
public FilterRegistrationBean prettyFilter() {
FilterRegistrationBean prettyFilter = new FilterRegistrationBean(new RewriteFilter());
return prettyFilter;
}
@Bean
public FilterRegistrationBean FileUploadFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new org.primefaces.webapp.filter.FileUploadFilter());
registration.setName("PrimeFaces FileUpload Filter");
registration.setDispatcherTypes(DispatcherType.FORWARD, DispatcherType.REQUEST);
return registration;
}
@Bean
public FilterRegistrationBean hiddenHttpMethodFilterDisabled(
@Qualifier("hiddenHttpMethodFilter") HiddenHttpMethodFilter filter) {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter);
filterRegistrationBean.setEnabled(false);
return filterRegistrationBean;
}
source to share
I might be late for this one, but I know it will save someone, I had a similar problem uploading files using firstfaces6.1 and springboot. My solution was to explicitly set the MultipartConfigElement parameter on the ServletRegistrationBean . A competitive working configuration looks like this:
@Configuration
public class JsfConfig extends SpringBootServletInitializer implements ServletContextAware {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.setInitParameter("primefaces.CLIENT_SIDE_VALIDATION", "true");
servletContext.setInitParameter("javax.faces.FACELETS_REFRESH_PERIOD", "0");
servletContext.setInitParameter("javax.faces.PROJECT_STAGE", "Development");
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", Boolean.TRUE.toString());
servletContext.setInitParameter("primefaces.FONT_AWESOME", Boolean.TRUE.toString());
servletContext.setInitParameter("primefaces.UPLOADER", "commons");
servletContext.setInitParameter("facelets.DEVELOPMENT", "true");
servletContext.setInitParameter("primefaces.THEME", "bootstrap");
}
@Bean
public ServletRegistrationBean facesServlet() {
FacesServlet servlet = new FacesServlet();
ServletRegistrationBean registration = new ServletRegistrationBean(servlet, "*.xhtml");
registration.setName("Faces Servlet");
registration.setLoadOnStartup(1);
registration.setMultipartConfig(new
MultipartConfigElement((String) null));
return registration;
}
@Bean
public ServletListenerRegistrationBean<ConfigureListener> jsfConfigureListener() {
return new ServletListenerRegistrationBean<ConfigureListener>(new ConfigureListener());
}
@Override
public void setServletContext(ServletContext servletContext) {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
}
@Bean
public FilterRegistrationBean facesUploadFilterRegistration() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new FileUploadFilter(), facesServlet());
registrationBean.setName("PrimeFaces FileUpload Filter");
registrationBean.addUrlPatterns("Faces Servlet");
registrationBean.setDispatcherTypes(DispatcherType.FORWARD, DispatcherType.REQUEST);
return registrationBean;
}
@Bean
public static CustomScopeConfigurer customScopeConfigurer(){
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
Map<String, Object> scopes = new HashMap<String, Object>();
scopes.put("view", new ViewScope());
configurer.setScopes(scopes);
return configurer;
}
}
I hope this helps.
source to share
Regardless of Spring Boot, I had this problem in front of PrettyFaces and PrimeFaces, it can be solved by configuring the correct display of filters in the web.xml
following way:
<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>*.xhtml</url-pattern>
</servlet-mapping>
<filter>
<filter-name>Pretty Filter</filter-name>
<filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>
<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>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
I'm not sure if this answer will be useful in your Spring boot environment as I don't have much experience with this stack.
source to share