10 de junho de 2011

XStream: Criando e lendo arquivos XML

Caso ainda não tenha precisado criar ou ler arquivos XML em Java, pelo menos já parou pra pensar como fazer isso? Criar uma String gigante concatenando valores e tags? Hoje em dia não há necessidade de se utilizar métodos tão "complexos" assim. Existe uma biblioteca chamada de XStream, onde objetos podem ser transformados em XML, e vice versa.
Obs: o XStream gera uma String em formato de XML, e não o arquivo XML propriamente dito, mas este é gerado com a ajuda do FileOutputStream do Java.
Então para fazer este exemplo vamos precisar de dois .jar, um é do próprio XStream e o outro é o Dom4J. Para baixar os dois juntos, clique aqui.

Estrutura do projeto
Nosso projeto irá ficar com essa estrutura:


Depois de muito tempo venho editar esta postagem sobre XStream...
Dentro do pacote model temos duas classes, um é o Endereco e a outra é Pessoa.
Classe Endereco:
@XStreamAlias("endereco")
public class Endereco {

    private String rua;
    private String cidade;

    //gettters e setters
}
A anotação @XStreamAlias é necessária quando vai fazer a leitura de uma String XML.
A Classe Pessoa:
public class Pessoa {

    private String nome;
    private String cpf;
    private List<Endereco> enderecos;
  
    //getters e setters
}

Bom agora vamos ver o que desejamos fazer e como fazer... Vamos começar pelo mais simples, caso queira gerar um XML de um endereço que está dessa forma:
<endereco>
  <rua>Rua das araras</rua>
  <cidade>Primavera do Leste</cidade>
</endereco>

Eu preciso do seguinte código:
private static void gravaEndereco() {
        Endereco endereco = new Endereco();
        endereco.setCidade("Primavera do Leste");
        endereco.setRua("Rua das araras");

        XStream xStream = new XStream();
        xStream.alias("endereco", Endereco.class);
       
        File arquivo = new File("endereco.xml");
        FileOutputStream gravar;
        try {
            gravar = new FileOutputStream(arquivo);
            gravar.write(xStream.toXML(endereco).getBytes());
            gravar.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

Lembrando que a parte de gravar o arquivo não é do XStream, a String é gerada pelo seguinte código: xStream.toXML(endereco), o mesmo vale para os próximos métodos...

Agora caso queira gravar uma lista de endereços em XML, que fique dessa forma:
<enderecos>
  <endereco>
    <rua>Rua abc</rua>
    <cidade>Cuiaba</cidade>
  </endereco>
  <endereco>
    <rua>Avenida São João</rua>
    <cidade>Primavera do Leste</cidade>
  </endereco>
</enderecos>

É necessário o seguinte método:
private static void gravaListaEndereco() {
        List<Endereco> enderecos = new ArrayList<Endereco>();

        Endereco e1 = new Endereco();
        e1.setCidade("Cuiaba");
        e1.setRua("Rua abc");
        enderecos.add(e1);

        Endereco e2 = new Endereco();
        e2.setCidade("Primavera do Leste");
        e2.setRua("Avenida São João");
        enderecos.add(e2);

        XStream xStream = new XStream();
        xStream.alias("enderecos", List.class);
        xStream.alias("endereco", Endereco.class);

        File arquivo = new File("enderecos.xml");
        FileOutputStream gravar;
        try {
            gravar = new FileOutputStream(arquivo);
            gravar.write(xStream.toXML(enderecos).getBytes());
            gravar.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

Agora vamos ver algo mais complicado, que é gravar objetos que contenham listas dentro dele... ou seja vamos criar um XML que represente uma lista de pessoas (nosso model lá do início):
<pessoas>
  <pessoa>
    <nome>Andii</nome>
    <cpf>123.123.123-34</cpf>
    <enderecos>
      <endereco>
        <rua>Rua 123</rua>
        <cidade>Primavera do Leste</cidade>
      </endereco>
    </enderecos>
  </pessoa>
  <pessoa>
    <nome>Maria</nome>
    <cpf>345.656.235-98</cpf>
    <enderecos>
      <endereco>
        <rua>Avenida das flores</rua>
        <cidade>Cuiabá</cidade>
      </endereco>
      <endereco>
        <rua>Rua das abelhas</rua>
        <cidade>Cuiabá</cidade>
      </endereco>
    </enderecos>
  </pessoa>
</pessoas>
Para gerar esta estrutura precisamos o seguinte método:
private static void gravaListaCompleta() {
        Pessoa pessoa1 = new Pessoa();
        pessoa1.setNome("Andii");
        pessoa1.setCpf("123.123.123-34");

        Endereco endereco1 = new Endereco();
        endereco1.setCidade("Primavera do Leste");
        endereco1.setRua("Rua 123");

        List<Endereco> enderecos1 = new ArrayList<Endereco>();
        enderecos1.add(endereco1);
        pessoa1.setEnderecos(enderecos1);

        Pessoa pessoa2 = new Pessoa();
        pessoa2.setNome("Maria");
        pessoa2.setCpf("345.656.235-98");

        Endereco endereco2 = new Endereco();
        endereco2.setCidade("Cuiabá");
        endereco2.setRua("Avenida das flores");

        Endereco endereco3 = new Endereco();
        endereco3.setCidade("Cuiabá");
        endereco3.setRua("Rua das abelhas");

        List<Endereco> enderecos2 = new ArrayList<Endereco>();
        enderecos2.add(endereco2);
        enderecos2.add(endereco3);
        pessoa2.setEnderecos(enderecos2);

        List<Pessoa> pessoas = new ArrayList<Pessoa>();
        pessoas.add(pessoa1);
        pessoas.add(pessoa2);

        XStream xStream = new XStream();

        xStream.alias("pessoas", List.class);
        xStream.alias("pessoa", Pessoa.class);
        xStream.alias("endereco", Endereco.class);

        File arquivo = new File("pessoas.xml");
        FileOutputStream gravar;
        try {
            gravar = new FileOutputStream(arquivo);
            gravar.write(xStream.toXML(pessoas).getBytes());
            gravar.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
E enfim para lermos uma String XML, precisamos do método abaixo, para o exemplo de leitura eu estarei utilizando o arquivo gerado em um dos métodos acima, aquele que gera uma lista de endereços:
private static void lerXML() {
        try {
            XStream xStream = new XStream(new Dom4JDriver());
            xStream.alias("enderecos", ArrayList.class);
            xStream.processAnnotations(Endereco.class);

            BufferedReader input = new BufferedReader(new FileReader("enderecos.xml"));
            ArrayList<Endereco> enderecos = (ArrayList) xStream.fromXML(input);
            input.close();

            for (Endereco endereco : enderecos) {
                System.out.println("Endereço: " + endereco.getRua() + " - " + endereco.getCidade());
            }

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
Veja que eu leio o arquivo utilizando BufferedReader e tendo esse arquivo "carregado" utilizo do XStream para gerar uma lista para mim... Lembrando que dessa vez eu preciso da anotação lá na classe Endereco, o resultado da leitura do método acima é:
Endereço: Rua abc - Cuiaba
Endereço: Avenida São João - Primavera do Leste
Bom... peço desculpas pela demora a fazer as explicações do XStream... Mas está aí :)

Observação final: como vocês podem ver, eu não coloquei um endereço fixo de onde armazenar meus arquivos, era apenas new file("endereco.xml") ... para quem não sabe isso gera o arquivo dentro da pasta do projeto.

7 de junho de 2011

JSF 2.0: Componentes PrimeFaces 2.2.1 - Parte 5

Depois de vermos sobre menus do PrimeFaces, nessa postagem vamos ver alguns outros componentes. Vamos precisar de algumas umas imagens e algumas bibliotecas extras, baixe por aqui.

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


O primeiro componente que veremos hoje é o dataExporter que serve para exportar os dados para arquivos PDF, XLS, XML ou CSV de uma determinada dataTable, então para isso eu preciso de uma dataTable:


Código-fonte:
Para este exemplo vamos precisar de uma classe Carro (pojo), então dentro de pacote de códigos fonte crie um novo pacote com o nome de model, e dentro dele crie uma nova classe Java com o nome de Carro:
public class Carro {

    private String marca;
    private int ano;
    private String placa;
    private String cor;
    private String modelo;

    public Carro(String marca, int ano, String placa, String cor, String modelo) {
        this.marca = marca;
        this.ano = ano;
        this.placa = placa;
        this.cor = cor;
        this.modelo = modelo;
    }

   //GETTERS e SETTERS
}

Agora vamos criar o nosso bean que vai dar suporte à nossa dataTable, para isso crie um pacote com o nome de controle, dentro desse pacote crie  uma nova classe Java com o nome de CarroBean:
@Named
@RequestScoped
public class CarroBean {

    private List<Carro> carros;

    public CarroBean() {
        listarCarros();
    }

    private void listarCarros() {
        carros = new ArrayList<Carro>();
        carros.add(new Carro("Fiat", 2011, "DFV 3455", "Verde", "Novo Uno"));
        carros.add(new Carro("Toyota", 2009, "ADV 3245", "Prata", "Prado"));
        carros.add(new Carro("Volks", 2010, "AAC 2351", "Vermelho", "Gol"));
        carros.add(new Carro("Volks", 2011, "EGF 1245", "Preto", "Cross Fox"));
    }

    //Gerar GET e SET
}
Bom nem tem o que explicar o código acima... Para este exemplo vamos precisar das imagens (do link que disponibilizei lá no inicio), por enquanto só irei precisar de: xsl.png e pdf.png, dentro de páginas web, crie um novo diretório com o nome de imagens, e coloque as imagens dentro dela. Agora vamos para a página index:
<h:form>
    <p:dataTable id="tabelaCarros" value="#{carroBean.carros}" var="c">
        <p:column>
            <f:facet name="header">Marca</f:facet>
            <h:outputText value="#{c.marca}" />
        </p:column>
        <p:column>
            <f:facet name="header">Modelo</f:facet>
            <h:outputText value="#{c.modelo}" />
        </p:column>
        <p:column>
            <f:facet name="header">Ano</f:facet>
            <h:outputText value="#{c.ano}" />
        </p:column>
        <p:column>
            <f:facet name="header">Cor</f:facet>
            <h:outputText value="#{c.cor}" />
        </p:column>
        <p:column>
            <f:facet name="header">Placa</f:facet>
            <h:outputText value="#{c.placa}" />
        </p:column>
    </p:dataTable>

    <h:commandLink>
        <p:graphicImage value="/imagens/xls.png" />
        <p:dataExporter type="xls" target="tabelaCarros" fileName="carros" />
    </h:commandLink>
    <h:commandLink>
        <p:graphicImage value="/imagens/pdf.png" />
        <p:dataExporter type="pdf" target="tabelaCarros" fileName="carros"/>
    </h:commandLink>
</h:form>
No código acima eu tenho uma dataTable normal (vista em postagens anteriores) e logo abaixo dela eu tenho os dataExporter, o detalhe mais importante é quanto a propriedade target, veja que ela corresponde ao id da tabela.

Nosso segundo componente é o pickList:


Vamos direto ao código, então dentro do pacote controle (criado anteriormente) vamos criar uma classe com o nome de PicklistBean:
@Named
@RequestScoped
public class PicklistBean {

    private DualListModel<String> cores;

    public PicklistBean() {
        listarCores();
    }

    private void listarCores() {
        List<String> lista = new ArrayList<String>();
        List<String> selecionados = new ArrayList<String>();

        lista.add("Azul");
        lista.add("Amarelo");
        lista.add("Vermelho");
        lista.add("Verde");
        lista.add("Roxo");

        cores = new DualListModel<String>(lista, selecionados);
    }

    public void mostrarCoresSelecionadas() {
        for (String cor : cores.getTarget()) {
            System.out.println("Esta cor é: " + cor);
        }
    }

    //Gerar GET e SET
}
Veja que usamos um DualListModel (do próprio PrimeFaces), para inicializar ele eu preciso informar duas listas, uma é dos os objetos a serem selecionados (chamada de source) e a outra representará o objetos selecionados(target), o método mostrarCoresSelecionadas() percorre a lista de cores selecionadas, repare que ele dá um getTarget() ... para pegar a lista original é só dar um getSource().
<h:form>
    <p:pickList value="#{picklistBean.cores}" var="cor" iconOnly="true" itemLabel="#{cor}" itemValue="#{cor}">
        <f:facet name="sourceCaption">Lista</f:facet>
        <f:facet name="targetCaption">Selecionadas</f:facet>
    </p:pickList>
    <p:commandButton value="Ver cores selecionadas" actionListener="#{picklistBean.mostrarCoresSelecionadas}" />
</h:form>
Ao final do código eu coloquei um commandButton que chama o método para listar as cores selecionadas.

O nosso próximo componente é o printer, ele é um componente que chama a função de impressão do navegador, com a diferença que o programador define qual a parte da página será impressa, para usar ele eu vou precisar da imagem printer.png (no arquivo que eu passei), coloque-o dentro do diretório imagens. Vou mostra-lo junto com o próximo componente, mas antes segue o código:
<h:outputLink id="lnk" value="#">
    <p:printer target="quebraCabeca" />
    <p:graphicImage value="/imagens/print.png" />
</h:outputLink>
Repare que o target se refere a um elemento quebraCabeca, ele corresponde a uma parte da página que eu quero que seja impresso, nesse caso este quebraCabeca será o próximo elemento a ser feito.

Para finalizar vamos ver o componente dashboard, que em um sistema comercial eu não vi muita utilidade, então para este exemplo eu resolvi criar um quebra cabeça meio desengonçado com ele!


Quanto a impressora que aparece acima na imagem, esta corresponde ao componente printer. Vamos começar então com o nosso quebra-cabeça, primeiramente precisamos pegar as imagens que eu passei lá no inicio e coloca-las no projeto. Primeiro dentro do diretório imagens crie um novo diretório com o nome de jogo: dentro dele coloque as imagens a.jpg, b.jpg até a imagem i.jpg... Abaixo segue a classe Java QuebraCabecaBean que deve ser criado dentro do pacote controle:
@Named
@RequestScoped
public class QuebraCabecaBean {

    private DashboardModel pecas;

    public QuebraCabecaBean() {
        listarPecas();
    }

    private void listarPecas() {
        pecas = new DefaultDashboardModel();
        DashboardColumn coluna1 = new DefaultDashboardColumn();
        DashboardColumn coluna2 = new DefaultDashboardColumn();
        DashboardColumn coluna3 = new DefaultDashboardColumn();

        coluna1.addWidget("f");
        coluna1.addWidget("c");
        coluna1.addWidget("g");

        coluna2.addWidget("h");
        coluna2.addWidget("a");
        coluna2.addWidget("d");

        coluna3.addWidget("i");
        coluna3.addWidget("e");
        coluna3.addWidget("b");

        pecas.addColumn(coluna1);
        pecas.addColumn(coluna2);
        pecas.addColumn(coluna3);
    }

    //Gerar GET e SET
}
Veja que eu incluo as letras embaralhadas dentro do DashboardColumn, realmente para iniciarem embaralhadas, só temos um detalhe: para cada letra que eu coloquei nessa lista eu preciso de um componente com o id do mesmo nome dentro do componente dashboard, apenas colocar os painéis no xhtml com as imagens não é suficiente eu preciso ter esse espelho entre o bean e a página:
<h:form id="quebraCabeca">
    <p:dashboard model="#{quebraCabecaBean.pecas}">
        <p:panel id="f">
            <p:graphicImage url="/imagens/jogo/f.jpg" />
        </p:panel>
        <p:panel id="c">
            <p:graphicImage url="/imagens/jogo/c.jpg" />
        </p:panel>
        <p:panel id="g">
            <p:graphicImage url="/imagens/jogo/g.jpg" />
        </p:panel>

        <p:panel id="h">
            <p:graphicImage url="/imagens/jogo/h.jpg" />
        </p:panel>
        <p:panel id="a">
            <p:graphicImage url="/imagens/jogo/a.jpg" />
        </p:panel>
        <p:panel id="d">
            <p:graphicImage url="/imagens/jogo/d.jpg" />
        </p:panel>

        <p:panel id="i">
            <p:graphicImage url="/imagens/jogo/i.jpg" />
        </p:panel>
        <p:panel id="e">
            <p:graphicImage url="/imagens/jogo/e.jpg" />
        </p:panel>
        <p:panel id="b">
            <p:graphicImage url="/imagens/jogo/b.jpg" />
        </p:panel>
    </p:dashboard>
</h:form>

A solução do quebra cabeça é este:


OBS: Quanto ao quebra cabeça este foi improvisado, já que a postagem original era para ser falado sobre os gráficos do PrimeFaces, mas que infelizmente não consegui fazer funcionar.
Mas pensem comigo, antes isso do que nada né!? :P

4 de junho de 2011

JasperReports 4.0.1: Utilizando Subreports e parâmetros

Para esta não ser uma postagem muito extensa, irei utilizar o mesmo projeto e o mesmo relatório criado na postagem: agrupando de dados com JasperReports. Para completar esse projeto, logo abaixo do agrupamento eu vou listar os dados dos cliente, ou seja, terei um relatório de clientes embutido no relatório de pedidos (claro que pode ser feito outras coisas, este é apenas um exemplo)

Começando...
Então lá no projeto Pedidos (link acima), dentro do pacote pedidos.dao, vamos criar uma classe Java como o nome de ClienteDAO, seguindo a mesma linha da classe PedidoDAO, temos:
public class ClienteDAO {

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("PedidosPU");
    EntityManager em = emf.createEntityManager();

    public List<Cliente> listarClientes() {
        List<Cliente> clientes = null;
        try {
            Query query = em.createQuery("Select c from Cliente c order by c.nome");
            clientes = query.getResultList();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            em.close();
        }
        return clientes;
    }
}

No iReport, vamos editar o relatório pedidos.jrxml, criando também no link da postagem acima.
Para começar no relatório vamos adicionar a band Summary:


Precisamos criar um parâmetro que será enviado pelo projeto, para isso no Report Inspector, clique com o botão direito em Parameters, e em Adicionar Parameter:


Selecione o parameter1 e vá nas propriedades para configurá-lo, altere o nome para listaClientes e o Parameter class para java.util.List, pois passaremos por parâmetro uma lista de clientes:


Na paleta procure pelo elemento Subreport, arraste-o para a band Summary, a partir de agora siga as imagens abaixo:


Clique em próximo, na janela abaixo selecione o tipo Blank A4:


Clique em próximo novamente, como estamos usando JavaBean datasource, e não utilizamos datasource, configure como na imagem:


Avance de novo:


Mais uma vez:


Na janela abaixo informe o nome do Subreport, nesse caso será chamado de pedidos_subreport:


No passo 7, habilite a opção "Use a JRDatasource expression", e clique no botão do lado da caixa de texto, a seguinte janela aparecerá, nela nós convertemos a listaClientes em um JRBeanCollectionDataSource :


Ao clicar em Apply voltamos para a seguinte janela:



E aqui basta finalizar...
No relatório que foi criado, deixe apenas as bands - Title, Column Header e Detail 1:


Como será uma lista de clientes, precisamos pegar da classe Cliente os seguintes fields - codigo, nome e limiteCredito... para isso em Report Query, na aba JavaBean Datasource:

Feito isso...
Como visto em postagens anteriores, estruture o relatório para que fique assim:


Ah, lembre-se de nas propriedades do relatório alterar a linguagem para Java, já que estamos usando JavaBean datasource:


Depois disto basta compilar nosso subreport, para poder gerar o pedidos_subreport.jasper 

Voltamos ao pedidos.jrxml, e vamos fazer umas ultimas configurações, temos este resultado:

Precisamos criar mais um parâmetro que será uma String com o caminho de onde encontrar o pedidos_subreport.jasper, repita o mesmo passo que foi feito para criar o listaClientes, mas dessa vez use as seguintes propriedades:


Agora precisamos setá-lo no lugar certo... para isso: veja que na band Summary tem um elemento que representa o subreport, clique nele e vá nas propriedades, procure por Subreport Expression, e configure-o assim:


Feito todos esses passos, pode compilar novamente o relatório principal (pedidos)...
Caso não ocorra nenhum erro, voltamos ao projeto Pedidos no NetBeans.

No projeto..
No pacote pedidos,controle.relatorios, substitua o pedidos,jasper pelo que foi compilado agora, e adicione o pedidos_subreport.jasper, ficando assim:

Para finalizar de vez, precisamos fazer algumas alterações no método gerarRelatorio() da classe PedidoControle.java:
public void gerarRelatorio() {
     String arquivo = "src/pedidos/controle/relatorios/pedidos.jasper";

     pedidoDAO = new PedidoDAO();
     clienteDAO = new ClienteDAO();

     Map parametros = new HashMap();
     parametros.put("localizacaoPedidosSubreport", "src/pedidos/controle/relatorios/pedidos_subreport.jasper");
     parametros.put("listaClientes", clienteDAO.listarClientes());

     JRDataSource jrds = new JRBeanCollectionDataSource(pedidoDAO.listarPedidos());
    gerarRelatorioDesktop(jrds, parametros, arquivo);
}

No começo da classe lembre-se de adicionar a declaração do ClienteDAO, assim como foi feito para PedidoDAO...
Vamos ver o que foi alterado no método...
Primeiro, depois de declarado o atributo clienteDAO no inicio da classe, na linha 5 estamos inicializando-o.
Da linha 7 a 9, criamos um Map, com os parâmetros que criamos lá no iReport... e por fim... na linha 12, passávamos o parâmetro como null, agora este é substituído e passamos o Map parametros por parâmetro.

Assim podemos executar nosso projeto e ver o seguinte resultado:


Por aqui ficamos... admito que tive alguns probleminhas ao conseguir utilizar o JavaBean datasource no subreport, o que me levou a pedir um help no Twitter onde o @altitdb me ajudou! por isso deixo os devidos créditos à ele :)

Créditos da postagem: Altieres de Matos, pois ele salvou minha aula sobre Subrepot hehe (pois é, tive problemas ao usar Subreport com JavaBean datasource)

JasperReports 4.0.1: Agrupando dados

Na postagem de hoje vamos agrupar os pedidos por cliente, assim:


Para este exemplo eu vou utilizar o JPA (visto em postagens anteriores), em um projeto Desktop, só para ser mais rápido, o foco da postagem será o agrupamento então para outros detalhes colocarei apenas os links com exemplos.

Banco de dados
Antes de começar vamos ver qual será as tabelas utilizadas no banco de dados:


Criando o projeto..
Inicialmente vamos no NetBeans criar um novo Aplicativo Java(Desktop) com o nome de Pedidos. Dentro do pacote pedidos(criado por padrão) crie um pacote com o nome de model, ficando assim: pedidos.model, as classes do model serão criadas pelo JPA, ou seja serão geradas a partir do banco, caso não saiba como fazer, veja aqui. Quando geradas o projeto ficará com essa estrutura:

Por eu estar utilizando o MySQL preciso incluir a biblioteca do mesmo dentro do projeto... então em Bibliotecas adicione a biblioteca MySQL JDBC Driver que já tem no NetBeans, caso contrário é facilmente encontrado na Internet.

Novamente dentro do pacote pedidos, crie um novo pacote com o nome de dao, ficando como: pedidos.dao, e dentro dele crie uma nova classe Java com o nome de PedidoDAO.java:
public class PedidoDAO {

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("PedidosPU");
    EntityManager em = emf.createEntityManager();

    public List<Pedido> listarPedidos() {
        List<Pedido> pedidos = null;
        try {
            Query query = em.createQuery(
                    "Select p from Pedido p order by p.cliente.nome");
            pedidos = query.getResultList();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            em.close();
        }
        return pedidos;
    }
}
OBS: ao criar o EntityManagerFactory veja que passo por parâmetro  a String PedidosPU, este valor é  o nome da Persistence Unit, que é encontrado no persistence.xml, por isso confirme se é este o nome que aparece no seu persistence.
Outro detalhe é quanto a consulta... essa parte é de extrema importância: para eu poder agrupar os dados, eu preciso mandar as informações ordenadas de acordo pelo o que eu quero agrupar, neste caso eu quero agrupar por cliente, então dou um order by pelo nome do cliente.
Até agora esse é o nosso projeto:


Depois de ter feito isso, no NetBeans clique em Limpar e Construir, para que ele gere o nosso .jar
Agora vamos dar uma pausa no projeto e vamos criar nosso .jasper...

No iReport
Como vamos utilizar o datasource do tipo JavaBean datasource, aconselho ver esta postagem antes de continuar, caso contrário não será possível entender o que está sendo feito.
No iReport aberto, crie um novo relatório do tipo Blank A4, para mais informações de como criar um relatório veja aqui, e coloque o nome do mesmo como pedidos... depois de criado, nas propriedades do report troque a Language para Java:


Agora antes de continuar, lembre-se de setar no classpath do iReport (ver na postagem sobre JavaBean datasource) o .jar criado do projeto acima...Depois de feito isso, vamos deixar no nosso relatório apenas as seguintes bands: Title, Column Header e Detail 1, quanto as outras pode removê-las, ficando assim:


Agora vamos pegar os fields que vamos precisar para fazer o relatório... então em Report Query vamos selecionar os atributos da classe Pedido... para isso, faça como na imagem abaixo:


No Report Inspector, confirme se os fields foram criados, caso sim, ainda no Report Inspector, na raiz (pedidos) clique com o botão direito e vá em Add report group, coloque o nome de pedido:


Ao clicar em próximo, aparece a seguinte tela, onde pode deixar marcado apenas a opção de Add the group header, pois o group footer não iremos utilizar, e por fim clique em Finalizar:


O nosso relatório passa a ter as seguintes bands:


Agora vamos estruturar nosso relatório, deixando-o assim (abaixo da imagem digo o que tem em cada band), aconselho clicar na imagem para ampliar e ver corretamente as bands:


Primeiramente na band Title, foi colocado apenas um static text como título do relatório. Logo abaixo no Column Header, tem mais um static text informando o "Nome do Cliente"... agora no pedido Group Header 1  que é onde a coisa acontece eu coloquei um text field com o field que pega o nome do cliente, e ainda na mesma band, logo abaixo do text field eu adicionei dois static text: um para código e outro para o valor do pedido. Por fim na band Detail 1, é colocado dois text fields referentes ao código e ao valor (lembrar de alterar os expression class dos text fields de acordo com o tipo dos fields)
Feito tudo isso vamos compilar o nosso relatório para gerar o .jasper (no botão que parece um martelinho) caso não dê nenhum problema podemos continuar no projeto agora.

Voltando ao projeto...
Novamente no pacote pedidos vamos criar agora nosso pacote controle, ficando assim: pedidos.controle e dentro dele crie uma classe Java com o nome de PedidoControle.java, antes de fazermos a codificação dela, vamos dentro do pacote controle, criar um pacote relatorios onde iremos armazenar nosso .jasper, ficando dessa forma: pedidos.controle.relatorios e dentro dele jogue o .jasper gerado ao compilar o relatório:

Antes que esqueçamos, precisamos jogar as bibliotecas do JasperReports dentro do projeto, caso não as tenha ainda, pode consegui-las nesta postagem. Agora sim vamos editar a classe PedidoControle:
public class PedidoControle {

    private PedidoDAO pedidoDAO;

    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();
        }
    }

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

        pedidoDAO = new PedidoDAO();

        JRDataSource jrds = new JRBeanCollectionDataSource(pedidoDAO.listarPedidos());
        gerarRelatorioDesktop(jrds, null, arquivo);
    }
}

Como já foi visto em outras postagens não irei explicar novamente o que acontece neste código.
Para finalizar, vamos chamar nosso método gerarRelatorio() na classe Main.java:
public class Main {

    public static void main(String[] args) {
        PedidoControle controle = new PedidoControle();
        controle.gerarRelatorio();
    }
}

Bom... ao executar o projeto, se tudo ocorrer bem, abrirá a janela no JasperViewer, o resultado será:


E por aqui ficamos com mais uma postagem sobre JasperReports... =)

1 de junho de 2011

JSF 2.0: Componentes PrimeFaces 2.2.1 - Parte 4

Continuando com a série de postagens de componentes PrimeFaces 2.2.1, hoje vamos ver a utilização de layout e menus! Teremos menus para todas as necessidades ;)
Lembrando, que na postagem anterior vimos alguns componentes do tipo dialog, confirmDialog, entre outros: clique aqui para acessar.
Para esse projeto, vamos precisar de alguns ícones... estou disponibilizando-os aqui, mas se quiser use seus próprios ícones: baixar aqui.

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


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


Nessa imagem temos o layout e os menus do PrimeFaces...

Nesse exemplo vamos usar o layout de tela inteira, e aproveitando este layout vamos encaixando os menus nele:

Código-fonte do componente:
<p:layout fullPage="true">
    <p:layoutUnit position="top" height="50">
    </p:layoutUnit>
    <p:layoutUnit position="left" width="180" header="Menu" collapsible="true" >
    </p:layoutUnit>
    <p:layoutUnit position="center" header="Sistema">
    </p:layoutUnit>
</p:layout>
Veja que quem cria as divisões é o componente layoutUnit, aconselho ver o link acima para ver as outras possibilidades de uso do layout.

Agora começamos com os menus, estes pouca coisa diferem entre si...

O primeiro que vamos usar é o breadCrumb, ele é um menu na horizontal:


Código-fonte do componente:
<p:breadCrumb>
    <p:menuitem value="Home" url="http://www.google.com.br" />
    <p:menuitem value="Documentos" url="#" />
    <p:menuitem value="Musicas" url="#" />
    <p:menuitem value="Imagens" url="#" />
    <p:menuitem value="Zip" url="#" />
</p:breadCrumb>
Veja que ele é composto por menuitem... na realidade todos os menus do PrimeFaces  são compostos de menuitem, por isso nos outros menus vamos os mesmos do exemplo acima. Nos menus quem faz a diferença é o componente-pai, no caso acima é a tag breadCrumb, o detalhe é que pra esse componente ele não aceita ícones no menuitem.
Obs: pode-se abrir dialogs(visto na parte 3) com os menuitem, para isso use a propriedade onclick deste...

O outro menu é na vertical, este tem também submenus, e com a diferença que ele aceita icones nos menuitem:


Obs: essa é uma das formas de usar ele, no link do menu tem outras formas bem interessantes de menu na posição vertical.
Código-fonte do componente:
<p:menu style="width: 98%">
    <p:submenu label="Contas...">
        <p:menuitem value="... a pagar" url="#" />
        <p:menuitem value="... a receber" url="#" />
    </p:submenu>
    <p:submenu label="Outros">
        <p:menuitem value="Home" url="http://www.google.com.br" />
        <p:menuitem value="Documentos" url="#" />
        <p:menuitem value="Musicas" url="#" />
        <p:menuitem value="Imagens" url="#" />
        <p:menuitem value="Zip" url="#" />
    </p:submenu>
    <p:submenu>
        <p:menuitem value="Sair" url="#" icon="ui-icon ui-icon-power" />
    </p:submenu>
</p:menu>
veja que eu defini o style na tag menu, fiz isto pois quero que este menu se adapte ao layout que ele se encontra e conforme redimensionar a janela, ele também se redimensionará (isso também pode ser feito em outros componentes que tenham a propriedade style)

O próximo menu é um menubar, na horizontal que também aceita ícones, mas este permite que tenha submenus:


Código-fonte do componente:
<p:menubar>
    <p:submenu label="Contas...">
        <p:menuitem value="... a pagar" url="#" />
        <p:menuitem value="... a receber" url="#" />
    </p:submenu>
    <p:submenu label="Outros">
        <p:menuitem value="Home" url="http://www.google.com.br" />
        <p:menuitem value="Documentos" url="#" />
        <p:menuitem value="Musicas" url="#" />
        <p:menuitem value="Imagens" url="#" />
        <p:menuitem value="Zip" url="#" />
    </p:submenu>
    <p:menuitem value="Sair" url="#" icon="ui-icon ui-icon-power" />
</p:menubar>

Agora pra quem não tem espaço na página, temos um botão menu que abre na posição vertical e também aceita ícones... que é o menuButton.
Fechado:

Clicado:


Código-fonte do componente:
<h:form>
    <p:menuButton value="Menu...">
        <p:menuitem value="Home" url="http://www.google.com.br" />
        <p:menuitem value="Documentos" url="#" />
        <p:menuitem value="Musicas" url="#" />
        <p:menuitem value="Imagens" url="#" />
        <p:menuitem value="Zip" url="#" />
        <p:menuitem value="Sair" url="#" icon="ui-icon ui-icon-power" />
    </p:menuButton>
</h:form>

Agora vamos para os menus bonitinhos e queridinhos com imagens!
Primeiramente vamos colocar aquelas imagens que eu passei lá no início, dentro do projeto... no meu caso eu estou colocando elas dentro do projeto de forma organizada, ou seja... dentro de Páginas Web, crie um novo diretório com o nome de imagens e dentro deste diretório coloque as imagens (.png).

Vamos começar pelo dock que funciona como o menu do Mac OS:


Obs: ele é um menu um pouco mais limitado, ou fica na parte superior da página ou na parte inferior da página (padrão)... mas dá um efeito muito legal :)
Código-fonte do componente:
<p:dock>
    <p:menuitem value="Home" url="http://www.google.com.br" icon="/imagens/home.png" />
    <p:menuitem value="Documentos" url="#" icon="/imagens/documentos.png" />
    <p:menuitem value="Musicas" url="#" icon="/imagens/musicas.png" />
    <p:menuitem value="Imagens" url="#" icon="/imagens/imagens.png" />
    <p:menuitem value="Zip" url="#" icon="/imagens/zip.png" />
