6.12. PorletFaces File Upload

The JSF 1.x and 2.x specifications have not implemented support for HTML forms with enctype="multipart/form-data" and are therefore do not support file uploads. Various workarounds exist for use with the JSP view-handler, such as introducing a servlet filter or phase listener to intercept the request. With the advent of the Facelets view-handler, these techniques have become largely ineffectual. The problem has to do with the FaceletViewHandler restoreView(FacesContext context, String viewId) method which is unable to retrieve the javax.faces.ViewState request parameter for HTML forms with enctype="multipart/form-data". The underlying reason why it can't retrieve the parameter is because the ExternalContextImpl.getRequestParameterMap() method in the JSF Reference Implementation is not equipped to handle these types of postback requests.

The PortletFaces project solves this problem by providing wrapper implementations of FacesContext, FacesContextFactory, and ExternalContext. These can be activated by placing the following <faces-context-factory> element inside of your portlet WAR's WEB-INF/faces-config.xml descriptor:

Example 6.56. Example usage of faces-context-factory element

<factory>
	<faces-context-factory>org.edorasframework.portletfaces.bridge.sun.FacesContextFactoryImpl</faces-context-factory>
</factory>


This will ultimately cause the FacesContext.getExternalContext() method to return an instance of the org.edorasframework.portletfaces.bridge.sun.ExternalContextImpl class. This class overrides the ExternalContext.getRequestParameterMap() method, which uses Apache Commons FileUpload project to parse the request parameters. When used in conjunction with the pf:inputFile tag, JSF portlet developers can provide file upload capability in their Facelet views.