• Nenhum resultado encontrado

DIFERENTES TIPOS DE FONTES DE DADOS – DATASOURCES

´

Nesta parte iremos aprender a usar outros tipos de datasources para obtermos os dados que serão apresentados nos nossos relatórios. Como de costume, vou explicar como fazer para utilizar a funcionalidade, permitindo que vocês consigam caminhar sozinhos posteriormente.

Nas três partes anteriores, a nossa fonte de dados era uma conexão JDBC que era usada para executar uma query SQL. A partir do resultado da query, o JasperReports preenchia o relatório para nós. Imagine agora a seguinte situação: Eu tenho uma lista de objetos do tipo “Cliente” e quero exibir essa lista de clientes em um relatório. Note que eu já tenho a lista, que foi obtida de alguma forma, ou seja, usando um DAO, ou executando uma query pelo Hibernate. Para conseguir fazer isso, utilizamos outros tipos de datasources.

No projeto que construímos para testar a emissão de relatório, criamos um formulário para a geração, onde nele possui um método openRelatorio() cujo código é:

private void openRelatorio( String titulo,

InputStream inputStream, Map parametros,

Connection conexao ) throws JRException {

// Cria um JasperPrint, que é a versão preenchida do relatório, usando uma conexão.

JasperPrint print = JasperFillManager.fillReport(inputStream, parametros, conexao);

// abre o JasperPrint em um JFrame JRViewer viewer = new JRViewer(print); if(rbVisualizar.isSelected()) { JasperExportManager.exportReportToPdfFile(print,"relatorios/RelatorioClientes.pdf"); this.visualizarPDF(); } else{

FormVisualizar form = new FormVisualizar(); form.add(viewer,BorderLayout.CENTER); form.setVisible(true);

} }

O método que utilizamos até agora recebe uma String que vai ser usada como título do JFrame utilizado como container do relatório, um InputStream que vai ser usado para obtermos o arquivo .jasper, um Map que contém os parâmetros passados para o relatório e, por fim, uma Connection para a base de dados que usamos na query do relatório.

Iremos construir um segundo método openRelatorio (realizando sua Sobrecarga), aque terá praticamente a mesma assinatura do primeiro, mudando apenas o último parâmetro, que nessa versão do método será um JRDataSource. A implementação do método é igual

ao outro, com a diferença de ser passado o JRDataSource para o

JasperFillManager.fillReport(…) ao invés da Connection.

public static void

openReport

( String titulo,

InputStream inputStream, Map parametros,

JRDataSource dataSource ) throwsJRException {

JasperPrint print = JasperFillManager.fillReport( inputStream, parametros, dataSource );

JRViewer viewer = new JRViewer(print);

// continuação do método para mostrar o relatório, igual ao primeiro método.

}

Segunda implementação do método OpenRelatorio com DataSource genérico

O JRDataSource é uma interface que define o contrato que os datasources devem seguir para que o JasperReports possa usar os dados contidos neles dentro do relatório. A documentação da

interface JRDataSource pode ser vista no link

(http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/JRDataSource.html). Ao analisar a documentação, observe que existem diversas implementações da interface JRDataSource. Iremos focar em duas:

JRBeanCollectionDataSource: Utilizada para usar coleções como fonte de dados, ou

seja, qualquer classe que implemente – ou interface que estenda – a interface

java.util.Collection. Por exemplo, um ArrayList, que implementa a interface List que por sua vez estende a interface Collection. A documentação deste tipo de datasource pode

(http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/data/JRBeanCollect ionDataSource.html)

JRBeanArrayCollectionDataSource: Utilizado para usar arrays de objetos como fonte de dados. A documentação deste tipo de datasource pode ser vista no link (http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/data/JRBeanArrayD ataSource.html).

Então, além da conexão JDBC, podemos utilizar vários outros tipos de datasources.

Para nosso estudo, iremos utilizar o primeiro, para Coleções de Objetos, e depois a utilização do segundo ficará como exercício. Como o funcionamento de ambos é muito parecido, não iremos explicar os tipos existentes. Caso seja necessário outro tipo de datasource, basta ler a documentação.

A utilização dos datasources não é complicada, bastando você criar um objeto do tipo do datasource desejado e passar o parâmetro que ele espera, entretanto precisamos alterar uma configuração no iReport para indicar ao compilador onde estão as classes que vamos utilizar para instanciar os objetos e enviar no datasource.

Antes de fazer isso, vamos criar uma classe no nosso projeto, sendo que essa classe será utilizada como a nossa entidade. Iremos instanciar objetos dessa classe manualmente, mas em um caso real, esses objetos virão de algum outro lugar, como uma query do Hibernate como eu já mencionei. Vamos lá então!

Clique com o botão direito no “Pacotes de Códigos-fonte” e crie um novo pacote

chamado “entidades”. Crie uma classe nesse pacote chamada “Cliente” (sem as

aspas). Crie os campos id (privado, int), nome (privado, String), cpf (privado, String) e renda (privado, float). Com os campos criados, gere os gets e os sets. Segue o código da classe Cliente.

public class Cliente { private int id; private String cpf; private String nome; private float renda;

public ClienteRel() {

}

public int getId() { return id; }

public void setId(int id) { this.id = id;

}

public String getCpf() { return cpf;

}

public void setCpf(String cpf) { this.cpf = cpf;

}

public String getNome() { return nome;

}

public void setNome(String nome) { this.nome = nome;

}

public float getRenda() { return renda;

}

public void setRenda(float renda) { this.renda = renda;

} }