</p:dock>

O outro é o stack, esse é outro menu com imagens, mas bem intessante... eu peguei a imagem padrão dele no site do PrimeFaces pra usar como base, mas você pode colocar a imagem que quiser.
Fechado:
Clicado:


Vamos as limitações... ele é um menu que aceita poucos menuitem, pois como pode ver na imagem acima, ele vai pendendo pro lado direito (deve ser o peso dos icones hahaha), e outro detalhe... ele só fica no canto inferior direito da página... pois é, não dá pra colocá-lo em qualquer lugar!
Código-fonte do componente:
<p:stack icon="/imagens/stack.png">
    <p:menuitem value="Home" url="http://www.google.com.br" icon="/imagens/home.png" />
    <p:menuitem value="Documentos" url="#" icon="/imagens/documentos.png" />
    <p:menuitem value="Musicas" url="#" icon="/imagens/musicas.png" />
    <p:menuitem value="Imagens" url="#" icon="/imagens/imagens.png" />
    <p:menuitem value="Zip" url="#" icon="/imagens/zip.png" />
</p:stack>

Bom... esses são os menus que eu selecionei para falar hoje do PrimeFaces, quando a esses dois últimos por serem mais limitados até coloquei-os fora do layout da página, para que funcionem melhor...

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>Primefaces - Parte 4</title>
    </h:head>
    <h:body>
        <p:layout fullPage="true">
            <p:layoutUnit position="top" height="50">
                <p:breadCrumb>
                    <p:menuitem value="Home" url="http://www.google.com.br" />
                    <p:menuitem value="Documentos" url="#" />
                    <p:menuitem value="Musicas" url="#" />
                    <p:menuitem value="Imagens" url="#" />
                    <p:menuitem value="Zip" url="#" />
                    <p:menuitem value="Sair" url="#" icon="ui-icon ui-icon-power" />
                </p:breadCrumb>
            </p:layoutUnit>
            <p:layoutUnit position="left" width="180" header="Menu" collapsible="true" >
                <p:menu style="width: 98%">
                    <p:submenu label="Contas...">
                        <p:menuitem value="... a pagar" url="#" />
                        <p:menuitem value="... a receber" url="#" />
                    </p:submenu>
                    <p:submenu label="Outros">
                        <p:menuitem value="Home" url="http://www.google.com.br" />
                        <p:menuitem value="Documentos" url="#" />
                        <p:menuitem value="Musicas" url="#" />
                        <p:menuitem value="Imagens" url="#" />
                        <p:menuitem value="Zip" url="#" />
                    </p:submenu>
                    <p:submenu>
                        <p:menuitem value="Sair" url="#" icon="ui-icon ui-icon-power" />
                    </p:submenu>
                </p:menu>
            </p:layoutUnit>
            <p:layoutUnit position="center" header="Sistema">
                <p:menubar>
                    <p:submenu label="Contas...">
                        <p:menuitem value="... a pagar" url="#" />
                        <p:menuitem value="... a receber" url="#" />
                    </p:submenu>
                    <p:submenu label="Outros">
                        <p:menuitem value="Home" url="http://www.google.com.br" />
                        <p:menuitem value="Documentos" url="#" />
                        <p:menuitem value="Musicas" url="#" />
                        <p:menuitem value="Imagens" url="#" />
                        <p:menuitem value="Zip" url="#" />
                    </p:submenu>
                    <p:menuitem value="Sair" url="#" icon="ui-icon ui-icon-power" />
                </p:menubar>
                <h:form>
                    <p:menuButton value="Menu...">
                        <p:menuitem value="Home" url="http://www.google.com.br" />
                        <p:menuitem value="Documentos" url="#" />
                        <p:menuitem value="Musicas" url="#" />
                        <p:menuitem value="Imagens" url="#" />
                        <p:menuitem value="Zip" url="#" />
                        <p:menuitem value="Sair" url="#" icon="ui-icon ui-icon-power" />
                    </p:menuButton>
                </h:form>
            </p:layoutUnit>
        </p:layout>

        <p:dock>
            <p:menuitem value="Home" url="http://www.google.com.br" icon="/imagens/home.png" />
            <p:menuitem value="Documentos" url="#" icon="/imagens/documentos.png" />
            <p:menuitem value="Musicas" url="#" icon="/imagens/musicas.png" />
            <p:menuitem value="Imagens" url="#" icon="/imagens/imagens.png" />
            <p:menuitem value="Zip" url="#" icon="/imagens/zip.png" />
        </p:dock>

        <p:stack icon="/imagens/stack.png">
            <p:menuitem value="Home" url="http://www.google.com.br" icon="/imagens/home.png" />
            <p:menuitem value="Documentos" url="#" icon="/imagens/documentos.png" />
            <p:menuitem value="Musicas" url="#" icon="/imagens/musicas.png" />
            <p:menuitem value="Imagens" url="#" icon="/imagens/imagens.png" />
            <p:menuitem value="Zip" url="#" icon="/imagens/zip.png" />
        </p:stack>

    </h:body>
</html>

Por hoje, ficamos por aqui! Ao final da série de componentes do PrimeFaces, crio a postagem de como usar o layout do PrimeFaces com os templates do Facelets.!

:)