VRaptor 3 - JasperMaker (para JasperReporter)

26 respostas
Lavieri

Uma solução para transformar o resultado do jasperReporter em um download no browser... escolhendo nome, e podendo ou não forçar download.
além de oder enviar parametros, e enviar uma Coleção como DataSource

http://pastebin.com/8ABRRHE7

coloca esse componente no seu projeto

e dentro da sua lógica faz assim

@Resrouce
public class MeuController{
     private final JasperMaker jasperMaker;
     
     //Injeta no construtor o jasperMaker
     public MeuController(JasperMaker jasperMaker) {
          this.jasperMaker = jasperMaker
     }

    
     public Download minhasLogica() {
           //aqui vc monta a coleção para ser usada como DataSource no jasper
           //e coloca seus parametros (se quiser) em um mapa de parametros...

           return jasperMaker.makePdf(
               "seuArquivoJasper.jasper",
               suaColecaoComOsBeansParaDataSource, 
               "nomeDoArquivoQueSeraExibidoParaUsuario.pdf", 
               desejaForcarODownload, 
               opicionalmenteObjetosParametrosPodemSerEnviadosOuNao);
     }
}

Pronto.... é isso

por padrão, o jasperMaker usa a pasta "WEB-INF/jasper/" para procurar seus arquivos *.jasper

caso queria trocar esse lugar padrão, é só trocar o lugar no web.xml colocando o seguinte

<context-param>
	<param-name>vraptor.jasperMaker</param-name>
	<param-value>WEB-INF/jasper/</param-value>
</context-param>

caminho que inicia com "/" é conciderado caminho absoluto da maquina
caminho que inicia sem a barra, que é o caso do exemplo que passei, usa como base o caminho do contexto, ou seja, o caminho do seu WebContent

dentro do jasper, vc vai ter dois parametros pra usar se quiser... o 1° é o "jasperPath" que contémo caminho para a pasta dos arquivos .jasper, que é útil para sub-relatorios, e o 2° é o "contextPath" que é o caminho do WebContent, e é útil pra encontrar qualquer arquivo dentro do container web.

é isso

boa sorte pra quem for usar

Agradecimentos ao Lucas, que ajudou a colocar o resultado do jasper dentro do objeto Download do vraptor.

Libs necessários para usar jasper, com essa solução (pelomenos as que eu precisei)
- commons-digester-1.7.jar
- commons-beanutils-1.7.0.jar
- groovy-all-1.5.5.jar
- iText-2.1.0.jar
- jasperreports-3.7.0.jar

26 Respostas

Guevara

Oi Lavieri!
Estou usando o JasperMaker, agora preciso criar um form para passar parâmetro e gerar o relatório com os parâmetros passado:

public Download geraRelatorioImoveisProprietario(Proprietario proprietario) {
	      //aqui vc monta a coleção para ser usada como DataSource no jasper
	      //e coloca seus parametros (se quiser) em um mapa de parametros...	
		List<Imovel> imoveis = imovelDAO.lista();
	      return jasperMaker.makePdf(
	      "relatorioImoveis.jasper",
	      imoveis, 
	      "relatorio-imoveis-proprietario.pdf", 
	      true, proprietario.getIdProprietario()); // passagem de parâmetros
	}

Como eu poderia passar parâmetros ali? Outra dúvida é quanto a subrelatório, fiz um aqui pra teste, ao chamar o relatório principal o subrelatório será chamado automáticamente?
Abraço!! o/

Lavieri

Guevara:
Oi Lavieri!
Estou usando o JasperMaker, agora preciso criar um form para passar parâmetro e gerar o relatório com os parâmetros passado:

public Download geraRelatorioImoveisProprietario(Proprietario proprietario) {
	      //aqui vc monta a coleção para ser usada como DataSource no jasper
	      //e coloca seus parametros (se quiser) em um mapa de parametros...	
		List<Imovel> imoveis = imovelDAO.lista();
	      return jasperMaker.makePdf(
	      "relatorioImoveis.jasper",
	      imoveis, 
	      "relatorio-imoveis-proprietario.pdf", 
	      true, proprietario.getIdProprietario()); // passagem de parâmetros
	}

Como eu poderia passar parâmetros ali? Outra dúvida é quanto a subrelatório, fiz um aqui pra teste, ao chamar o relatório principal o subrelatório será chamado automáticamente?
Abraço!! o/

vc tem que criar um MAP, e dentro do map colocar, a srtring do nome do parametro no chave, e o objeto que será enviado como parametro no value.

veja a assinatura do método

public Download makePdf(String jasperFile,Collection<?> dataSource, String fileName, boolean doDownload, Map<String,Object> parametros) { //... }

como pode ver Map<String,Object> parametros

os sub-relatórios são chamados pelo jasper, elechama automaticamente, só colocar o caminho relativo, e os manter na mesma pasta do relatório principal.

Guevara

Beleza Lavieri! Consegui gerar o relatório, mas só veio o que têm os dados do proprietário, o subrelatório com os dados do imóvel que ele possui não veio. Lá no iReport ao criar o subrelatório, foi gerado outro jasper e os dois estão juntos na mesma pasta jasper do projeto. Preciso colocar mais alguma coisa no método ou era pra ter puxado automáticamente o subrelatório?
Veja como estão:

Abraço!!

Lavieri

Guevara:
Beleza Lavieri! Consegui gerar o relatório, mas só veio o que têm os dados do proprietário, o subrelatório com os dados do imóvel que ele possui não veio. Lá no iReport ao criar o subrelatório, foi gerado outro jasper e os dois estão juntos na mesma pasta jasper do projeto. Preciso colocar mais alguma coisa no método ou era pra ter puxado automáticamente o subrelatório?
Veja como estão:

Abraço!!

na referencia do seu relatório principal, para o subrelatório, tem que estar o caminho relativo, e não o absoluto…

ou então vc pode colcar “P{jasperPath}relProprietarios_subreportImovel.jasper”

confira o nome, posso ter digitado errado… o P{jasperPath} para usar ele, vc precisa declarar a propriedade no relatorio principal, colocando ela como string.

o parametro jasperPath é enviado automaticamente para o jasper, quando usado esse código q desenvolvi.

Guevara

Oi Lavieri!
Pelo iReport está trazendo os dados dos dois, mas pela aplicação não.

No Controller, estou passando a id assim:

public Download geraRelatorioProprietarios(Long idProprietario) {	
		List<Proprietario> proprietarios = proprietarioDAO.lista();		
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("idProprietario", idProprietario); // passo a id do proprietario pro relatorio Master, deveria repassar pro subrelatorio

	      return jasperMaker.makePdf(
	      "relProprietarios.jasper",
	      proprietarios, 
	      "relatorio-proprietarios.pdf", 
	      true,
	      map 
	   );
	}

Parece que o subrelatório não está recebendo a id do Master.

Veja como consegui linkar os dois usando HQL:
http://www.guj.com.br/posts/list/218802.java

Abraço!

Guevara

Continuo com o problema, testei agora passando o CPF como parâmetro, no iReport o subrelatório é embutido no Master, mas pelo JasperMaker não. Só vêm os dados do proprietário. =/

public Download geraRelatorioImoveisProprietario(Proprietario proprietario) {
		  List<Proprietario> prop = proprietarioDAO.getImoveisPorCpf(proprietario);
		  Map<String, Object> map = new HashMap<String, Object>(); 
		  map.put("cpf", proprietario.getPessoa().getCpf());		  
		  return jasperMaker.makePdf(
		  "relImoveisProprietario.jasper",
		  prop, 
		 "relatorio-imoveis-proprietario.pdf", 
		  true,
		  map 
	   );
	}

Abraço!

Guevara

Relatório feito no iReport:

Refiz o relatório umas 5 vezes, mas pelo JasperMaker só vêm os dados do proprietário. =/

Lá no iReport coloquei assim o “subreport expression”:

$P{SUBREPORT_DIR} + "relImoveisProprietario_subreport.jasper"

O jrxml do Master na parte do sburelatório está assim:

<subreport>
				<reportElement x="0" y="97" width="555" height="53"/>
				<parametersMapExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}]]></parametersMapExpression>
				<subreportParameter name="SUBREPORT_DIR">
					<subreportParameterExpression><![CDATA[$P{SUBREPORT_DIR}]]></subreportParameterExpression>
				</subreportParameter>
				<subreportParameter name="cpf">
					<subreportParameterExpression><![CDATA[$P{cpf}]]></subreportParameterExpression>
				</subreportParameter>
				<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
				<subreportExpression class="java.lang.String"><![CDATA[$P{SUBREPORT_DIR} + "relImoveisProprietario_subreport.jasper"]]></subreportExpression>
			</subreport>

Deve ser ai que o JasperMaker não está achando o caminho para o subrelatório…

Abraço!

Lavieri

é algo assim

Obs.: eu não fiz pelo XML, eu fiz pelo jasper reporter mesmo, abre o IReport, e configurei o subrelatorio

