5

I'm running my JSF project launching it with Spring Boot and taking advantage of the whole Spring environment. The configuration is: Mojarra 2.2.8 + Primefaces 5.1 + Spring Boot 1.1.9. That's how my POM.xml file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany</groupId>
    <artifactId>project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</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-web</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-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>${jsf.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>${jsf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>5.1</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces.themes</groupId>
            <artifactId>all-themes</artifactId>
            <version>1.0.10</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>el-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>el-impl</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>com.tesicnor.workplace.monitor.Application</start-class>
        <java.version>1.7</java.version>
        <tomcat.version>7.0.57</tomcat.version>
        <jsf.version>2.2.8</jsf.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

As it's specified above, I'm configuring the project to run in a tomcat 7.0.57 (Servlet 3.0 compatible) launcher. All the JSF functions are properly working, but the problem is I can't get the Primefaces p:fileUpload component work, neither the basic or the advanced versions. The file upload listener doesn't get invoked and no error thrown.

That's my bean's code:

@ManagedBean
@javax.faces.bean.ViewScoped
public class Bean {

    public void handleFileUpload(FileUploadEvent event) {
        FacesMessage message = new FacesMessage("Succesful", event.getFile()
                .getFileName() + " is uploaded.");
        FacesContext.getCurrentInstance().addMessage(null, message);
        System.out.println("Uploaded!");
    }

}

And that's how my xhtml file looks like, under a template:

<ui:composition template="/WEB-INF/template.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">

    <ui:define name="content">
        <h:form>
            <p:fileUpload fileUploadListener="#{bean.handleFileUpload}" />
        </h:form>
    </ui:define>
</ui:composition>

Nothing special about the code at all, it must be a server configuration issue. When I drop the file and click on upload, the FacesServlet gets hit. So the request is performed and no javascript errors shown. But when I perform a debugging into the InvokeApplicationPhase class, where my method should be invoked, I find no events to be processed. So the FileUploadEvent is not being attached to the cycle.

Furthermore, that's the debugging stack of another project that properly performs the file upload with Tomcat 7 and that JSF version:

enter image description here

Here the NativeFileUploadDecoder is being called. However that's not happening in my Spring boot project and no method below FileUpload#visitTree is invoked.

I tried other choices and found out that when I use some <h:form enctype="multipart/form-data"> none of the action methods for components inside are invoked, even when I place a plain h:commandButton.

Aritz
  • 30,971
  • 16
  • 136
  • 217
  • And the upload filter ? I'm not sure about spring-boot, maybe it has some filters in the way... I had the same issue when I used rewrite urls, I had to add to the `filter-mapping` of `PrimeFaces FileUpload Filter` a `FORWARD`. it is a wild guess :) – Hatem Alimam Dec 19 '14 at 10:13
  • Thanks for the answer @HatemAlimam . I've been looking through documentation and actually PF has two upload options in its latest version, one relying on Servlet 3.0 spec and the other one on the `apache-commons` library. The filter is only required when using `apache-commons`. Finally I achieved getting it working that way, but not with the native spec. It would be interesting however to know the root cause of all of this. I'll post a small-demo project for people to be able to reproduce the issue.. – Aritz Dec 19 '14 at 10:20

3 Answers3

4

Finally, I got it working using the Apache Commons library. Similarly that what we might do in a standard web.xml file, that's my context initializer:

@Bean
public ServletContextInitializer initializer() {
    return new ServletContextInitializer() {
        @Override
        public void onStartup(ServletContext servletContext)
                throws ServletException {
            servletContext.setInitParameter("primefaces.THEME", "bluesky");
            servletContext.setInitParameter(
                    "javax.faces.FACELETS_SKIP_COMMENTS", "true");
            servletContext.setInitParameter(
                    "com.sun.faces.expressionFactory",
                    "com.sun.el.ExpressionFactoryImpl");
            servletContext.setInitParameter("primefaces.UPLOADER",
                    "commons");
        }
    };
}

I explicitly tell Primefaces to use the commons uploader, like said in docs (the other choice is to use native, which is not working).

Then, just adding this two dependencies to the project, we're ready to go:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.2</version>
</dependency>

I keep the thread opened for some response based in the native mode.

See also:

Community
  • 1
  • 1
Aritz
  • 30,971
  • 16
  • 136
  • 217
  • Combining both answers worked for me with PF5.3. Thanks! Saved me a lot of time. – SeC May 22 '16 at 20:58
  • 1
    Combining both answers worked for me as well PF 6.1 Spring boot 1.5.8. Many thanks I lost a few days of my wife searching for the solution. – Petar Petrov Dec 27 '17 at 20:44
4

It could be also necessary to transfer xml filter configuration to Java-based Config :

<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

to your @Configuration

@Bean
public FilterRegistrationBean FileUploadFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new org.primefaces.webapp.filter.FileUploadFilter());
    registration.setName("PrimeFaces FileUpload Filter");
    return registration;
}

in combination with the above answer it work for me

zydor
  • 91
  • 4
  • Did it work for the native way? I mean, having `servletContext.setInitParameter("primefaces.UPLOADER", "native");` in your java configuration. This configuration is expected to work without the FileUpload filter. – Aritz Feb 03 '16 at 15:24
4

Just to put my two cents, with Spring boot 1.4.2.RELEASE, Primefaces 6.0, OCP Soft rewrite 2.0.12.Final, JSF 2.1.29-08 and application deployed on Tomcat 8, I also need to disable spring hiddenHttpMethodFilter.

@Bean
public FilterRegistrationBean hiddenHttpMethodFilterDisabled(
        @Qualifier("hiddenHttpMethodFilter") HiddenHttpMethodFilter filter) { 
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter);
    filterRegistrationBean.setEnabled(false);
    return filterRegistrationBean;
}

I have spent with this issue almost two days and as last thing I have tried to disable spring filters one by one, so I hope it will help someone.

Rado Skrib
  • 396
  • 1
  • 4
  • 7
  • The upload worked running the app in my IDE (irrespective of `packaging` setting in `pom.xml`) after using @Xtreme Biker's solution. However as a `war` deployed in tomcat, it didn't work. Adding your solution too did it for me. Thanks – inginia Sep 29 '17 at 05:36