JSF 2 + PrimeFaces + Jasper

14 respostas
Z

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!

14 Respostas

Scoobydoo

Podes colocar o código todo do JSF…

R

Para setar o titulo vc pode fazer assim:

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

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>
Z

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

Scoobydoo

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.

R

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

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();
		}
	}
Z

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.
=/

Scoobydoo

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>

T

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

Z

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>
Z

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>
Z

help? :frowning:

Z

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!

eduardo_whip_cotia

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.

Criado 14 de maio de 2012
Ultima resposta 13 de set. de 2013
Respostas 14
Participantes 5