Formulário dinâmico com upload de arquivos - JSF

Boa noite,

Estou desenvolvendo um projeto onde tenho uma tela de cadastro de treinamentos. Para cada material do treinamento eu incluo um texto com instruções e um arquivo. Estou gerando o formulário dinamicamente através do botão “Adicionar material”.

O problema ocorre na seguinte situação: eu adiciono um material, digito as instruções e seleciono um arquivo e depois disso, eu clico novamente em “Adicionar material”:

Para exibir os campos dinâmicos eu faço o update no formulário. O problema é que o arquivo selecionado anteriormente se perde. Já tentei atualizar somente o último h:panelGrid, mas retorna um erro porque ele ainda não existe quando a página é renderizada. Também tentei ignorar o p:fileUpload no update utilizando o update="@(#formularioTreinamento:not(.noUpdate))" e também não funcionou. Como posso fazer isso funcionar?

Seguem os códigos:

treinamento.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"	
	xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
	xmlns:c="http://java.sun.com/jsp/jstl/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">
	
	<ui:composition template="/WEB-INF/_template.xhtml">
		
		<ui:define name="title">
			Treinamentos
		</ui:define>
		
		<ui:define name="content">
				<h:form id="formularioTreinamento">
					<p:growl id="msgs" showDetail="true" rendered="#{not facesContext.validationFailed}" />
					<fieldset>
						<legend>Cadastrar treinamento</legend>
						<h:panelGrid columns="3">
							<h:outputLabel value="Nome:" for="nomeTreinamento" />
							<h:inputText id="nomeTreinamento" value="#{treinamentoBean.treinamento.nomeTreinamento}" required="true" />
							<p:message for="nomeTreinamento" />
						</h:panelGrid>
					</fieldset>
					
					<fieldset>
						<legend>Materiais do treinamento</legend>
						<ui:repeat value="#{treinamentoBean.treinamento.treinamentoMateriais}" var="material" varStatus="status" id="teste">
							<h:panelGrid columns="4" id="materiais">
								<h:outputLabel value="Instruções:" />
								<p:inputTextarea value="#{material.instrucoes}" rows="6" cols="50" />
								<p:fileUpload id="uploadFileMaterial" value="#{treinamentoBean.uploadedFiles[status.index]}" label="Adicionar arquivo" allowTypes="/(\.|\/)(pdf)$/" mode="simple" skinSimple="true" auto="true" />
								<p:commandButton action="#{treinamentoBean.removerMaterial(material)}" value="Remover" icon="ui-icon ui-icon-closethick" />
							</h:panelGrid>
						</ui:repeat>
						<p:commandButton actionListener="#{treinamentoBean.addMaterial()}" update="formularioTreinamento" value="Adicionar material" style="float: right; margin-bottom: 10px; margin-top: 20px;" />
					</fieldset>
					
					<p:commandButton id="salvarTreinamento" value="Salvar" update="formularioTreinamento:msgs" actionListener="#{treinamentoBean.salvar}" style="float: right; margin: 3px;" />
				</h:form>
		</ui:define>
		
	</ui:composition>
	
</html>

TreinamentoBean.java:

package br.com.mbfarmacias.intranet.bean;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.RowEditEvent;
import org.primefaces.model.UploadedFile;

import br.com.mbfarmacias.intranet.dao.DAO;
import br.com.mbfarmacias.intranet.dao.JPAUtil;
import br.com.mbfarmacias.intranet.model.Treinamento;
import br.com.mbfarmacias.intranet.model.TreinamentoMaterial;

@ManagedBean
@ViewScoped
public class TreinamentoBean {
	private Treinamento treinamento = new Treinamento();
	private List<Treinamento> treinamentos;
	private List<UploadedFile> uploadedFiles;
	
	@PostConstruct
	public void init(){
		EntityManager em = JPAUtil.getEntityManager();
		this.treinamentos = (List<Treinamento>) em.createNamedQuery("Treinamento.findAll", Treinamento.class).getResultList();
		em.close();
		
		this.treinamento.setTreinamentoMateriais(new ArrayList<>());
		this.uploadedFiles = new ArrayList<>();
	}
	
	public void salvar(){
		try{
			new DAO<Treinamento>(Treinamento.class).adiciona(this.treinamento);
			this.treinamento = new Treinamento();
			addMensagem("Sucesso", "Treinamento adicionado", false);
		} catch (Exception e) {
			this.treinamento = new Treinamento();
			addMensagem("Erro", "Treinamento não foi adicionado", true);
		}
	}
	
	public void addMaterial(){
		/*this.treinamentoMateriais.add(new TreinamentoMaterial());
		System.out.println("adicionou: " + treinamentoMateriais.size());*/
		this.treinamento.getTreinamentoMateriais().add(new TreinamentoMaterial());
		System.out.println("adicionou1: " + this.treinamento.getTreinamentoMateriais().size() + "(" + uploadedFiles.size() + ")");
		for (UploadedFile uploadedFile : uploadedFiles) {
			System.out.println("nome: " + uploadedFile.getFileName());
		}
	}
	
	public void removerMaterial(TreinamentoMaterial treinamentoMaterial){
		this.treinamento.getTreinamentoMateriais().remove(treinamentoMaterial);
		System.out.println("removeu: " + this.treinamento.getTreinamentoMateriais().size());
	}
	
	public void apagar(Treinamento treinamento){
		new DAO<Treinamento>(Treinamento.class).remove(treinamento);
		addMensagem("Sucesso", "Treinamento removido", false);
	}
	
	public void atualizar(Treinamento treinamento){
		new DAO<Treinamento>(Treinamento.class).atualiza(treinamento);
		addMensagem("Sucesso", "Treinamento atualizado", false);
	}

	public void onRowEdit(RowEditEvent event) {
		Treinamento treinamento = (Treinamento) event.getObject();
		atualizar(treinamento);
	}
     
    public void onRowCancel(RowEditEvent event) {
    	addMensagem("Edição cancelada","", false);
    }
	
	public void addMensagem(String resumo, String detalhe, boolean erro){
    	if(erro){
    		FacesMessage mensagem = new FacesMessage(FacesMessage.SEVERITY_ERROR, resumo, detalhe);
    		FacesContext.getCurrentInstance().addMessage(null, mensagem);
    	} else{
    		FacesMessage mensagem = new FacesMessage(FacesMessage.SEVERITY_INFO, resumo, detalhe);
    		FacesContext.getCurrentInstance().addMessage(null, mensagem);
    	}
	}

	public Treinamento getTreinamento() {
		return treinamento;
	}

	public void setTreinamento(Treinamento treinamento) {
		this.treinamento = treinamento;
	}

	public List<Treinamento> getTreinamentos() {
		return treinamentos;
	}

	public void setTreinamentos(List<Treinamento> treinamentos) {
		this.treinamentos = treinamentos;
	}

	public List<UploadedFile> getUploadedFiles() {
		return uploadedFiles;
	}

	public void setUploadedFiles(List<UploadedFile> uploadedFiles) {
		this.uploadedFiles = uploadedFiles;
	}
}

Alguém tem alguma sugestão?

Faça a adição de um novo upload via jquery