27 de maio de 2011

JasperReports 4.0.1: Criando gráficos no iReport com JDBC datasource - Gráfico tipo: pizza

Depois de criarmos gráficos do tipo em barras, agora vamos criar gráficos do tipo pizza, para esta postagem eu vou usar JDBC datasouce, por ser mais prático, isso só para mostrar mesmo como criar gráficos usando o iReport.
Obs: qualquer semelhança inicialmente com a postagem sobre gráficos em barras é mera coincidência... brincadeira, é puro CTRL C + CTRL V hahaha

Banco de dados
Tendo as seguintes tabelas no banco de dados:


Se eu executar a seguinte query no banco:
select cliente.nome, sum(pedido.valor) as total from cliente, pedido 
where pedido.cliente_codigo = cliente.codigo 
group by cliente.nome 
order by total desc;

Levando em consideração os dados do meu banco, eu tenho o seguinte resultado:

Agora eu quero representar esses valores graficamente, para isso no iReport...

No iReport...
A partir daqui já estou considerando que já tenha um novo relatório criado, caso queira mais detalhes de como proceder com o JDBC datasource, veja o link lá do início.
Em Report query vou usar a mesma query acima, assim:

Depois de dar um OK, confirmo no Report Inspector se os fields foram criados:

Criando o gráfico...
Na paleta de elementos, procure por Chart:

Clique no elemento e arraste-o para a band summary, ao fazer isso, aparecerá a janela para selecionar o tipo de gráfico, neste exemplo vou usar o Pie 3D:

Na próxima janela clique em Finalizar (e não em próximo como parece selecionado na imagem):

O resultado será este:

Veja que neste exemplo eu tenho apenas as bands Tittle e Summary, quanto as outras eu removi.
Agora vamos configurar nosso gráfico, para isso clique com o botão direito no gráfico, e vá na opção Chart Data:


Na aba Details configure os campos de acordo com a imagem acima: e de acordo com os nomes dos seus fields, informe o nome do cliente para Key e o valor total do pedido para Value e Label. Feito basta dar um Close na janela, e pronto...

Basta clicar em Preview na janela do iReport, que já poderemos ver o resultado:

Bem simples!

JasperReports 4.0.1: Criando gráficos no iReport com JDBC datasource - Gráfico tipo: barras

Na postagem de hoje vamos gerar gráficos com JasperReports, para esta postagem eu vou usar JDBC datasouce, por ser mais prático, isso só para mostrar mesmo como criar gráficos usando o iReport.

Banco de dados
Tendo as seguintes tabelas no banco de dados:


Se eu executar a seguinte query no banco:
select cliente.nome, sum(pedido.valor) as total from cliente, pedido 
where pedido.cliente_codigo = cliente.codigo 
group by cliente.nome 
order by total desc;

Levando em consideração os dados do meu banco, eu tenho o seguinte resultado:


Agora eu quero representar esses valores graficamente, para isso no iReport...

No iReport...
A partir daqui já estou considerando que já tenha um novo relatório criado, caso queira mais detalhes de como proceder com o JDBC datasource, veja o link lá do início.
Em Report query vou usar a mesma query acima, assim:


Depois de dar um OK, confirmo no Report Inspector se os fields foram criados:


Criando o gráfico...
Na paleta de elementos, procure por Chart:

Clique no elemento e arraste-o para a band summary, ao fazer isso, aparecerá a janela para selecionar o tipo de gráfico, neste exemplo vou usar o Bar 3D:


Na próxima janela clique em Finalizar (e não em próximo como parece selecionado na imagem):

O resultado será este:

Veja que neste exemplo eu tenho apenas as bands Tittle e Summary, quanto as outras eu removi.
Agora vamos configurar nosso gráfico, para isso clique com o botão direito no gráfico, e vá na opção Chart Data:


Na aba Details clique no botão Add:

De acordo com os nomes dos seus fields, informe o nome do cliente para Series e Category e o valor total do pedido para Value. Feito isso dê OK na janela principal e um Close na janela abaixo, e pronto...
Basta clicar em Preview na janela do iReport, que já poderemos ver o resultado:

