Inicial > Java, JSF, JSF 2.0, PrimeFaces > JSF 2.0 + PRIMEFACES + iREPORT

JSF 2.0 + PRIMEFACES + iREPORT


Neste post iremos demonstrar, de forma sucinta, como criar relatórios com iReport e como utiliza-lo em suas aplicações web. O iReport é uma ferramenta para  se desenhar relatórios para o JasperReport, que é a uma biblioteca para geração de relatórios. Escolhemos o iReport, por ser uma ferramenta open-source e de bastante disseminação na comunidade Java, além de ser muito fácil de usar e possuir integração com o JFreeChart, para geração de gráficos, e com o Barbecue, gerador de código de barras.

No nosso exemplo utilizaremos

  • Mojarra 2.0.3
  • Primefaces 2.2.1
  • Mysql JDBC Connector 5.1.14

Alé disso precisamos acrescertar ao projeto, as bibliotecas necessárias para rodar relatórios jasper. São elas:

  • Jasper Reports 3.7.6
  • iText 2.1.7
  • Grovy All 1.7.5
  • Commons beanutils 1.8.2
  • Commons collections 3.2.1
  • Commons Digester 1.7
  • Commons Logging 1.1

Lembre-se que a maioria destes jars você pode encontrar na pasta libs do iReport..

Abaixo você pode ver a estrutura que usaremos para nossa base de dados:

Imagem 1

Como você pode ver, utilizaremos uma tabela cargos(mestre) com uma tabela funcionários(detalhes), onde um cargo pode ser comum de vários funcionários, mas um funcionário só de ter um cargo.

Iniciando com o iRerpot

O iReport é uma ferramenta para criação do arquivo jrxml, que nada mais é do que uma definição do relatório em xml. Esta definição poderia ser feita em um bloco de notas, ou qualquer outro editor de texto, porém seria uma atividade incomparavelmente mais custosa para o desenvolvedor.

Com o iReport, é possível desenhar todo o relatório, incluir imagens, além de manipular sub-relatórios e diferentes fontes de dados.

Bom, no início de qualquer relatório é necessário primeiro definir a fonte de dados, ou seja, de onde iremos captar os dados para construção do relatório. Existem duas formas que gosto de trabalhar, uma é utilizando uma consulta SQL diretamente no banco e utilizando os dados retornados para preencher o relatórios. Outra forma, é através da utilização de JavaBeans enviado para o relatório apenas uma coleção dos dados a serem utilizados.

Ao construirmos um relatório temos diversas bandas aparentes na tela, estas seções são divisões da tela do relatório onde podemos preenche-las com textos e imagens .

No iReport estão visíveis 9 seções, ou bandas. São elas:

1. Title: Título do relatório. Pode ser impresso em uma página separada;

2. Page Header: Cabeçalho de cada página do relatório;

3. Column Header: Seção exibida em cada página que contém uma seção Detail;

4. Detail: Nesta seção são impressos todos os registros fornecidos ao relatório;

5. Column Footer: Exibido em cada página que contém uma seção Detail;

6. Page Footer: Rodapé de cada página;

7. Summary: Seção exibida no fim do relatório. Pode ser impresso em uma página separada;

8. No Data: Seção exibida quando não há registros;

9. Background: Nesta seção é possível inserir uma imagem de fundo que será exibida em cada página do relatório.

Fonte: Gerando relatórios com iReport – Roberto Jundi Furutani da Java Magazina 84.

Imagem 2

Criando os Beans

Na aplicação exemplo que iremos fazer, teremos dois beans. Abaixo você pode ver a codificação de ambos:

Cargo.java

