Glassfish 4, JSF 2.2, and PrimeFaces FileUploadEvent do not work together

After upgrading to GlassFish 4 and JSF 2.2, Primefaces FileUploadEvent stops working. With JSF 2.1, it worked without problems. Everything works fine except file uploads. Is there something I'm missing?

GlassFish 4 JSF 2.2 PrimeFaces 3.4.2 and 3.5 Commons io version: 2.4 Commons fileupload version: 1.3 

Controller side

 public void handleFileUpload(FileUploadEvent event) { System.out.println("HandleFileUpload"); byte[] file = event.getFile().getContents(); newFieldset.setData(file); FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded."); FacesContext.getCurrentInstance().addMessage(null, msg); } 

View

 <h:form enctype="multipart/form-data"> <p:fieldset legend="Create new feed" toggleable="true" collapsed="true" > <p:fileUpload fileUploadListener="#{adminHomeController.handleFileUpload}" style="margin-top: 20px;" mode="advanced" update="messages" sizeLimit="1000000" multiple="false" allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/> <p:inputText label="Baslik" style="margin-top: 20px;" required="true" value="#{adminHomeController.newFieldset.legend}" /> <p:editor style="margin-top: 20px;" value="#{adminHomeController.newFieldset.content}" /> <p:commandButton style="margin-top: 20px;" value="#{msg['common.save']}" update="messages" icon="ui-icon-disk" actionListener="#{adminHomeController.saveFieldset()}"/> </p:fieldset> <p:growl id="messages" showDetail="true"/> </h:form> 
+6
source share
6 answers

Finally, I was able to figure it out. The Commons-fileuploads parseRequest(httpServletRequest) tries to read the inputStream request. Since the container has already read it, it is empty. So what can be done to solve this problem? The answer is a bit more complicated than I originally thought. First you need your own FileUploadFilter file, which might look like this:

 public class FileUploadFilter implements Filter { private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadFilter.class); /* * (non-Javadoc) * * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ @Override public void init(FilterConfig filterConfig) throws ServletException { } /* * (non-Javadoc) * * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, * javax.servlet.ServletResponse, javax.servlet.FilterChain) */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; boolean isMultipart = (httpServletRequest.getContentType() == null) ? false : httpServletRequest.getContentType().toLowerCase().startsWith("multipart/"); if (isMultipart) { MultipartRequest multipartRequest = new MultipartRequest(httpServletRequest); LOGGER.info("File upload request parsed succesfully, continuing with filter chain with a wrapped multipart request"); filterChain.doFilter(multipartRequest, response); } else { filterChain.doFilter(request, response); } } /* * (non-Javadoc) * * @see javax.servlet.Filter#destroy() */ @Override public void destroy() { LOGGER.info("Destroying UploadFilter"); } 

Next: register this filter in your web.xml and remove / replace the Primefaces filter. It should look something like this:

  <filter> <filter-name>FileUpload Filter</filter-name> <filter-class><YourPackage>.FileUploadFilter</filter-class> </filter> <filter-mapping> <filter-name>FileUpload Filter</filter-name> <servlet-name>Faces Servlet</servlet-name> </filter-mapping> 

Unfortunately, this is not the case. You will need your own MultipartRequest, since you will have to compile a list of FileItems yourself. But stop. We must work with javax.servlet.Part classes that are not compatible with FileItem. So I wrote a new class that connects the two. You can find this class here: http://pastebin.com/JcfAYjey

The final piece of the puzzle is the mentioned MultipartRequest, which links PartItem and FileUploadFilter. I took this class from Primefaces-Repository and changed it as needed (see http://pastebin.com/Vc5h2rmJ ). The difference between lines 47 and 57.

So what you need to do: 1. Create three classes FileUploadFilter, MultipartRequest and PartItem 2. Register the file FileUploadFilter in your web.xml 3. Enjoy!

PLEASE PAY ATTENTION: this is not intended as a solution to solve all problems, but simply a direction that you can take in further implementations. For example, MultipartRequest will only work for parts with the image/* content type. You may need to change this.

Feel free to change the code;) I hope this helps!

EDIT: I forgot to mention one important step. You will also need your own FileIUploadRenderer. The implemented Primefaces use instanceof checking to find MultipartRequest. Since you are using another option, the import must be changed. The rest of the class may remain unchanged ( http://pastebin.com/rDUkPqf6 ). Remember to register it inside your faces-config.xml:

 <render-kit> <renderer> <component-family>org.primefaces.component</component-family> <renderer-type>org.primefaces.component.FileUploadRenderer</renderer-type> <renderer-class><YourPackage>.FileUploadRenderer</renderer-class> </renderer> </render-kit> 
+6
source

The answer lies in the UploadFile getInputstream () method. Do not rely on the getContents () method. This is my simple solution that worked with the glassfish dependencies below 4

  • Main interfaces 4.0.RC1
  • jsf 2.2
  • commons-fileupload 1.3

     private byte[] getFileContents(InputStream in) { byte[] bytes = null; try { // write the inputStream to a FileOutputStream ByteArrayOutputStream bos = new ByteArrayOutputStream(); int read = 0; bytes = new byte[1024]; while ((read = in.read(bytes)) != -1) { bos.write(bytes, 0, read); } bytes = bos.toByteArray(); in.close(); in = null; bos.flush(); bos.close(); bos = null; logger.debug("New file created!"); } catch (IOException e) { System.out.println(e.getMessage()); } return bytes; } getFileContents(getFile().getInputstream()); 
+4
source

Try removing beans.xml (CDI configuration file) and use JSF beans.

+3
source

On the PrimeFaces blog, I saw that full support for JSF 2.2 will come from version 4.0.

+2
source

I think this is a problem with public files. When I debug the code, PrimeFaces UploadFilter correctly runs the Commus-fileupload FileUploadBase.parseRequest method (identical when I use GlassFish 3.1.22 or GlassFish 4), but checking FileItemIterator.hasNext returns false.

+1
source

Source: https://habr.com/ru/post/947701/


All Articles