&lt;subreport&gt;
	&lt;reportElement mode="Opaque" x="0" y="0" width="595" height="5"&gt;
		&lt;printWhenExpression&gt;&lt;![CDATA[$P{contador}.renderiza($P{mensuracao}.getT(),$F{this})]]&gt;&lt;/printWhenExpression&gt;
	&lt;/reportElement&gt;
	&lt;subreportParameter name="dateUtil"&gt;
		&lt;subreportParameterExpression&gt;&lt;![CDATA[$P{dateUtil}]]&gt;&lt;/subreportParameterExpression&gt;
	&lt;/subreportParameter&gt;
	&lt;subreportParameter name="counter"&gt;
		&lt;subreportParameterExpression&gt;&lt;![CDATA[$P{contador}]]&gt;&lt;/subreportParameterExpression&gt;
	&lt;/subreportParameter&gt;
	&lt;dataSourceExpression&gt;&lt;![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource(java.util.Collections.singletonList($F{this}))]]&gt;&lt;/dataSourceExpression&gt;
	&lt;subreportExpression class="java.lang.String"&gt;&lt;![CDATA[$P{jasperPath} + ($F{this} != null ? $P{resolver}.getSubRelatorio($F{this}): "GEOR-FichaMensuracao_ABERTA.jasper")]]&gt;&lt;/subreportExpression&gt;
&lt;/subreport&gt;

o que importa mesmo desse trecho todo ???

E o que importa desse trecho menor ??

ou seja, no link do subreporter eu aponto como sendo

isso quer dizer que, ele vai usar como o relatorio de subreporter a pasta passada no argumento jasperPath + o nome do subreporter

Lavieri

se vc quer usar, $P{SUBREPORT_DIR} vc precisa passar esse parametro para dentro do jasper…

o parametro que eu passo é o $P{jasperPath}

Guevara

Tá brabo, deixei parecido com o seu, só que além do cpf, pede o jasperPath, preencho o cpf e me pede o jasperPath, deixando em branco ou colocando o nome do subrelatório, só vêm os dados do proprietário:

<subreport>
				<reportElement x="0" y="97" width="555" height="53"/>
				<parametersMapExpression><![CDATA[$P{cpf}]]></parametersMapExpression>
				<subreportParameter name="cpf">
					<subreportParameterExpression><![CDATA[$P{cpf}]]></subreportParameterExpression>
				</subreportParameter>
				<dataSourceExpression><![CDATA[$P{jasperPath} + "relImoveisProprietario_subreport.jasper"]]></dataSourceExpression>
			</subreport>

Tava querendo usar o $P{SUBREPORT_DIR}, ai eu substituo no lugar do jasperPath criado? Crio lá SUBREPORT_DIR?

Eu preciso usar esta configuração que está funcionando no JasperMaker:

Com essa configuração vêm td certo.
Valeu!!

Lavieri

nop, se pareceu brabo devo ter me expressado errado ^^…

Guevara:
Com essa configuração vêm td certo.
Valeu!!

se funcionou agora então blz ^^

Guevara

Não não :smiley:
Está perfeito no iReport, no JasperMaker vêm só os dados do proprietário, os dados dos imóveis não vêm. hehehe
Por algum motivo o JasperMaker não traz os imóveis com aquela configuração do print. =/

Lavieri

o que deve estar faltando então é o campo “Data Source Expression”, no meu caso o meu valor é

no seu pode ser outra coisa… ^^

Guevara

Então Lavieri, como eu tenho um atributo em Proprietario List imoveis, usei imoveis como data source:
connection type:

Use a datasource expression

Data Source Expression

new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{imoveis})

Mesmo assim os dados dos imóveis não são puxados.

Guevara

Consegui Lavieri!
Era isso ai que acabei de passar mesmo, o “imoveis” é passado como data source pro subrelatório, o que precisava era deletar a query que ainda estava no subrelatório. heheh
Valeu pela força!!
Abraço!!!

juniorsatanas

Guevara BOA TARDE !

Esse projeto que vc ta fazendo é o WebChat ?

Onde ta os fontes ?

jr

Lucas_Cavalcanti

Lavieri, não quer colocar esse plugin no vraptor-contrib, por favor?

pode ser em outro repositório do git, daí eu adiciono como submodulos

juniorsatanas

Lavieri Cara esse plugin e uma mae ! nossa

PARABÉNS ! tu tem um DEMO usando ele ?

jr

A

A classe JasperMaker tem como argumento no construtor um ServletContext
Como vocês criaram o ServletContext para passar para o teste junit?

S

Oi,

Eu estou usando esse código para gerar relatórios e enviar para o browser para o utilizador fazer o download mas não estou conseguindo. Ele passa no código sem problemas mas depois não envia nada para o browser. :cry:
O que pode ser?

@Path({"","/"})
     public Download getConsentimentoReport(int id_episodio) {
           Collection<Consentimento> consentimento = consentimentoDAO.getListaConsentimento(id_episodio);
           return jasperMaker.makePdf(
               "report1.jasper",
               consentimento, 
               "teste.pdf", 
               true);
     }
Lucas_Cavalcanti

o relatório está escrevendo alguma coisa?

a tela fica em branco?

tem certeza que vc quer colocar isso no path / ? (ou o controller tá anotado com @Path tb?)

S

ele não está fazendo nada, não escreve, não dá erro, nem lança o download. Se eu for direto pelo link do controller ele faz o download do relatorio. Já tentei usar um servlet em vez do Vraptor mas o resultado é o mesmo. Ah, eu estou a usar o Extjs4 para fazer a chamada ao controller e ao servlet. Provavelmente deve ser no tratamento da resposta que eu não estou a conseguir gerar o download do pdf. :frowning:

Lucas_Cavalcanti

isso não vai funcionar do jeito que vc quer…

vc tem que colocar o link direto pro controller. Tente mudar aquele true pra false, daí o browser pode escolher mostrar o pdf direto nele.

S

Oi, obrigado pela ajuda. Mas não resultou ainda :| O meu controller está assim agora:

@Resource
@Path("/Report")
public class ReportController{
     private final JasperMaker jasperMaker;
     private ConsentimentoDAO consentimentoDAO;
     private Result result;
     private Session session;
     private ServletContext context;

     //Injeta no construtor o jasperMaker
     public ReportController(Result result, JasperMaker jasperMaker, ConsentimentoDAO consentimentoDAO, Session session, HttpServletResponse response, ServletContext context) {
          this.result = result;
          this.jasperMaker = jasperMaker;
          this.consentimentoDAO = consentimentoDAO;
          this.session = session;
          this.context = context;
     }
     @Get
     @Path({"/GetConsentimentoReport"})
     public Download getConsentimentoReport(int id_episodio) {
           Collection<Consentimento> consentimento = consentimentoDAO.getListaConsentimento(id_episodio);
           return jasperMaker.makePdf(
               "report1.jasper",
               consentimento, 
               "teste.pdf", 
               false);
           
     }

Ele corre no Extjs4 sem qualquer erro mais não mostra nada, nem pede para fazer download. Mas se eu abrir o browser e colocar o endereço minhaApp/Report/GetConsentimentoReport?id_episodio=12345 ele mostra o report preenchido com os dados correctos! :roll: Será que não há forma de processar isto no Extjs4?

EDIT: Já consegui resolver! Usei um iframe e já dá para visualizar. O único problema é no scroll ele começa a ficar todo partido mas depois volta ao normal. De qualquer forma muito obrigado pela ajuda :D

Fica aqui o que usei:

var relatorioWindow = new Ext.Window({        
                        title : "Relatório de Consentimento",        
                        width : 400,        
                        height: 400,        
                        layout : 'fit',        
                        items : [    
                        new Ext.Panel({      
                            autoWidth: true,       
                            autoHeigth: true,      
                            html:"<iframe width='100%' height='400' src='/MinhApp/ReportServlet?id_episodio="+infoCirurgiaPanel.getForm().getValues().Chave+"'></iframe>"      
                        })      
                                  
                        ]        
                    }).show();
L

Olá pessoal,

Esse post me ajudou muito!
Entretanto no meu caso estou tendo alguns problemas.

Consegui enviar uma outra lista por parâmetro para utilizar no subreport. Aparece os itens certinho.

Mas no meu caso eu preciso utilizar o caro “Print When Expression”, e PRECISO acessar um valor da minha lista (no relatório principal).

Então o que eu tenho (no relatório principal):

parametro -> itensNegociacao (Collection)
Field -> itemDescricao (String)

O que eu preciso fazer:
A verficação da descrição no campo “Print When Expression” pois só quero que apareça os itens referentes aquela descrição.
new Boolean( $F{itemDescricao}.equals( $P{itensNegociacao} ) (AQUI ESTÁ O PROBLEMA) - eu precisaria fazer $P{itensNegociacao}.getDescricao() ou algo assim, mas não dá certo!

Já tentei de tudo: $P{itensNegociacao.descricao}, $P{itensNegociacao}.getDescricao(), e algumas outras formas esquisitas.

Não sei mais o que fazer! Alguém tem alguma solução? Sabe como posso resolver isso?
Agradeço desde já por toda ajuda!!!

fabioducarmo

Pessoal,

Estou com um não estou conseguindo utilizar a classe.

Tenho uma aplicação para geração de contracheques, cada contracheque tem um colaborador, e uma lista de eventosSalariais.

Problema:

Unknown property ‘CONTRACHEQUES_ID’ on class ‘class model.Contracheque’

Como faço para ter acesso as informações da lista de eventos salariais e do colaborador, lá no Jasper?

Criado 16 de março de 2010
Ultima resposta 29 de jul. de 2013
Respostas 26
Participantes 8