Agora, antes de partirmos para o nosso relatório, precisamos configurar o iReport para enxergar as classes do nosso projeto, permitindo assim que possamos utilizar nossas entidades no relatório. Antes disso, dê um Build (Construir) no projeto (botão direito no

projeto, Build, ou Clean and Build –Limpar e Construir), para que o diretório de build seja gerado, ou seja, o diretório que contém os arquivos compilados no nosso projeto.

Com o build feito, entre no menu do NetBeans Tools (Ferramentas) e vá em Options

(Opções). Clique no botão do iReport e procure pela guia Classpath. Com a guia aberta,

clique no botão Add Folder. Ao clicar no botão, será exibido um diálogo para você

procurar a pasta desejada. Nós precisamos encontrar a pasta build/classes do nosso

projeto. No meu caso, eu estou salvando o projeto em

“D:\ProjetosJava\TutorialRelatorios\”, então o build/classes está localizado em “D:\ProjetosJava\TutorialRelatorios\\build\classes”. Procure então pelo o seu build/classes, selecione o diretório e clique em Open. O editor de opções da IDE deve ficar assim:

Editando o Classpath do iReport

Vamos criar o relatório então. Crie um novo Empty Report. Vamos dar o nome nesse

relatório de ClientesCollectionDS, pois vamos utilizar o datasource do tipo

JRBeanCollectionDataSource. Assim que clicar em Finish no assistente de criação de

relatórios, o arquivo ClientesCollectionDS.jrxml será gerado e será aberto no editor.

Para simplificar, remova todas as bandas, exceto a Title, a Column Header e a Detail. Na banda Title crie um campo de texto estático e defina o título do relatório, desta forma:

Layout Inicial do Relatório de Clientes usando Collection DS

Agora chegou a parte onde vamos obter os atributos da nossa entidade Cliente.

1. Clique no botão usado para editar a query do relatório e acesse a guia “JavaBean

Datasource”. Note que não vamos criar uma query.

2. Com a aba aberta, preencha o campo “Class name” com “entidades.Cliente”

3. Vão ser lidos 5 atributos: class, id, nome, cpf e renda. Selecione todos, exceto o

class e clique em “Add selected field(s)”.

4. Ao fazer isso, os campos serão inseridos na tabela de campos do editor. Veja a Figura abaixo.

Carregando Campos de Uma Classe

5. Perceba que você precisa inserir o nome completo da classe (pacote + nome da classe) para que o iReport encontre a classe e a possa utilizar no relatório. Com isso feito, clique em OK.

Os campos serão criados no Report Inspector da mesma forma que seriam criados caso estivéssemos usando uma query tradicional. Agora que os campos estão criados, basta montar o relatório, arrastando os campos para a banda Detail e editando o título de cada um deles.

Layout Final do Relatório de Clientes usando Collection DS

Observe que ao se dar um “Preview” no relatório, será avisado que o relatório não contém páginas, justamente porque não existem dados para serem exibidos. É possível criar um datasource para ser usado no preview do relatório, mas irei deixar como exercício para você, caso queira descobrir como faz ;-) Compilem o relatório!

Para chama-lo, vamos incluir em nosso formulário FormRelatorio.java um novo botão,

com o título “Emitir Relatório com DS” que terá mesma implementação do primeiro

botão. Portanto, para simplificar, iremos copiar-e-colar o código do primeiro no Action deste novo botão e realizar as seguintes modificações:

1. Modificar o relatório alvo que será exibido.

InputStream inputStream = getClass().getResourceAsStream( "/ClientesCollectionDS.jasper");

2. Mude o título do relatório na chamada do openRelatorio():

this.openRelatorio( "Clientes - Bean Collection Data Source", inputStream, parâmetros, Conexao.getConexao());

3. O mais importante agora é modificar o método openRelatorio() para, ao invés de passar um Connection (ultimo parâmetro Conexao.getConexao()) usar o datasource, ou seja, a segunda versão do método implementado. Para isso, vamos

instanciar um objeto datasource JRDataSource e passar para ele uma lista de

Clientes chamada “dados” (que será criada mais adiante): Essa instanciação será

antes da chamada do openRelatorio(), no caso, antes do try:

JRDataSource ds = new JRBeanCollectionDataSource(dados);

Campos carregados ficam

aqui, da mesma forma que uma query tradicional

4. Vamos criar essa lista “dados” que conterá uma coleção de objetos Cliente. Montaremos usando um ArrayList e com dados aleatórios, cerca de 100 clientes:

List dados = new ArrayList<Cliente>(); for(int i = 1; i <= 100; i++)

{

Cliente cliente = new Cliente(); cliente.setId(i); cliente.setCpf(Math.round(Math.random()*100)+".000.000-"+i); cliente.setNome("Nome do Cliente "+ i); cliente.setRenda(1500 + (i*50)); dados.add(cliente); }

JRDataSource ds = new JRBeanCollectionDataSource(dados);

5. Para completar vamos passar o objeto “ds” no lugar de Conexao.getConexao()

para o método openRelatorio(). Desta forma, estaremos chamando a segunda versão do método, usando a sobrecarga.

this.openRelatorio( "Clientes - Bean Collection Data Source", inputStream, parâmetros, ds);

6. Teste sua aplicação! O relatório será exibido ao clicar o botão “Emitir Relatório com DS”: