JSF 2 + PrimeFaces + Jasper

Fala galera! Bão?
Procurei no forum mas não encontrei algo parecido.

Tô com dois problemas ao gerar/chamar meu arquivo via JSF 2:
1 - Por um botão, preciso chamar meu método e ao final fazer o download do arquivo gerado por ele.
2 - O nome do arquivo no download está sempre “application_pdf” mesmo setando o nome correto.

Com o código abaixo eu consigo o que eu preciso para o meu 1 problema, porém, não é atualizado o “update”, ou seja, a mensagem nunca é atualizada, nem no caso de sucesso, nem ao dar erro e é jogado o exception na tela do usuário:

<p:commandButton value="#{rotulo.confirmar}" actionListener="#{familiasHabilitadasObservacaoMBean.gerarRelatorio}" ajax="false" update=":mensagens">
					<p:fileDownload name="fileName" value="#{familiasHabilitadasObservacaoMBean.arquivo}"/>
				</p:commandButton>

Meu método:

public void gerarRelatorio() {
		try {
			List<Map<String, Object>> lstFamilias = familiasHabilitadasObservacaoService
					.consultarFamiliasHabilitadasObservacao(empreendimentoSelecionado, parcelaSelecionado,
							ordenarPorSelecionado);
			
			if (lstFamilias.isEmpty()){
				addMessage(FacesMessage.SEVERITY_ERROR, "Nenhum registro encontrado.");
				return;
			}
			
			List<Integer> lstAux = new ArrayList<Integer>(); 														
			lstAux.add(0);
			
			String titulo = RelatorioConstants.TIT_FAMILIAS_HABILITADAS_OBSERVACAO;

			EmpreendimentoEntity dadosEmpreendimento = (EmpreendimentoEntity) ReflectionUtils
					.findFromListById(lstEmpreendimento, empreendimentoSelecionado.getIdentEmpreend(),
							"identEmpreend");
			String subTitulo = dadosEmpreendimento.getNomeEmpreend();

			FacesContext facesContext = FacesContext.getCurrentInstance();
			ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();
			String pathRel = servletContext.getRealPath("/WEB-INF/classes/");
			String pathImg = servletContext.getRealPath("/imagens/logo_cdhu.gif");

			Map<String, Object> parametros = new HashMap<String, Object>();
			parametros.put("dados", lstFamilias);
			parametros.put("titulo", titulo);
			parametros.put("subTitulo", subTitulo);
			parametros.put("SUBREPORT_DIR", pathRel);
			parametros.put("pathImg", pathImg);

			arquivo = super.gerarRelatorio(
					"familiasHabilitadasObservacao/familiasHabilitadasObservacao.jasper", lstAux,
					parametros, FormatoExportacaoEnum.PDF, "familiasHabilitadasObservacao.pdf");

			addMessage(FacesMessage.SEVERITY_INFO, "Relatório gerado com sucesso.");
		} catch (BCException e) {
			addMessage(FacesMessage.SEVERITY_ERROR, "Erro ao gerar relatório.");

		} catch (Exception e) {
			addMessage(FacesMessage.SEVERITY_ERROR, "Erro ao gerar relatório.");
		}

Método pai:

public StreamedContent gerarRelatorio(String templatePath, List objects, Map<String, Object> parametros,
			FormatoExportacaoEnum formatoExportacao, String nomeSaida) throws BCException, JRException {

		InputStream relatorio = null;

		try {
			
			ByteArrayOutputStream byteArrayOutStream = new ByteArrayOutputStream();
			JRDataSource lista = new JRBeanCollectionDataSource(objects);
			JasperReport jasperReport = (JasperReport) JRLoader.loadObject(RelatorioMBean.class.getClassLoader()
					.getResourceAsStream(templatePath));
			jasperReport.setWhenNoDataType(WhenNoDataTypeEnum.ALL_SECTIONS_NO_DETAIL);
			JasperPrint print = JasperFillManager.fillReport(jasperReport, parametros, lista);
			JRExporter exporter = null;
			switch (formatoExportacao) {
			case PDF:
				exporter = new net.sf.jasperreports.engine.export.JRPdfExporter();
				break;
			case XML:
				exporter = new net.sf.jasperreports.engine.export.JRXmlExporter();
				break;
			case XLS:
				exporter = new net.sf.jasperreports.engine.export.JRXlsExporter();
				break;
			case CSV:
				exporter = new net.sf.jasperreports.engine.export.JRCsvExporter();
				break;
			case HTML:
				exporter = new net.sf.jasperreports.engine.export.JRHtmlExporter();
				break;
			default:
				exporter = new net.sf.jasperreports.engine.export.JRPdfExporter();
				break;
			}
			exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, byteArrayOutStream);
			exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
			exporter.exportReport();
			relatorio = new ByteArrayInputStream(byteArrayOutStream.toByteArray());
		} catch (JRException ex) {
			LOG.error("Error : " + ex);
			throw ex;
		}
		return new DefaultStreamedContent(relatorio, formatoExportacao.getContentType(), nomeSaida);
	}

Se alguém tiver uma ideia de como solucionar esses dois problemas, agradeceria bastante!
Valeww!

Podes colocar o código todo do JSF…

Para setar o titulo vc pode fazer assim:

response.setHeader("content-disposition",
			"attachment;filename=Nome.pdf");

Scoobydoo, segue:

<ui:composition template="/template.xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">
	<ui:define name="principal">
		<h:form>
			<p:panel header="#{rotulo.relatorioFamiliasHabilitadasObservacaoTitulo}">
				<h:panelGrid columns="2">

					<h:outputLabel value="#{rotulo.relatorioCodigoEmpreendimento}:" />
					<h:inputText value="#{familiasHabilitadasObservacaoMBean.codigoEmpreendimento}">
	   					<p:ajax event="change" update="messages, comboMunicipio, comboEmpreendimento, comboParcela" listener="#{familiasHabilitadasObservacaoMBean.carregaEmpreendimentoPorCodigoEmpreendimento}"  />
       				</h:inputText>
					
					<h:outputLabel value="#{rotulo.municipio}:" />
					<h:selectOneMenu label="#{rotulo.municipio}" id="comboMunicipio" value="#{familiasHabilitadasObservacaoMBean.municipioSelecionado.identMun}">
						<f:selectItem itemLabel="" itemValue="" />
						<f:selectItems value="#{familiasHabilitadasObservacaoMBean.lstMunicipio}" var="item" itemLabel="#{item.nomeMunicipio}" itemValue="#{item.identMun}" />
						<p:ajax update="messages, comboEmpreendimento, comboParcela" listener="#{familiasHabilitadasObservacaoMBean.carregaEmpreendimentoPorMunicipio}" />
					</h:selectOneMenu>
					
					<h:panelGroup>
						<span style="color: red;">* </span>
						<h:outputLabel value="#{rotulo.empreendimento}:" />
					</h:panelGroup>
					<h:selectOneMenu label="#{rotulo.empreendimento}" required="true" id="comboEmpreendimento" value="#{familiasHabilitadasObservacaoMBean.empreendimentoSelecionado.identEmpreend}">
						<f:selectItem itemLabel="" itemValue="" />
						<f:selectItems value="#{familiasHabilitadasObservacaoMBean.lstEmpreendimento}" var="item" itemLabel="#{item.nomeEmpreend}" itemValue="#{item.identEmpreend}" />
						<p:ajax update="messages, comboParcela" listener="#{familiasHabilitadasObservacaoMBean.carregaParcelaPorEmpreendimento}" />
					</h:selectOneMenu>

					<h:outputLabel value="#{rotulo.parcela}:" />
					<h:selectOneMenu label="#{rotulo.parcela}:" id="comboParcela" value="#{familiasHabilitadasObservacaoMBean.parcelaSelecionado.identParcEmpreend}">
						<f:selectItem itemLabel="" itemValue="" />
						<f:selectItems value="#{familiasHabilitadasObservacaoMBean.lstParcela}" var="item" itemLabel="#{item.numParcEmpreend}" itemValue="#{item.identParcEmpreend}" />
					</h:selectOneMenu>

					<h:outputLabel value="#{rotulo.ordenarPor}:" />
					<h:selectOneMenu label="#{rotulo.ordenarPor}:" value="#{familiasHabilitadasObservacaoMBean.ordenarPorSelecionado}">
						<f:selectItem itemLabel="" itemValue=""/>
						<f:selectItems value="#{familiasHabilitadasObservacaoMBean.lstOrdenarPor}"
							var="item" itemLabel="#{item.descricao}" itemValue="#{item}" />
					</h:selectOneMenu>

					<p:spacer />
					<p:spacer height="20" />

				</h:panelGrid>
				<p:commandButton value="#{rotulo.limpar}" type="reset" />
				<p:spacer width="10"/>
				<p:commandButton value="#{rotulo.confirmar}" actionListener="#{familiasHabilitadasObservacaoMBean.gerarRelatorio}" ajax="false" update=":mensagens">
					<p:fileDownload name="fileName" value="#{familiasHabilitadasObservacaoMBean.arquivo}"/>
				</p:commandButton>			
			</p:panel>
		</h:form>
	</ui:define>
</ui:composition>

Desculpe raf4ever, será funcionaria nessa estrutura?
Onde devo incluir exatamente?

Analisei o código e está tudo dentro do padrão PrimeFaces, se o problema 1 foi resolvido, tente mudar o update de :mensagens para mensagens, sem o “:” .
Não creio que seja isso mas nunca se sabe os bugs que ocorrem no quesito programação rsrsrs…
Note que você está dando um refresh na página por causa do ajax=“false”, faz um teste colocando para true.

[quote=zitiii]Desculpe raf4ever, será funcionaria nessa estrutura?
Onde devo incluir exatamente?[/quote]

Exemplo completo:

public void imprimirFormulario() throws IOException{
		try {
			ServletContext ctx = (ServletContext) FacesContext
			.getCurrentInstance().getExternalContext().getContext();
			File f = new File(ctx.getRealPath("/publicacoes/formulario.pdf"));
			
			HttpServletResponse response = (HttpServletResponse) FacesContext
			.getCurrentInstance().getExternalContext().getResponse();
			response.setContentType("application/pdf");
			response.setHeader("content-disposition",
			"attachment;filename=Formulario.pdf");
			byte[]bytes = bytesFromFile(f);
			response.setContentLength(bytes.length);
			ServletOutputStream servletStream = response.getOutputStream();
			servletStream.write(bytes, 0, bytes.length);
			servletStream.flush();
			servletStream.close();
			FacesContext.getCurrentInstance().responseComplete();
		}catch(Exception e){
			e.printStackTrace();
		}
	}

Bom galera, o problema 2 (do nome) foi solucionado, foi um vacilo:
Tava invertido o return:

return new DefaultStreamedContent(relatorio, formatoExportacao.getContentType(), nomeSaida);

“formatoExportacao.getContentType(),” com “nomeSaida”

Mas o problema 1 continua, a mensagem não aparece…
Scoobydoo, tirei os dois pontos e nada, troquei pra “true” e a tela não saí do “Aguarde”, ou seja, trava.
=/

A função gerarRelatorio(); chega até o final ou ocorre algum erro no meio do caminho?
Coloca um id pro teu <p:panel ID="PANEL_RELATORIO" header="#{rotulo.relatorioFamiliasHabilitadasObservacaoTitulo}">
E no update coloca esse id

<p:commandButton value="#{rotulo.confirmar}" actionListener="#{familiasHabilitadasObservacaoMBean.gerarRelatorio}" ajax="false" update=":mensagens,:PANEL_RELATORIO"> <p:fileDownload name="fileName" value="#{familiasHabilitadasObservacaoMBean.arquivo}"/> </p:commandButton>

Bom dia, amigo!

Onde vc coloca suas mensagens que deveriam ser exibidas?
E onde vc exibe?

Vc pode dar um reRender na div onde vc exibe as mensagens…ja experimentou? :smiley:

Abs

independente se a função chegar até o final ou não ela não mostra as mensagens, ou seja, se ela chega ao final, o relatório é gerado, se dá erro no meio, a exception é jogada na tela.

o “:mensagens” é um id do template que utilizo:

<?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:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.org/ui">
	<h:head>
		<style type="text/css">
	BODY {
		font-size: 11px;
	}
	
	TD {
		font-size: 11px;
	}
	
	DIV {
		font-size: 11px;
	}
	
	TH {
		font-size: 11px;
		white-space: normal !important;
	}
	
	.ui-growl {
		right: 40%;
		top: 40%;
		color: #FF0000;
	}
	</style>
	
		<title>CDHU - Habilitação</title>
	</h:head>
	<h:body>
		<f:view contentType="text/html"
				locale="#{facesContext.externalContext.request.locale}">
	
			<table>
				<tr>
					<td>
						<ui:insert name="menu">
							<ui:include src="menu.xhtml" />
							<p:ajaxStatus onstart="statusDialog.show();"
										  onsuccess="statusDialog.hide();" />
							<p:dialog modal="true" widgetVar="statusDialog" header="Aguarde"
									  draggable="false" closable="false">
								<p:graphicImage value="/imagens/ajax-loader.gif" />
							</p:dialog>
						</ui:insert> 
						<ui:insert name="mensagens">
							<h:form id="mensagens">
								<p:messages id="msgs" />
							</h:form>
						</ui:insert>
					</td>
				</tr>
				<tr>
					<td><ui:insert name="principal" /></td>
				</tr>
			</table>
		</f:view>
	</h:body>
</html>

pensei no “p:remoteCommand”
chamar ele após o término, mas também não funcionou:

<p:commandButton value="teste" action="#{familiasHabilitadasObservacaoMBean.gerarRelatorio}" ajax="true" update="mensagens" onclick="lazyload()" />                        
			    <p:remoteCommand name="lazyload">  
			       <p:fileDownload value="#{familiasHabilitadasObservacaoMBean.arquivo}" />
			    </p:remoteCommand>  

help? :frowning:

Da forma abaixo funciona perfeitamente, no entanto, preciso utilizar 2 botões:

<p:commandButton value="#{rotulo.confirmar}" action="#{familiasHabilitadasObservacaoMBean.gerarRelatorio}" ajax="true"  update="mensagens" />                        
<p:commandButton value="Download" ajax="false">                        
        <p:fileDownload value="#{familiasHabilitadasObservacaoMBean.arquivo}"/>  
</p:commandButton>

O primeiro botão precisa do “ajax=true” para atualizar a mensagem e o segundo do “ajax=false” para fazer o download.
Acredito que aí esteja o problema.

Alguém saberia uma forma de juntar esses dois botões?
Muito obrigado galera!

Caros, boa noite.

Estou com um problema parecido.

Só que meu caso quando faço do download do PDF não consigo atualizar a pagina.

Quando atualizo a pagina não consigo fazer download.

Acredito que não sou o único que passou ou esta passando por isso.

Tenho dois botoes na tela.

1 - Um faz o download mas não atualiza a pagina.

2 - O segundo atualizar a pagina mas não faz o download.

Quero fazer o download e em seguida atualizar a minha table.

Alguém já fez isso?

Desde já agradeço.