Bem simples!

25 de maio de 2011

JasperReports 4.0.1: JDBC datasource - abrir relatório em projeto desktop

Depois de vermos como chamar um relatório feito no JasperReports utilizando JDBC datasource em um projeto Web, nessa postagem vamos usar o mesmo relatório mas em um projeto Java Desktop!
Reveja algumas postagens:

Começando...
Para começar, no NetBeans crie um novo Aplicativo Java com o nome de RelatorioJDBC. A estrutura final será esta aqui:


Feito isso, vamos começar a estruturar nosso projeto para usarmos .jasper (criado na postagem do link). Como estamos usando JDBC, precisamos ter uma conexão com o banco de dados, então em pacotes de código-fonte já existirá um pacote com o nome de relatoriojdbc, dentro dele crie um novo pacote com o nome de dao, dentro desse pacote crie a classe Java com o nome de Conexao (já foi utilizada em outras postagem que não utilizava JPA), segue o código-fonte:
public class Conexao {
    private String driver = "com.mysql.jdbc.Driver";
    private String URL = "jdbc:mysql://localhost/5tads";
    private String USER = "root";
    private String SENHA = "admin";
    private Connection conn;

    public Conexao() {
        try {
            Class.forName(driver);
            conn = (Connection) DriverManager.getConnection(URL, USER, SENHA);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Connection getConn() {
        return conn;
    }

    public void fecharConexao() {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
Obs: só lembrando que na URL, o 5tads corresponde à minha database.
Como nosso foco não é a conexão com o banco de dados, vamos prosseguir... agora no mesmo pacote relatoriojdbc.dao, vamos criar mais uma classe Java com o nome de ClienteDAO:
public class ClienteDAO {

    private Conexao conexao;
    private Statement stmt;

    public ClienteDAO() {
        conexao = new Conexao();
        try {
            stmt = (Statement) conexao.getConn().createStatement();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public ResultSet clientesResultSet() {
        ResultSet rs = null;
        try {
            rs = stmt.executeQuery("SELECT * FROM cliente ORDER BY nome");
        } catch (Exception e) {
            e.printStackTrace();
        } 

        return rs;
    }
}
Veja que o nosso método clientesResultSet, retorna um ResultSet mesmo e não uma lista de clientes, ao usarmos a metodologia de JDBC datasource, é isto que precisamos passar para o .jasper, e não uma lista como na JavaBean datasource.

Agora precisamos de um lugar para guardar nosso .jasper, para isso crie a seguinte estrutura de pacotes:
relatoriojdbc.controle.relatorios, e dentro dele, coloque o arquivo .jasper (no meu caso relatorioJDBC .jasper):


Agora precisamos colocar as bibliotecas no projeto, caso não tenha baixado as bibliotecas do JasperReports, baixe por aqui.
De todas as bibliotecas disponibilizadas no link, para este tipo de relatório iremos usar apenas algumas delas, acabei filtrando e chegando as que realmente precisavam, então adicione ao projeto as seguintes bibliotecas:

* quanto a biblioteca do MySQL é do próprio NetBeans (mas pode ser encontrada facilmente no Google).

Agora que já temos nosso dao pronto, e como já criamos um pacote relatoriojdbc.controle.relatorios, já temos um pacote controle, e então dentro dele teremos uma classe Java com o nome de ClienteControle:
public class ClienteControle {

    private ClienteDAO dao;

    public void gerarRelatorio() {
        String arquivo = "src/relatoriojdbc/controle/relatorios/relatorioJDBC.jasper";

        dao = new ClienteDAO();
        JRDataSource jrds = new JRResultSetDataSource(dao.clientesResultSet());
        gerarRelatorioDesktop(jrds, null, arquivo);
    }

    private void gerarRelatorioDesktop(JRDataSource jrds, Map<Object, Object> parametros, String arquivo) {
        try {
            JasperPrint print = JasperFillManager.fillReport(arquivo, parametros, jrds);
            JasperViewer.viewReport(print, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Vamos ver o que esses métodos fazem: 

public void gerarRelatorio()
Inicialmente este método será chamado pela nossa classe Main (que foi criada por padrão no projeto), nesse método nós precisamos pegar o caminho exato do nosso arquivo .jasper, que lá no começo da postagem colocamos dentro do pacote relatoriojdbc.controle.relatorios para isso precisamos indicar o caminho corretamente.
Quanto ao jrRS: por termos utilizado JDBC datasource para gerar nosso .jasper, nos precisamos passar para nosso relatório um JRDataSource, que é formado por um Result Set  que é retornado pelo nosso método lá do ClienteDAO.
Ao chamar o gerarRelatorioDesktop, estamos passando um parâmetro null, esse corresponderia a uma Map, que serviria para passarmos parâmetros(que vai ficar pra outra postagem) para o nosso relatório...
Agora vamos ver o que acontece no:
gerarRelatorioDesktop(JRDataSource jrRS, Map<Object, Object> parametros, String arquivo)
Dentro de um try-catch(para capturar possíveis exceções) nós temos o método principal que é o responsável por gerar o que vai ser o nosso relatório, que é essa linha aqui:
JasperFillManager.fillReport... 
esse método não cria um arquivo .pdf fisicamente no computador, apenas gera ele como se fosse um arquivo temporário, e quem decide se quer salvar o relatório ou não é o usuário, depois disso, chamamos o JasperViewer que é o que eu chamo de "visualizador de relatórios" do próprio JasperReports (ao final eu mostro visualmente este visualizador)...
Depois de vermos a principal classe do projeto, vamos ver a classe Main.java (dentro do pacote relatoriojdbc) que vai ser a responsável por mostrar uma telinha em Swing que tem um jButton, e que quando clicar nele ele vai chamar nosso método gerarRelatorio() da nossa classe ClienteControle, veja o código da classe Main abaixo:
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame("Meu relatorio!");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton botao = new JButton("Chamar meu relatório!");
        botao.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent ae) {
                ClienteControle controle = new ClienteControle();
                controle.gerarRelatorio();
            }
        });

        frame.getContentPane().add(botao);
        frame.pack();
        frame.setVisible(true);

    }
}

Ao executar o projeto (F6) temos a seguinte tela (é bem essa grande tela aí abaixo):


Ao clicar no botão "Chamar meu relatório!", ele irá fazer o que o próprio nome dele já diz: Chamar o nosso relatório =) ... assim, aparece a seguinte tela do JasperViewer:


Por aqui finalizamos a visualização de relatórios feito no JasperReports utilizando JDBC datasource. =)

JasperReports 4.0.1: JDBC datasource - abrir relatório em projeto web

Dando continuidade na postagem: JasperReports 4.0.1: Utilizando JDBC datasource, agora vamos usar o .jasper gerado no iReport, em um projeto Java EE 6.

Começando...
Para começar, no NetBeans crie uma nova Aplicação Web com o nome de RelatorioJDBC (seguindo os passos já vistos em postagens anteriores), o estrutura final é este aqui:


Feito isso, vamos começar a estruturar nosso projeto para usarmos .jasper (criado na postagem do link). Como estamos usando JDBC, precisamos ter uma conexão com o banco de dados, então em pacotes de código-fonte crie um novo pacote com o nome de dao, dentro desse pacote crie a classe Java com o nome de Conexao (já foi utilizada em outras postagem que não utilizava JPA), segue o código-fonte:
public class Conexao {
    private String driver = "com.mysql.jdbc.Driver";
    private String URL = "jdbc:mysql://localhost/5tads";
    private String USER = "root";
    private String SENHA = "admin";
    private Connection conn;

    public Conexao() {
        try {
            Class.forName(driver);
            conn = (Connection) DriverManager.getConnection(URL, USER, SENHA);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Connection getConn() {
        return conn;
    }

    public void fecharConexao() {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
Obs: só lembrando que na URL, o 5tads corresponde à minha database.
Como nosso foco não é a conexão com o banco de dados, vamos prosseguir... agora no mesmo pacote dao, vamos criar mais uma classe Java com o nome de ClienteDAO:
public class ClienteDAO {

    private Conexao conexao;
    private Statement stmt;

    public ClienteDAO() {
        conexao = new Conexao();
        try {
            stmt = (Statement) conexao.getConn().createStatement();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public ResultSet clientesResultSet() {
        ResultSet rs = null;
        try {
            rs = stmt.executeQuery("SELECT * FROM cliente ORDER BY nome");
        } catch (Exception e) {
            e.printStackTrace();
        } 

        return rs;
    }
}
Veja que o nosso método clientesResultSet, retorna um ResultSet mesmo e não uma lista de clientes, ao usarmos a metodologia de JDBC datasource, é isto que precisamos passar para o .jasper, e não uma lista como na JavaBean datasource.

Agora vamos colocar o .jasper dentro do nosso projeto, para isso em Páginas Web, dentro de WEB-INF crie um novo diretório com o nome de relatorios, e dentro dele coloque o arquivo .jasper, no meu caso tem o nome de relatorioJDBC.jasper (em caso de dúvidas volte na imagem acima da estrutura do projeto).
O próximo passo é colocar as bibliotecas necessárias no projeto, caso não tenha baixado as bibliotecas do JasperReports, baixe por aqui. De todas as bibliotecas disponibilizadas no link, para este tipo de relatório iremos usar apenas algumas delas, acabei filtrando e chegando as que realmente precisavam, então adicione ao projeto as seguintes bibliotecas:


* quanto a biblioteca do MySQL é do próprio NetBeans (mas pode ser encontrada facilmente no Google).

Agora que já temos nosso dao pronto, vamos criar um novo pacote para armazenar nossos beans esse pacote será o controle: depois de criado, crie uma nova classe Java com o nome de ClienteBean:
@Named
@RequestScoped
public class ClienteBean {

    private ClienteDAO dao;

    public void gerarRelatorio() {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        ServletContext context = (ServletContext) externalContext.getContext();
        String arquivo = context.getRealPath("WEB-INF/relatorios/relatorioJDBC.jasper");

        dao = new ClienteDAO();
        JRDataSource jrRS = new JRResultSetDataSource(dao.clientesResultSet());

        gerarRelatorioWeb(jrRS, null, arquivo);
    }

    private void gerarRelatorioWeb(JRDataSource jrRS, Map<Object, Object> parametros, String arquivo) {
        ServletOutputStream servletOutputStream = null;
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();

        try {
            servletOutputStream = response.getOutputStream();
            JasperRunManager.runReportToPdfStream(new FileInputStream(new File(arquivo)), response.getOutputStream(), parametros, jrRS);
            response.setContentType("application/pdf");
            servletOutputStream.flush();
            servletOutputStream.close();
            context.renderResponse();
            context.responseComplete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Vamos ver o que esses métodos fazem:

public void gerarRelatorio()
Inicialmente este método será chamado pela nossa página JSF, nele nós precisamos pegar o caminho exato do nosso arquivo .jasper, que lá no começo da postagem colocamos dentro de WEB-INF/relatorios, para isso usamos o context.getRealPath.
Quanto ao jrRS: por termos utilizado JDBC datasource para gerar nosso .jasper, nos precisamos passar para nosso relatório um JRDataSource, que é formado por um Result Set  que é retornado pelo nosso método lá do ClienteDAO.
Ao chamar o gerarRelatorioWeb, estamos passando um parâmetro null, esse corresponderia a uma Map, que serviria para passarmos parâmetros(que vai ficar pra outra postagem) para o nosso relatório...
Agora vamos ver o que acontece no:
gerarRelatorioWeb(JRDataSource jrRS, Map<Object, Object> parametros, String arquivo)
Neste método nós dependemos do response para mostrar o nosso relatório no navegador, quanto a essa parte não vou dar muitas explicações, pois sairia do nosso foco que é o JasperReports...
Bom, no final o responsável por gerar o que vai ser o nosso relatório, é essa linha aqui:
JasperRunManager.runReportToPdfStream... 
esse método não cria um arquivo .pdf fisicamente no computador, apenas gera ele como se fosse um arquivo temporário, e quem decide se quer salvar o relatório ou não é o usuário, depois disso, o response entra em campo novamente dizendo ao navegador que o que será enviado é do tipo application/pdf, cada navegador reage de uma forma quando se trata de PDF, no caso do Google Chrome, mostra nele mesmo, se não me engano o Firefox, já dá a opção de fazer download do PDF...
e por fim o servletOutputStream, é quem manda o relatório para o navegador!


Depois de entendermos como funciona essa classe, vamos alterar nossa página index.xhtml, para que ela chame o método e mostre o relatório:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:commandButton value="Ver relatorio" actionListener="#{clienteBean.gerarRelatorio}" onclick="this.form.target='_blank'" />
        </h:form>
    </h:body>
</html

Quanto ao onclick do commandButton, eu uso para poder abrir o relatório em outra aba do navegador. Visualmente a página index, fica assim:


Quem estiver usando o Google Chrome para fazer estes testes, terá o seguinte resultado ao clicar no botão:


E por aqui finalizamos a postagem de como usar um .jasper feito com base em JDBC, em um projeto web (Java EE 6)  =)

23 de maio de 2011

JSF 2.0: Componentes PrimeFaces 2.2.1 - Parte 3

Vamos dar continuidade nas postagens sobre os componentes do PrimeFaces na versão 2.2.1. Na postagem anterior tratamos mais a parte de painéis, hoje será tratado de componentes um pouco mais úteis do que aqueles.

Estrutura do projeto
Caso não saiba como montar a estrutura do projeto veja aqui.
Depois de pronto o projeto fica com essa estrutura:

Antes de começar vamos ver o código fonte do nosso bean TesteBean.java que irá auxiliar os componentes (aos poucos vamos entendendo como essa classe será utilizada):
@Named
@SessionScoped
public class TesteBean implements Serializable {

    private int numeroSlider;
    private double valorSpinner;
    private List<String> animais;

    public void confirmar() {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Confirmação", "Você confirmou alguma coisa!");
        FacesContext.getCurrentInstance().addMessage(null, message);
    }

    public int getNumeroSlider() {
        return numeroSlider;
    }

    public void setNumeroSlider(int numeroSlider) {
        this.numeroSlider = numeroSlider;
    }

    public double getValorSpinner() {
        return valorSpinner;
    }

    public void setValorSpinner(double valorSpinner) {
        this.valorSpinner = valorSpinner;
    }

    public List<String> getAnimais() {
        animais = new ArrayList<String>();
        animais.add("Girafa");
        animais.add("Pato");
        animais.add("Leopardo");
        animais.add("Elefante");
        animais.add("Zebra");
        return animais;
    }

    public void setAnimais(List<String> animais) {
        this.animais = animais;
    }

}

Começando...
Nossa tela irá ficar assim:


Bom... na imagem não aparecem todas os componentes, alguns deles serão chamados pelos botões "Confirmar" e "Abrir janela".

Agora vamos começar de uma vez, com um componente que é bem util, é o p:confirmDialog ele é um janelinha que geralmente é utilizada em casos de confirmação de exclusão ou confirmar alguma outra coisa:

Ao clicar no botão "Sim", a janela se fecha e mostra um mensagem a partir do componente p:messages (visto na primeira postagem), assim:


Código-fonte do componente:
<p:messages id="mensagens" showDetail="true" />
<p:commandButton value="Confirmar" onclick="confirmacao.show()" type="button"/>
<h:form>
    <p:confirmDialog widgetVar="confirmacao" header="Confirmar" message="Deseja confirmar alguma coisa?" severity="alert" modal="true">
        <p:commandButton value="Sim" update="mensagens" oncomplete="confirmacao.hide()" actionListener="#{testeBean.confirmar}" />
        <p:commandButton value="Não" onclick="confirmacao.hide()" type="button" />
    </p:confirmDialog>
</h:form>
Vamos entender o que está acontecendo neste código, inicialmente eu tenho um p:messages que será atualizado quando eu clicar no commandButton correspondente ao "Sim", esse commandButton chama o método confirmar que retorna uma mensagem ao JSF pelo FacesContext. A propriedade modal do confirmDialog serve pra bloquear que possa ser feito outras ações com este componente em funcionamento, ou seja ele faz tipo um painel de vidro, não deixando a possibilidade de mexer nos componentes atrás dele.

O segundo componente é bem parecido com o anterior, porém mais maleável, é o p:dialog, ele é praticamente um painel só que não é fixo na tela, ele realmente funciona como uma janelinha independente que abre, fecha e que pode ser movida de lugar:

Código-fonte do componente:
<p:commandButton value="Abrir janela" onclick="janela.show()" type="button" />
<p:dialog widgetVar="janela" header="Novo..." modal="true" width="500" height="230">
 ...
</p:dialog>
No código fonte completo (final da postagem) eu coloquei alguns outros componentes dentro deste dialog, apenas para mostrar que os componentes podem ser usados juntos (mas todos eles podem funcionar muito bem separadamente).

O componente p:wizard é algo até complicado de explicar para o que serve, pois depende da criatividade de quem for usar, mas o que eu posso dizer é que funciona quase como a tabView (vista na segunda postagem) mas ao invés de clicar na tab para abri-la, existem dois botões, um de avançar e outro de voltar uma tab:


Código-fonte do componente:
<p:wizard nextLabel="Avançar" backLabel="Voltar">
    <p:tab title="Slider">
        <p:panel header="Testando o slider">
        </p:panel>
    </p:tab>
    <p:tab title="Spinner">
        <p:panel header="Testando o spinner">
        </p:panel>
    </p:tab>
</p:wizard>
Veja que o mesmo é composto da mesma tag p:tab, já utilizada por outros componentes (na segunda postagem), quanto ao p:panel, não é obrigado ter ele alí, eu só coloquei para dar uma entendida melhor que se pode fazer com esse componente.

p:slider é um componente para números utilizado juntamente com um inputText (talvez com outros elementos também, não testei isso), o interessante dele é que pode-se definir intervalos numéricos:


Código-fonte do componente:
<h:outputText value="Numero:" />
<p:inputText id="numero1" value="#{testeBean.numeroSlider}"/>
<p:slider for="numero1" minValue="-100" maxValue="100" style="width: 127px"/>

Bom, como nem tudo é perfeito... a versão 2.2.1 do PrimeFaces também não é perfeita, e sim.. ela tem bugs, por exemplo o componente p:spinner não renderiza corretamente (veja no link a renderização correta dele), mas mesmo assim vou mostrar ele, é bom saber que ele existe, pode ser que em outra versão ele funcione perfeitamente:


Código-fonte do componente:
<h:outputText value="Valor:" />
<p:spinner value="#{testeBean.valorSpinner}" min="-10" max="10" stepFactor="0.10" showOn="hover"/>
Assim como o slider, este componente permite definir um intervalo numérico e também a quantidade de quanto ele deve somar ou subtrair do numero atual, isso é configurado na propriedade stepFactor. Para não ficar devendo: no Blog tem uma postagem sobre ajax nativo do JSF 2.0, onde o primeiro componente funciona meio parecido com este. Caso encontre uma solução para este bug eu volto aqui e atualizo esta postagem (se alguém souber essa solução, será bem vinda).

Agora sim vamos ver um componente bem útil, é a p:dataTable que é uma tabela que pode ser paginada e tudo mais, no link tem muitas formas de utilização dela, aconselho dar uma olhada, aqui vou mostrar o básico do básico dela:


Código-fonte do componente:
<p:dataTable value="#{testeBean.animais}" var="a" paginator="true" rows="4">
    <p:column headerText="Nome dos animais">
        <h:outputText value="#{a}" />
    </p:column>
    <p:column style="width: 30px">
        <p:commandButton image="ui-icon-wrench" />
    </p:column>
</p:dataTable>
Vou levar em consideração que você que está lendo já tenha conhecimento da h:dataTable do JSF puro, assim posso pular os detalhes... neste caso eu estou usando ela com paginação, então eu preciso dizer quantas linhas eu quero que apareça em cada página, para isso eu uso a propriedade rows.
Obs: é importante saber que ao utilizar um h:column em uma p:dataTable, esta não renderizará corretamente, por isso eu uso o p:column.

E pra finalizar, um componente que funciona bem parecido com o componente acima, porém é mais maleável também que é o p:dataGrid:


Veja que ele usa paginação da mesma forma que a p:dataTable, abaixo do código explicarei alguns detalhes.
Código-fonte do componente:
<p:dataGrid value="#{testeBean.animais}" var="a" paginator="true" columns="2" rows="4">
    <p:column>
        <p:panel header="Animal">
            <h:outputText value="Este animal é um #{a}" />
        </p:panel>
    </p:column>
</p:dataGrid>
Veja que eu estou usando a mesma lista que usei na p:dataTable, a diferença é que, na p:dataGrid é utilizada apenas um p:column, essa unica coluna funciona como um laço de repetição. Vamos aos detalhes importantes: a propriedade columns serve para definir quantas colunas devem ser mostradas, já a propriedade rows à primeira impressão ela engana, pois é, quando eu vi ela, pensava que era como a rows da p:dataTable que seria a quantidade de linhas que teria minha dataGrid, mas não é... na realidade ela corresponde a quantidade de elementos que devem ser mostrados na página: como eu defini que teria apenas duas colunas, por exemplo eu não posso querer que mostre apenas três elementos na dataGrid (ficaria meio furada) para isso não acontecer, a dataGrid preenche todos os lugares, não deixando apenas três elementos e um espaço em branco, as vezes mesmo eu explicando fica difícil de entender, por isso aconselho fazer testes com ela.

Enfim, o código fonte completo:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <p:messages id="mensagens" showDetail="true" />
        <p:commandButton value="Confirmar" onclick="confirmacao.show()" type="button"/>
        <h:form>
            <p:confirmDialog widgetVar="confirmacao" header="Confirmar" message="Deseja confirmar alguma coisa?" severity="alert" modal="true">
                <p:commandButton value="Sim" update="mensagens" oncomplete="confirmacao.hide()" actionListener="#{testeBean.confirmar}" />
                <p:commandButton value="Não" onclick="confirmacao.hide()" type="button" />
            </p:confirmDialog>
        </h:form>

        <p:separator />

        <p:commandButton value="Abrir janela" onclick="janela.show()" type="button" />
        <p:dialog widgetVar="janela" header="Novo..." modal="true" width="500" height="230">
            <h:form>
                <p:wizard nextLabel="Avançar" backLabel="Voltar">
                    <p:tab title="Slider">
                        <p:panel header="Testando o slider">
                            <h:outputText value="Numero:" /><br />
                            <p:inputText id="numero1" value="#{testeBean.numeroSlider}"/>
                            <p:slider for="numero1" minValue="-100" maxValue="100" style="width: 127px"/>
                        </p:panel>
                    </p:tab>
                    <p:tab title="Spinner">
                        <p:panel header="Testando o spinner">
                            <h:outputText value="Valor:" /><br />
                            <p:spinner value="#{testeBean.valorSpinner}" min="-10" max="10" stepFactor="0.10" showOn="hover"/>
                        </p:panel>
                    </p:tab>
                </p:wizard>
            </h:form>
        </p:dialog>

        <p:separator />

        <h:form>
            <p:dataTable value="#{testeBean.animais}" var="a" paginator="true" rows="4">
                <p:column headerText="Nome dos animais">
                    <h:outputText value="#{a}" />
                </p:column>
            </p:dataTable>
        </h:form>

        <p:separator />

        <h:form>
            <p:dataGrid value="#{testeBean.animais}" var="a" paginator="true" columns="2" rows="4">
                <p:column>
                    <p:panel header="Animal">
                        <h:outputText value="Este animal é um #{a}" />
                    </p:panel>
                </p:column>
            </p:dataGrid>
        </h:form>

    </h:body>
</html>

Acredito que por hoje chega... =)

22 de maio de 2011

JasperReports 4.0.1: Utilizando JDBC datasource

Para quem está perdido no assunto, aconselho que vejam o início de tudo, nesse link também tem as ferramentas que vamos utilizar: iReport 4.0.1 e a biblioteca JasperReports 4.0.1 ... JasperReports 4.0.1: Conhecendo o iReport 4.0.1
Pra quem já está por dentro das postagens: depois de vermos como utilizar JavaBeans datasource em relatórios do JasperReports, vamos para uma parte mais simples, usar JDBC como datasource. Para este exemplo irei usar o banco de dados MySQL... 

Preparando o banco de dados..
No banco de dados MySQL eu vou usar uma database com o nome de 5tads, dentro dela eu vou criar uma tabela com as seguintes informações:


Nesse ponto já aconselho que insira alguns clientes dentro dessa tabela, vamos precisar mais pra frente pra fazer os testes!

Estrutura básica do relatório...
Tendo o iReport aberto, vamos criar um novo relatório do formato Blank A4 e vamos colocar o nome de relatorioJDBC. A estrutura básica do nosso relatório será baseada no que vimos na postagem sobre "Conhecendo o iReport 4.0.1", para este relatório eu removi as bands: Page Header, Column Footer e Sumary, pois não irei precisar delas, abaixo eu digo o que eu coloquei em cada band que ficou:
Title: apenas um static text que é o "Relação de Clientes";
Column Header: são quatro static text referentes às colunas que eu quero do meu relatório;
Detail 1: são quatro text field que são alinhados aos static text da band acima, e
Page Footer: utilizei dois componentes da paleta Tools, que são o Current Date e Page X of Y.

Criando o datasource...
Agora precisamos pegar os fields para colocar nos nossos text field da band Detail 1. Para isso vamos criar um datasource que vai fazer a conexão com o nosso banco de dados, e assim podermos pegar as colunas da tabela cliente.
No iReport, procure o botão Report datasources:


Na janela que abrir, clique no botão New, o que aparece é:

Nisso selecione a primeira opção mesmo, "Database JDBC connection" e clique em Next:

Na tela acima em JDBC URL, altere MYDATABASE para o nome da sua database (a minha é 5tads), e informe o username e a senha do seu banco de dados, veja se os dados estão corretos clicando em  Test caso esteja tudo certo é só salvar a conexão:

Deixe a conexão recém criada, marcada como Default e pode fechar a janela.

Buscando os fields...
Ainda no iReport procure o botão Report Query:


A janela que irá abrir está por padrão na tab que precisamos que é a Report Query mesmo. Para buscar os fields basta fazer um select do SQL na tabela que deseja, pode-se usar querys com JOIN's e tudo mais:

Conforme vai escrevendo a query no campo ele vai trazendo os fields abaixo... para selecionar eles basta dar um OK nessa janela, só para confirmar vá no Report Inspector e procure por Fields:


Feito isso, agora basta configurar corretamente os text fields com os fields selecionados:

Obs: na imagem acima o text field correspondente ao limite credito aparece apenas $F, mas é porque o campo está pequeno alí e não está cabendo o texto inteiro, então o correto mesmo é $F{limite_credito}

Ao utilizar o JDBC como datasource, é possível visualizar o relatório diretamente no iReport, basta clicar em Preview:

A visualização é:

Pela imagem não dá pra ver, mas os campos Data Nasc. e Limite não estão formatados, eu quero que a data apareça no formato dd/MM/yyyy e o limite tenha as casas decimais separadas por vírgula e não por ponto, para isso eu preciso alterar as propriedades do text fields correspondentes a eles. 
Data Nasc:


Limite crédito:


Depois de corrigido, volto a visualizar o relatório, o resultado é:


Para utilizar esse relatório, irei disponibilizar duas formas:
* Utilizar em projetos Web: Veja aqui
* Utilizar em projetos Desktop: Veja aqui