[contribuicao] Quer integrar o Jasper com o SEAM?

8 respostas
rodrigoy

Pra quem usa o SEAM e não gosta de fazer relatórios na mão com tags facelets segue uma contribuição:

package view;

import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;

import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory;

import org.jboss.seam.annotations.In;
import org.jboss.seam.core.FacesMessages;
import org.jboss.seam.pdf.DocumentData;
import org.jboss.seam.pdf.DocumentStore;
import org.jboss.seam.pdf.DocumentData.DocType;

/**
 * Esta é uma classe utilitária para exibir relatórios como PDF no Jboss SEAM.
 * 
 * @author rodrigoy
 */
public abstract class ReportAction {

	@In
	FacesMessages facesMessages;
	
	@In
	EntityManager manager;
	
	@In(value = "org.jboss.seam.pdf.documentStore", create = true)
	DocumentStore documentStore;

	/**
	 * Retorna o caminho para o relatório (arquivo ".jasper"). Esses arquivos 
	 * ficam armazenados em /view/report. Assim sendo, esse método deve retornar
	 * algo como:
	 * 
	 *  "/report/listaDocumento.jasper"
	 *  
	 * @return String contendo o caminho para o relatório.
	 */
	protected abstract String getReportPath();

	/**
	 * Refere-se aos parâmetros específicos do relatorio, geralmente constituído
	 * de informações que vieram da tela ou do contexto. Uma implementação exemplo
	 * seria:
	 * 
	 * 	Map<String, Object> params = new HashMap<String, Object>();
	 *	params.put("projetoId", projeto.getId());
	 * 	return params;
	 * 
	 * @return Map<String, Object> com os parâmetros.
	 */
	protected abstract Map<String, Object> getParams();
	
	@SuppressWarnings("deprecation")
	public String print() {
		
		String reportUrl = getReportPath();  
		
		try {
			Map<String, Object> params = new HashMap<String, Object>();
			
			// o entity manager deve ser informado para o Jasper
			params.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER, manager);
	
			// obter os parâmetros específicos do relatório
			params.putAll(getParams());
			
			// obter o caminho real (file system) para o relatório
			FacesContext facesContext = FacesContext.getCurrentInstance();
			HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
			String reportUrlReal = request.getRealPath(reportUrl);
	
			// imprimir o relatório para um stream em PDF
			JasperPrint jasperPrint = JasperFillManager.fillReport(reportUrlReal, params);
			ByteArrayOutputStream output = new ByteArrayOutputStream();
			JasperExportManager.exportReportToPdfStream(jasperPrint, output);
			
			// armazenar o relatório do DocumentStore do SEAM
			String reportId = documentStore.newId();
			DocumentData data = new DocumentData("Report #" + reportId , DocType.PDF, output.toByteArray());
			documentStore.saveData(reportId, data);
			
			// retornar para o caminho padrão do SEAM para exibição de relatórios
			return "/seam-doc?docId=" + reportId;
	
		} catch (Exception e) {
			facesMessages.addFromResourceBundle("ERRO_RELATORIO", 
					new Object[] {reportUrl, e.getMessage()});
			return null;
		}
	}
}

Uso:

package view;

import java.util.HashMap;
import java.util.Map;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;

import view.ReportAction;
import domain.Projeto;

@Name ("listaDocumentoReport")
public class ListaDocumentoReport extends ReportAction {

	@In
	Projeto projeto;

	@Override
	protected String getReportPath() {
		return "/report/listaDocumento.jasper";
	}

	@Override
	protected Map<String, Object> getParams() {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("projetoId", projeto.getId());
		return params;
	}
}

Na página xhtml:

<h:commandLink id="imprimir" value="#{messages.Imprimir}" action="#{listaDocumentoReport.print}"/>

Motivo: Fazer relatórios na mão é um saco. Use o iReport.

Débitos Técnicos:

  • 1 decapreted em getRealPath
  • Chumbamento em new DocumentData(“Report #” + reportId

Débitos Funcionais:

  • Fazer injetar diretamente do contexto Seam para o Jasper
  • Gerar outras coisas além de PDF

8 Respostas

J

Fiz o exemplo e deu o seguinte erro:

Exception during request processing: javax.servlet.ServletException: #{capaDeProcessoReport.print}: java.lang.IllegalArgumentException:[b] could not set field value[/b]: capaDeProcessoReport.org.jboss.seam.pdf.documentStore

Caused by: [color=blue]java.lang.IllegalArgumentException[/color]: Could not set field value by reflection: ReportGenerator.documentStore on: br.gov.pa.protocolo.ui.relatorio.processo.CapaDeProcessoReport with value: class org.jboss.seam.pdf.DocumentStore_$$_javassist_25

Alguem pode pq?

rodrigoy

Este teste funciona no Seam 1.2.1. Que versão vc está usando?

J

Estou usando o Seam 1.2.1

J

É preciso alguma configuracao no web.xml?
Ver o Link: http://www.redhat.com/docs/manuals/jboss/jboss-eap-4.3/doc/seam/Seam_Reference_Guide/html-single/index.html#Seam_Reference_Guide-iText_PDF_generation-Configuring_iText

J

Quais as LIB necessarias?

cleverson.sacramento
jbrunoribeiro:
Fiz o exemplo e deu o seguinte erro:
Exception during request processing: javax.servlet.ServletException: #{capaDeProcessoReport.print}: java.lang.IllegalArgumentException:[b] could not set field value[/b]: capaDeProcessoReport.org.jboss.seam.pdf.documentStore

Caused by: [color=blue]java.lang.IllegalArgumentException[/color]: Could not set field value by reflection: ReportGenerator.documentStore on: br.gov.pa.protocolo.ui.relatorio.processo.CapaDeProcessoReport with value: class org.jboss.seam.pdf.DocumentStore_$$_javassist_25

Alguem pode pq?

Experimente colocar jboss-seam-pdf.jar, itext.jar e jasperreports*.jar como biblioteca do EAR, e não como biblioteca do WAR. Certifique-se que elas não estão nos dois lugares ao mesmo tempo (lib do EAR e do WAR).

fabiocsilva

Eu utilizei um código semelhante para gerar um relatório na minha aplicação, mas o redirecionamento “seam-doc?docid=…” gera um erro 404, e no log aparece

14:46:53,877 WARN  [lifecycle] phase(RENDER_RESPONSE 6,com.sun.faces.context.FacesContextImpl@170848) threw exception: java.lang.NullPointerException null
org.jboss.seam.pdf.DocumentStorePhaseListener.sendContent(DocumentStorePhaseListener.java:47)
org.jboss.seam.pdf.DocumentStorePhaseListener.beforePhase(DocumentStorePhaseListener.java:37)

Alguém sabe o que significa esse erro ?

juniorsatanas

Para que serve ? JRJpaQueryExecuterFactory

O Eclipse ta dando erro nisto!

Criado 7 de dezembro de 2007
Ultima resposta 20 de jul. de 2012
Respostas 8
Participantes 5