public class Cargo {

private int id;

private String descricao;

public String getDescricao() {

return descricao;

}

public void setDescricao(String descricao) {

this.descricao = descricao;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

}

Funcionario.java


public class Funcionario {

private int id;

private String nome;

private String email;

private Cargo cargo = new Cargo();

public Cargo getCargo() {

return cargo;

}

public void setCargo(Cargo cargo) {

this.cargo = cargo;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getNome() {

return nome;

}

public void setNome(String nome) {

this.nome = nome;

}

}

Para que você possa utilizar os beans no iReport é necessário gerar os arquivos .jar e incluir no classpath. Caso você utilize o netbeans você poderá criar uma nova aplicação desktop, criar as classes e executar a aplicação. Dentro da pasta dist, será gerado um arquivo .jar, com o nome que você de ao projeto da aplicação. Com este arquivo criado,  basta colocar para o classpath do iReport apontar para o local onde você o salvou e pronto. Agora, você já pode configurar seu relatório baseado nos dois modelos que criamos.

Imagem 3

Para isso, vamos criar um novo relatório no iReport e depois clicar com o botão direito do mouse sobre o nome do relatório que fica na aba Report Inspector. Feito isso, clique em Edit Query. Abaixo veja imagens das telas:

Imagem 4

Imagem 5

Você deve escolher a segunda aba, JavaBean DataSource, a primeira é para utilizar-se com uma consulta SQL diretamente na base de dados. Digite o nome da classe, nome completo, incluindo o pacote e depois clique em Read Attributes e depois  selecione os campos e clique em Add Selected Field(s)

Imagem 6

Após adicionar os campos vamos montar nosso relatório. Utilize a paleta com as imagens, static text e text fields para montar seu relatório.

Montamos de acordo com a imagem abaixo:

Imagem 7

Criei uma aplicação JSF simples, somente com um botão para chamar o  relatório.

Imagem 8

Veja abaixo os DAOS:

FuncionarioDAO.java

public class FuncionarioDAO {

private Connection conexao;

public List<Funcionario> listaTodos() {

List<Funcionario> listaFuncionario = new ArrayList<Funcionario>();

String consulta = "select * from tab_funcionarios";

try {

conexao = ConnectionFactory.getMySQLConnection();

PreparedStatement ps = conexao.prepareStatement(consulta);

ResultSet rs = ps.executeQuery();

CargoDAO cargoDAO = new CargoDAO();

while(rs.next()) {

Funcionario funcionario = new Funcionario();

funcionario.setId(rs.getInt("id"));

funcionario.setNome(rs.getString("nome"));

funcionario.setEmail(rs.getString("email"));

funcionario.setCargo(cargoDAO.buscaCargoPorId(rs.getInt("tab_cargos_id")));

listaFuncionario.add(funcionario);

}

} catch (SQLException ex) {

Logger.getLogger(FuncionarioDAO.class.getName()).log(Level.SEVERE, null, ex);

}

return listaFuncionario;

}

}

CargoDAO.java

public class CargoDAO {

private Connection conexao;

public Cargo buscaCargoPorId(int id) {

Cargo cargo = new Cargo();

try {

conexao = ConnectionFactory.getMySQLConnection();

String consulta = "select * from tab_cargos where id=?";

PreparedStatement ps = conexao.prepareStatement(consulta);

ps.setInt(1, id);

ResultSet rs = ps.executeQuery();

if(rs.next()) {

cargo.setId(rs.getInt("id"));

cargo.setDescricao(rs.getString("descricao"));

}

} catch (SQLException ex) {

Logger.getLogger(CargoDAO.class.getName()).log(Level.SEVERE, null, ex);

}

return cargo;

}

}

Para chamar o relatório, colocamos o arquivo compilado(.jasper) na pasta report dentro da pasta web-inf e usamos o método imprimeRelatório() do manager bean:

public void imprimeRelatorio() throws IOException, SQLException {

Connection con = ConnectionFactory.getMySQLConnection();

FuncionarioDAO funcionarioDAO = new FuncionarioDAO();

List<Funcionario> listaFuncionario = new ArrayList<Funcionario>();

listaFuncionario = funcionarioDAO.listaTodos();

JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(listaFuncionario);

HashMap parameters = new HashMap();

try {

FacesContext facesContext = FacesContext.getCurrentInstance();

facesContext.responseComplete();

ServletContext scontext = (ServletContext) facesContext.getExternalContext().getContext();

JasperPrint jasperPrint = JasperFillManager.fillReport(scontext.getRealPath("/WEB-INF/report/relatorio_funcionarios_por_cargo.jasper"), parameters, ds);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

JRPdfExporter exporter = new JRPdfExporter();

exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);

exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);

exporter.exportReport();

byte[] bytes = baos.toByteArray();

if (bytes != null && bytes.length > 0) {

HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();

response.setContentType("application/pdf");

response.setHeader("Content-disposition", "inline; filename=\"relatorioPorData.pdf\"");

response.setContentLength(bytes.length);

ServletOutputStream outputStream = response.getOutputStream();

outputStream.write(bytes, 0, bytes.length);

outputStream.flush();

outputStream.close();

}

} catch (Exception e) {

e.printStackTrace();

}

}


Abaixo o resultado do relatório:

É isso, o que ficar de dúvida a gente tenta resolver pelos comentários.

Abraços.

  1. 15/03/2011 às 00:34

    Obrigada por responder!!! Mais pra frente vou fazer uns testes, vou precisar disso! Você como sempre muito prestativo hehehe … Lembre-se: vc é o cara!! 😀
    Bjinhus

  2. Orlando
    27/04/2011 às 14:07

    Ótimo post!

    Eu tenho um metodo para geração de relatorio, este salva o arquivo pdf no disco do servidor. Só que está gerando alguns problemas, quando 2 ou mais pessoas acessa o mesmo relatorio porem com parametros diferentes, o ultimo pdf gerado sobrepõe o anterior, porque estão com o mesmo nome. Ex: se o usuario 1 der um refresh na pagina depois que usuario 2 acessar o relatorio, irá aparecer para o usuario 1 o ultimo relatorio gerado.
    Uma solucao é colocar cada relatorio com nomes diferentes, mas iria gerar problema de espaço em disco, para salvar esses pdf.

    Minha dúvida é a seguinte esse exemplo que vc criou, o pdf gerado fica salvo na memória do servidor?

    Obrigado

  3. Benigno Sales
    01/06/2011 às 17:57

    Caro Manoel, verifique se o tipo dos dados estão iguais, confirme com os imports.

    • Manoel
      02/06/2011 às 17:08

      Benigno, nas classes utilizo Calendar, porém, no MySQL estão mapeados como Date.

  4. vitor
    22/06/2011 às 16:48

    olá

    tenho uma aplicação que serve para várias empresas, e cada uma delas tem uma logomarca diferente que está armazenada no seu cadastro no banco de dados.

    preciso mostrar essa logomarca da empresa no cabeçalho dos relatórios(cada empresa com a sua logo)

    estou passando a imagem via parâmetro para o relatório. tentei com InputStream e java.awt.Image mas a imagem insiste em não aparecer!!! Não dá exception, só a imagem não aparece. Já testei e o array de bytes da imagem que vem do banco não está nulo.

    utilizo JSF 2, Spring, primefaces e hibernate

    quase todos os posts da internet demonstram o mais simples, que é buscar a imagem de um arquivo, e esse não é o meu problema.
    alguma dica??

  5. Robson
    06/12/2011 às 08:41

    Olá Camilo bom dia

    Prezado utilizei as informações descritas por vc, pela similaridade de framework que vc utiliza, so que no meu projeto no log do Eclipse percebo o relatorio ser compilado, como tenho 4 registros na tabela também percebo que apos a compilação, no log aparece algo que identifico como o detalhe aparecendo 4 vezes ( ou seja o numero de registros que eu tenho ) mais, o relatorio não aparece, nem no IE, nem no Mozilla vc teria alguma dica do que pode estar ocorrendo?

    • 06/12/2011 às 10:02

      Camilo? Este comentário esta no blog correto?!

      • Robson
        06/12/2011 às 10:06

        Olá Benigno bom dia, prezado desculpe me descuidei, procurando por uma solucao para o problema do relatorio e olhando dois post muito bom e que tem a ver com o que eu estou fazendo é o seu e o do Camilo Lopes, então acabei escrevendo o seu nome Errado, mil Desculpas ai pelo descuido.

  6. danielortega
    01/03/2012 às 15:04

    Ola, fiz o relatorio seguindo esse exemplo, mas quando clico no botao imprimir, o relatório não é exibido, não acontece nada!!! Sem erros no console do servidor de aplicação, sem exceções, debugando vai até o fim do metodo imprimirRelatorio, porem nao aparece nada pra mim no navegador.

    Alguma Dica???

    • danielortega
      01/03/2012 às 15:13

      Já descobri o problema. Coloquei a propriedade ‘ajax=false’ commandLink

      Valeu!!!

  7. Robson
    07/05/2012 às 12:48

    E isto ai meu caro, testei e deu certo, cara ja tinha até deixado pra lá

  8. Denis
    05/03/2013 às 16:30

    Boa tarde Benigno, tudo em ordem?
    Vamos ver se pode me ajudar, criei o jar em cima do meu projeto mesmo.
    O jar esta la … qdo insiro no iReport ele não rertorna nada tentei colocar um caminho inexistente e ele aponta o erro.
    No caso sabe o pq não esta puxando mesmo o jar estando correto?
    Desde ja agradeço.

    []s

  9. Luis Gustavo
    25/10/2013 às 09:30

    No eclipse como faço pra fazer esse relatorio do Report?

  10. Lucas
    27/11/2013 às 20:38

    Cara pode me ajudar fiz conforme acima porem não esta encontrando o metodo

    javax.el.MethodNotFoundException: /newxhtml.xhtml @19,141 action=”#{setorBean.imprimiRelatorio}”: Method not found: br.com.sistema_servicos.bean.SetorBean@88e872.imprimiRelatorio()

  11. bruno
    10/02/2014 às 17:01

    Poderia me dizer como eu mapeio o classpath em uma aplicacao web jsf diretamente sem precisar criar os .jar de meus beans?

  12. Julio Cesar
    29/04/2014 às 10:50

    Blz, se eu estou ut6ilizando o persistencia por jpa? como fica minha classe que chama o relatorio?

  13. Ivan
    17/06/2015 às 19:18

    Parabéns, me ajudo e muito.
    um abraço

  14. Josué
    27/08/2016 às 03:44

    Muito obrigado por compartilhar conhecimento. Eu estava penando para desenvolver relatório em uma aplicação e graças a a sua ajuda agora o relatório esta uma maravilha. Exporta para doc, ptt pdf. Abraços!

  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

%d blogueiros gostam disto: