Arquivo

Archive for the ‘JSF’ Category

Download de Exemplos

Olá,

Encontrei vários exemplos do blog e para facilitar subi alguns deles no DROPBOX.

https://www.dropbox.com/sh/d540t5o7iyt4zzn/TLdmIgWMFS

Categorias:JSF

JSF 2 – PRIMEFACES – PHOTOCAM COM IMAGECROPPER

O desenvolvimento de novas versões do Primefaces, como seu próprio líder fala, está em chamas. Na última semana timemos a conclusão e lançamento da versão 3 e no mesmo dia o lançamento de novos componentes da versão 3.1.

Neste POST irei demonstrar como utilizar o componente PHOTOCAM para capturar uma imagem da sua webcam e como recortar esta imagem em seguida utilizando o IMAGECROPPER.

No nosso exemplo utilizamos:

  • Mojarra 2.1.3
  • Primefaces 3.1 SNAPSHOT
  • GlassFish 3.1.1

Let’s Rock!

Crie um novo projeto no Netbeans e dentro da pasta source crie um pacote para o managed bean, dentro da pasta web crie uma pasta para as imagens e nela uma outra pasta tmp. Veja a imagem abaixo com a estrutura básica do projeto:

Imagem 1 – Novo Projeto Netbeans

Adicione o jar do primerfaces na versão indicada acima. Na pasta web crie o arquivo index.xhtml e insira nele o código abaixo:

Codificação 1

<!--?xml version='1.0' encoding='UTF-8' ?-->



        Exemplo PhotoCam + ImageCropper











            

                Aguarde...



No arquivo index.xhtml temos o componete imagecropper definido a seguir:

Codificação 2


No atributo value definimos um objeto do tipo org.primefaces.model.CroppedImage que receberá a imagem recortada com o componente, em initialCoords definimos onde o retângulo marcador do recorte deve aparecer quando a imagem for renderizada. Além disso, temos um id para o componete, a definição se ele está ou não renderizado na view e um  outro atributo que merece um pouco mais de destaque.

No atributo image devemos especificar o caminho para a imagem capturada pela webcam, é salientar que neste atributo devemos colocar o caminho absoluto da imagem como por exemplo:

Para conseguir este caminho com precisão, coloque da forma como esta na codificação 2, pegando o caminho do contexto.

No componente photocam devemos definir um widgetVar para ser usado para chamar uma função javascript capture(), em update colocamos os ids do que deve ser atualizado ao capturar a imagem e em listenner o método a ser executado quando a captura for finalizada.

Codificação 3





Abaixo veremos a codificação do PhotoCamController:

Codificação 4

    private CroppedImage imagemRecortada;
    private String foto;
    private String fotoRecortada;
    private String arquivoFoto;
    private String arquivoFotoRecortada;
    private boolean exibeImagemCapturada;
    private ServletContext servletContext;

   /*getters e setters*/
    private String getNumeroRandomico() {
        int i = (int) (Math.random() * 10000);
        return String.valueOf(i);
    }

    private void criaArquivo(String arquivo, byte[] dados) {
        FileImageOutputStream imageOutput;
        try {
            imageOutput = new FileImageOutputStream(new File(arquivo));
            imageOutput.write(dados, 0, dados.length);
            imageOutput.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(PhotoController.class.getName()).log(Level.SEVERE, null, ex);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Caminho não encontrado!", "Erro"));
        } catch (IOException ex) {
            Logger.getLogger(PhotoController.class.getName()).log(Level.SEVERE, null, ex);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro ao criar arquivo!", "Erro"));
        }
    }

    public void recortar() {
        verificaExistenciaArquivo(arquivoFotoRecortada);
        fotoRecortada = "fotoRecortada" + getNumeroRandomico() + ".png";
        arquivoFotoRecortada = servletContext.getRealPath(File.separator + "imagens" + File.separator + "tmp" + File.separator + fotoRecortada);
        criaArquivo(arquivoFotoRecortada, imagemRecortada.getBytes());
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Foto RECORTADA com sucesso!", "Informação"));
    }

    public void oncapture(CaptureEvent captureEvent) {
        verificaExistenciaArquivo(arquivoFoto);
        foto = "foto" + getNumeroRandomico() + ".png";
        arquivoFoto = servletContext.getRealPath(File.separator + "imagens" + File.separator + "tmp" + File.separator + foto);
        criaArquivo(arquivoFoto, captureEvent.getData());
        exibeImagemCapturada = true;
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Foto CAPTURADA com sucesso!", "Informação"));
    }

    private void verificaExistenciaArquivo(String arquivo) {
        if (arquivo != null) {
            File file = new File(arquivo);
            if (file.exists()) {
                file.delete();
            }
        }
    }

    public PhotoController() {
        exibeImagemCapturada = false;
        servletContext = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
    }

O método  recortar() é chamado sempre que recortamos a imagem na view e o oncapture() é acionado pelo componente photocam sempre que a função javascript capture() for chamada. Veja que uso nomes randomicos para as imagens criadas, este é um truque para evitar cache do imagecropper, já que não há esta propriedade neste componente.

Muito simples!

Abaixo o resultado:

Categorias:JSF

JSF 2 – PRIMEFACES – P:GALLERIA – EXEMPLO DE GALERIA DE FOTOS

Olá pessoal,

Um componente muito interessante para exibição de imagens é o galleria do primefaces. Irei explicar neste post como podemos usar este componente para exibir as imagens enviadas ao servidor e armazenadas no banco de dados.

Para nosso exemplo utilizarei:

Netbeans 7.0.1
Primefaces 3.0M3
Commons-io 2.0.1
Commons-fileupload 1.2.2

Além disso iremos usar a seguinte base de dados:

Iremos armazenar eventos e as fotos dos eventos. Salvaremos o nome do evento e sua data e ainda a imagem, uma descrição, a ordem que ela aparecerá e o evento ao qual esta imagem pertence.

Nosso projeto consistirá de um sistema que cadastraremos o evento e depois poderemos inserir imagens utilizando o fileupload ou visualizar as imagens com o galleria.

Veja a estrutura do projeto no netbeans, inclusive com as libs usadas:



Criamos uma estrutura com pacotes para separar DAO, modelos, fábrica de conexões, os managedbeans, etc. Abaixo irei colocar o código e explicar cada classe. No noss projeto irei utilizar o componente p:fileupload para enviar e gravar e capturar as imagens para que sejam salvas no banco de dados. Como ja vimos em dois posts como configurar este componente, irei falar dele com menos detalhes, afinal, a ênfase deve ser dada ao uso do galleria.

Classe Evento.java

public class Evento {

    private Long id;
    private String nome;
    private Date data;
    private List<Foto> fotos = new ArrayList<Foto>();

    public Date getData() {
        return data;
    }

    public void setData(Date data) {
        this.data = data;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

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

    public List<Foto> getFotos() {
        return fotos;
    }

    public void setFotos(List<Foto> fotos) {
        this.fotos = fotos;
    }
}

Classe Foto.java


public class Foto {

    private Long id;
    private byte[] imagem;
    private int ordem;
    private String descricao;
    private Evento evento = new Evento();

    public Evento getEvento() {
        return evento;
    }

    public void setEvento(Evento evento) {
        this.evento = evento;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public byte[] getImagem() {
        return imagem;
    }

    public void setImagem(byte[] imagem) {
        this.imagem = imagem;
    }

    public int getOrdem() {
        return ordem;
    }

    public void setOrdem(int ordem) {
        this.ordem = ordem;
    }

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
}

As duas classes acima representam as tabelas Eventos e Fotos respectivamente. Primeiramente iremos abordar a cricação da estrutura para cadastrarmos os eventos, enviarmos e armazenarmos as fotos no banco.

No envio das fotos utilizaremos o componente fileupload, como nosso foco é o componente galleria não irei dar muitos detalhes da configuração do fileupload, para isso visite nosso outro post https://benignosales.wordpress.com/2011/03/17/jsf-2-0-primefaces-2-2-fileupload-com-imagecropper/ . Nele você encontrará todas as informações necessárias para configurar o componente de envio de arquivos.

Com o fileupload configurado, iremos criar nosso managed bean @SessionScoped, ele deve ser deste tipo para funcionar com o componente de envio de arquivos. Abaixo vamos conferir o código do gerenciador, para uma melhor visualização suprimi os getters e setters das variáveis.


@ManagedBean
@SessionScoped
public class GaleriaBean {

    private List<Evento> eventos = new ArrayList<Evento>();
    private Evento evento = new Evento();
    private Evento eventoSelecionado = new Evento();
    private EventoDAO eventoDAO = new EventoDAO();
    private FotoDAO fotoDAO = new FotoDAO();
    private Foto foto = new Foto();
    private StreamedContent imagem = new DefaultStreamedContent();
    private List<Foto> fotos = new ArrayList<Foto>();

    /* getters e setters */

    public void setFoto(Foto foto) {
        this.foto = foto;
    }

    public void salvaEvento() {
        try {
            eventoDAO.salva(evento);
            evento = new Evento();
            eventos = eventoDAO.listaTodos();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Evento adicionado", "Evento adicionado"));
        } catch (SQLException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void salvaFotos() {
        try {
            fotoDAO.salva(foto);
            foto = new Foto();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Foto adicionada", "Foto adicionada"));
        } catch (SQLException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void enviaImagem(FileUploadEvent event) {
        try {
            imagem = new DefaultStreamedContent(event.getFile().getInputstream());
            foto.setEvento(eventoSelecionado);
            foto.setImagem(event.getFile().getContents());
        } catch (IOException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void criaArquivo(byte[] bytes, String arquivo) {
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(arquivo);
            fos.write(bytes);
            fos.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void listaFotosEvento() {
        try {
            fotos = fotoDAO.buscaPorEvento(eventoSelecionado);
            for (Foto f : fotos) {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                ServletContext scontext = (ServletContext) facesContext.getExternalContext().getContext();
                String nomeArquivo = f.getId().toString() + ".jpg";
                String arquivo = scontext.getRealPath("/temp/" + nomeArquivo);
                criaArquivo(f.getImagem(), arquivo);
            }
        } catch (SQLException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public GaleriaBean() {
        try {
            eventos = eventoDAO.listaTodos();
        } catch (SQLException ex) {
            Logger.getLogger(GaleriaBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Temos uma coleção do tipo Evento na qual iremos jogar todos os eventos cadastrados no banco para exibirmos em um datatable, dois objetos do tipo Evento um para o cadastro e outro para a visualização e envio de imagens, um objeto Foto e uma coleção Foto, bem como um objeto StreamedContent que serve para aualizarmos dinamicamente um p:graphicimage e temos os DAOs.

Outro ponto, não iremos colocar o código dos DAOs, pois você pode trabalhar com o que quiser para a camada de persistencia, no meu caso, usei jdbc puro sem nenhuma framework ORM. Caso alguem queira os DAOs basta postar um comentário que envio.

Nos métodos temos o salvaEvento para persistirmos os eventos no banco e temos o salvaFotos para guardarmos as imagens no banco de dados. Além disso, o enviaImagem que é o listener do componente fileupload, ou seja, sempre que enviarmos um arquivo o sistema chama este método para “tratarmos” o arquivos como quisermos. Aqui, preenchemos o objeto StreamedContent imagem para exibir a imagem enviada na tela e setamos o objeto foto para que possamos salvá-lo depois. Mais abaixo, temos o método criaArquivo que serve para criar o arquivo físico a partir de um array de bytes e um caminho específico e o método listaFotosEvento, com o qual criamos os arquivos a serem exibidos na galeria. O grande lance é justamente esse, os arquivos devem ser criados dinamicamente e jogados dentro de uma pasta para serem exibidos na tela, pois o graphicImage não suporta conteudos dinamicos em listas, como um datatable ou mesmo no galleria.

Com isso, passamos para a nossa view. Veja o código abaixo:

Obs.: Crie uma pasta dentro da pasta web para armazenar temporariamente as imagens. No nossa caso, criei a pasta temp.

    <h:head>
        <title>Exemplo Galleria - Benigno Sales</title>
    </h:head>
    <h:body style="background-color: #CCCCCC">
        <h:form prependId="false" enctype="multipart/form-data">
            <p:panel id="dadosEvento" header="Exemplo Galeria" style="width: 600px;">
                <p:growl/>
                <h:panelGrid columns="2">
                    <h:outputText value="Nome"/>
                    <p:inputText value="#{galeriaBean.evento.nome}" size="40"/>
                    <h:outputText value="Data"/>
                    <p:calendar value="#{galeriaBean.evento.data}"
                                timeZone="GMT-3"
                                navigator="true"
                                pattern="dd/MM/yyyy"
                                locale="pt_BR"/>
                    <p:commandButton value="Salvar" action="#{galeriaBean.salvaEvento()}" update="tabelaEventos dadosEvento"/>
                    <p:commandButton value="Limpar" onclick="form.reset()"/>
                    <p:ajaxStatus>
                        <f:facet name="start">
                            <h:outputText value="aguarde..."/>
                        </f:facet>
                        <f:facet name="complete">
                            <h:outputText value=""/>
                        </f:facet>
                    </p:ajaxStatus>
                </h:panelGrid>
            </p:panel>
            <p:dialog id="dialogFotos" position="top" widgetVar="dialogFotos" modal="true" minWidth="600" minHeight="500">
                <p:fileUpload fileUploadListener="#{galeriaBean.enviaImagem}"
                              update="imagemTmp"
                              cancelLabel="Cancelar"
                              fileLimit="100000"
                              fileLimitMessage="Imagem muito grande"
                              label="Selecionar"
                              invalidFileMessage="Tipo de imagem inválido"
                              invalidSizeMessage="Imagem muito grande"
                              uploadLabel="Enviar"
                              allowTypes="/(\.|\/)(jpe?g|png)$/">

                </p:fileUpload>
                <p:outputPanel id="dadosFoto">
                    <h:panelGrid>
                        <p:graphicImage cache="false" id="imagemTmp" value="#{galeriaBean.imagem}" height="300" style="margin: 0 auto;"/>
                        <h:outputText value="Descrição"/>
                        <p:inputText value="#{galeriaBean.foto.descricao}" size="49"/>
                        <h:outputText value="Ordem"/>
                        <p:inputMask mask="9" value="#{galeriaBean.foto.ordem}" size="5"/>
                    </h:panelGrid>
                </p:outputPanel>
                <p:commandButton value="Adicionar" action="#{galeriaBean.salvaFotos()}" update="dadosFoto dadosEvento"/>
            </p:dialog>
            <p:dialog id="dialogGaleria" widgetVar="dialogGaleria" modal="true" position="top"
                      minWidth="440" minHeight="500">
                <h:outputText value="Nenhuma imagem encontrada" rendered="#{galeriaBean.fotos.size()==0}"/>
                <p:galleria value="#{galeriaBean.fotos}"
                            var="galeria" effect="slide" effectSpeed="2000"
                            panelHeight="300" panelWidth="400"
                            frameHeight="50" frameWidth="50"
                            filmstripPosition="bottom" showOverlays="true">
                    <p:graphicImage value="/temp/#{galeria.id}.jpg" cache="false" width="400" height="300"
                                    title="#{galeria.descricao}" alt="#{galeria.descricao}"/>

                    <p:galleriaOverlay title="#{galeria.descricao}">
                    </p:galleriaOverlay>
                </p:galleria>
            </p:dialog>
            <p:dataTable id="tabelaEventos"
                         value="#{galeriaBean.eventos}" var="evento" style="width: 610px;"
                         emptyMessage="Nenhum evento cadastrado"
                         rows="6"
                         paginator="true"
                         paginatorPosition="bottom"
                         paginatorAlwaysVisible="false">
                <p:column headerText="Id">
                    <h:outputText value="#{evento.id}"/>
                </p:column>
                <p:column headerText="Evento">
                    <h:outputText value="#{evento.nome}"/>
                </p:column>
                <p:column headerText="Data">
                    <h:outputText value="#{evento.data}">
                        <f:convertDateTime pattern="dd/MM/yyyy"/>
                    </h:outputText>
                </p:column>
                <p:column>
                    <p:commandButton image="ui-icon-plus" title="Adicionar Imagem" oncomplete="dialogFotos.show();" update="dadosFoto">
                        <f:setPropertyActionListener target="#{galeriaBean.eventoSelecionado}" value="#{evento}"/>
                    </p:commandButton>
                    <p:commandButton image="ui-icon-search" title="Ver Imagens" action="#{galeriaBean.listaFotosEvento()}" update="dialogGaleria" oncomplete="dialogGaleria.show()">
                        <f:setPropertyActionListener target="#{galeriaBean.eventoSelecionado}" value="#{evento}"/>
                    </p:commandButton>
                </p:column>
            </p:dataTable>
        </h:form>
    </h:body>
</html>

É uma tela simples, mas que da um grande resultado. Uma área para o cadastro dos eventos e um dataTable para listar estes eventos. Em uma coluna do dataTable colocamos dois botões, um para exibirmos as imagens(fotos) e outro para enviarmos as fotos.

O Componente Galleria tem alguns atributos que gostaria de destacar, são eles:

 value  null  String  Coleção que possui os dados das imagens
 var  null  String  Variavel  que vai interagir com a coleção
 panelHeight/panelWidth  –  Integer  Largura e altura do painel
 frameHeight/frameWidth  –  Integer  Largura e altura das miniaturas

style

null

String

 Estilo

styleClass

null

String

 Classe de estilo

effect

fade

String

 Nome da animação

filmstripPosition  top  String  Posição das miniaturas
showOverlays  true  boolean  Exibição das legendas

Abaixo eu criei um vídeo com o projeto em execução:

Ah! O vídeo foi feito com testes no primefaces 2.2.1, nesta versão a galeria era meio feinha. Abaixo vou postar como ficou com a versão 3M3 do prime.

Bom, é isso pessoal. Dúvidas? postem aqui! Abraço a todos e compartilhem suas idéias.

Gráficos com JSF 2 e Primefaces – Linhas

Dando continuidade a nossa série de posts sobre gráficos, mostrarei agora como criar um gráfico de linhas. Nosso exemplo mostrarei a evolução de três times durante cinco rodadas do brasileirão.

Basicamente a diferença entre o gráfico de torta e o de linhas é que no de torta analisamos a representação dos dados de um objeto com relação ao todo e no de linhas iremos analisar evoluções do objeto durante etapas(períodos).

No exemplo utilizamos:

– Netbeans 7.0.1
– Primeface 3.0 M3
– Jsf 2.1

Abaixo uma breve explicação sobre os principais atribudos do componente lineChar:

 Nome

Valor Padão

Tipo

Descrição

id

null

String

Identificador único

rendered

TRUE

Boolean

Indica que o componente deve ou não ser renderizado na tela

binding

null

Object

Uma expression language que faz o mapeamento do componente com um objeto UICOmponente localizado no backingbean.

value

null

Collection

É o modelo do gráfico

legendPosition

null

Object

Campo que indica a posição da legenda. Coloque as siglas dos pontos cardeais em inglês. Ex.: w, ne, n, etc.

style

null

String

Define o estilo do painel do gráfico, tamanho, tamanho de fonte, etc.

seriesStyle

null

String

Cores dos items. Coloque as cores em formato RGB sem o #.

minY/minX

null

Double

Menor valor para a dimensão Y/X.

maxY/maxX

null

Double

Maior valor para a dimensão Y/X.

yaxisLabel

null

String

Rótulo dos dados da dimensão Y

xaxisLabel

null

String

Rótulo dos dados da simensão X

No nosso projeto iremos utilizar apenas beans(modelos) e managedbeans, isso para facilitar o entendimento. Abaixo, como ficou a organização do projeto:

Observe que criamos 3 modelos, um para a Equipe(Time), outro para Rodada e mais um representando o relacionamento entre as duas. Como nosso objetivo é explicar o componente, não coloquei muitos atributos nos modelos, apenas o necessário para conseguir a compreensão. vejam abaixo os modelos:

Rodada.java

public class Rodada {

    private String numero;

    public Rodada(String numero) {
        this.numero = numero;
    }

    public String getNumero() {
        return numero;
    }

    public void setNumero(String numero) {
        this.numero = numero;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Rodada other = (Rodada) obj;
        if ((this.numero == null) ? (other.numero != null) : !this.numero.equals(other.numero)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 11 * hash + (this.numero != null ? this.numero.hashCode() : 0);
        return hash;
    }
}

Time.java

public class Time {

    private String nome;

    public Time(String nome) {
        this.nome = nome;
    }

    public String getNome() {
        return nome;
    }

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

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Time other = (Time) obj;
        if ((this.nome == null) ? (other.nome != null) : !this.nome.equals(other.nome)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 59 * hash + (this.nome != null ? this.nome.hashCode() : 0);
        return hash;
    }
}

TimeRodada.java

public class TimeRodada {

    private Time time;
    private Rodada rodada;
    private int pontos;

    public int getPontos() {
        return pontos;
    }

    public void setPontos(int pontos) {
        this.pontos = pontos;
    }

    public Rodada getRodada() {
        return rodada;
    }

    public void setRodada(Rodada rodada) {
        this.rodada = rodada;
    }

    public Time getTime() {
        return time;
    }

    public void setTime(Time time) {
        this.time = time;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final TimeRodada other = (TimeRodada) obj;
        if (this.time != other.time && (this.time == null || !this.time.equals(other.time))) {
            return false;
        }
        if (this.rodada != other.rodada && (this.rodada == null || !this.rodada.equals(other.rodada))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 31 * hash + (this.time != null ? this.time.hashCode() : 0);
        hash = 31 * hash + (this.rodada != null ? this.rodada.hashCode() : 0);
        return hash;
    }
}

Abaixo iremos explicar o managed bean GraficoLinhaBean.java

@ManagedBean
@ViewScoped
public class GraficoLinhaBean {

    private List timesRodadas = new ArrayList();
    private List<time> times = new ArrayList<time>();
 private List rodadas = new ArrayList();
 private CartesianChartModel rodadasBrasileirao = new CartesianChartModel();

 public GraficoLinhaBean() {
 criarDados();
 criarModelo();
 }

 public CartesianChartModel getRodadasBrasileirao() {
 return rodadasBrasileirao;
 }

 public void setRodadasBrasileirao(CartesianChartModel rodadasBrasileirao) {
 this.rodadasBrasileirao = rodadasBrasileirao;
 }

 public List getRodadas() {
 return rodadas;
 }

 public void setRodadas(List rodadas) {
 this.rodadas = rodadas;
 }

 public List<time> getTimes() {
 return times;
 }

 public void setTimes(List<time> times) {
 this.times = times;
 }

 public List getTimesRodadas() {
 return timesRodadas;
 }

 public void setTimesRodadas(List timesRodadas) {
 this.timesRodadas = timesRodadas;
 }

 private void criarDados() {
 Rodada r = new Rodada("1");
 rodadas.add(r);
 Rodada r2 = new Rodada("2");
 rodadas.add(r2);
 Rodada r3 = new Rodada("3");
 rodadas.add(r3);
 Rodada r4 = new Rodada("4");
 rodadas.add(r4);
 Rodada r5 = new Rodada("5");
 rodadas.add(r5);
 Time t = new Time("Corinthians");
 times.add(t);
 Time t2 = new Time("São Paulo");
 times.add(t2);
 Time t3 = new Time("Flamengo");
 times.add(t3);
 //Rodada 1
 TimeRodada tr = new TimeRodada();
 tr.setTime(t);
 tr.setRodada(r);
 tr.setPontos(3);
 timesRodadas.add(tr);
 TimeRodada tr2 = new TimeRodada();
 tr2.setTime(t2);
 tr2.setRodada(r);
 tr2.setPontos(1);
 timesRodadas.add(tr2);
 TimeRodada tr3 = new TimeRodada();
 tr3.setTime(t3);
 tr3.setRodada(r);
 tr3.setPontos(1);
 timesRodadas.add(tr3);
 //Rodada 2
 TimeRodada tr4 = new TimeRodada();
 tr4.setTime(t);
 tr4.setRodada(r2);
 tr4.setPontos(6);
 timesRodadas.add(tr4);
 TimeRodada tr5 = new TimeRodada();
 tr5.setTime(t2);
 tr5.setRodada(r2);
 tr5.setPontos(2);
 timesRodadas.add(tr5);
 TimeRodada tr6 = new TimeRodada();
 tr6.setTime(t3);
 tr6.setRodada(r2);
 tr6.setPontos(4);
 timesRodadas.add(tr6);
 //Rodada 3
 TimeRodada tr7 = new TimeRodada();
 tr7.setTime(t);
 tr7.setRodada(r3);
 tr7.setPontos(9);
 timesRodadas.add(tr7);
 TimeRodada tr8 = new TimeRodada();
 tr8.setTime(t2);
 tr8.setRodada(r3);
 tr8.setPontos(5);
 timesRodadas.add(tr8);
 TimeRodada tr9 = new TimeRodada();
 tr9.setTime(t3);
 tr9.setRodada(r3);
 tr9.setPontos(5);
 timesRodadas.add(tr9);
 //Rodada 4
 TimeRodada tr10 = new TimeRodada();
 tr10.setTime(t);
 tr10.setRodada(r4);
 tr10.setPontos(12);
 timesRodadas.add(tr10);
 TimeRodada tr11 = new TimeRodada();
 tr11.setTime(t2);
 tr11.setRodada(r4);
 tr11.setPontos(6);
 timesRodadas.add(tr11);
 TimeRodada tr12 = new TimeRodada();
 tr12.setTime(t3);
 tr12.setRodada(r4);
 tr12.setPontos(8);
 timesRodadas.add(tr12);
 //Rodada 5
 TimeRodada tr13 = new TimeRodada();
 tr13.setTime(t);
 tr13.setRodada(r5);
 tr13.setPontos(15);
 timesRodadas.add(tr13);
 TimeRodada tr14 = new TimeRodada();
 tr14.setTime(t2);
 tr14.setRodada(r5);
 tr14.setPontos(6);
 timesRodadas.add(tr14);
 TimeRodada tr15 = new TimeRodada();
 tr15.setTime(t3);
 tr15.setRodada(r5);
 tr15.setPontos(9);
 timesRodadas.add(tr15);
 }

 private void criarModelo() {
 rodadasBrasileirao = new CartesianChartModel();
 for (Time time : times) {
 ChartSeries cs = new ChartSeries();
 for (Rodada rodada : rodadas) {
 TimeRodada tr = new TimeRodada();
 tr.setRodada(rodada);
 tr.setTime(time);
 for (TimeRodada timeRodada : timesRodadas) {
 if (timeRodada.equals(tr)) {
 cs.setLabel(timeRodada.getTime().getNome());
 cs.set(timeRodada.getRodada().getNumero(), timeRodada.getPontos());
 }
 }
 }
 rodadasBrasileirao.addSeries(cs);
 }
 }
}

Vejamos que no construtor eu chamo o metodo criarDados que cria as rodadas e os times, alem de preencher preencher o relacionamento com os pontos de cada time em cada rodada.

No bean temos um objeto da classe CartesianChartModel, este objeto ira espelhar o componente lineChart no managedBean, ou seja, da forma como montarmos este objeto, ser exibida na view.

Com a classe CartesianChartModel trabalharemos com ChartSeries, para criar as linhas do grafico. Cada linha devera ser um novo objeto que atraves do metodo setLabel definimos o nome que aquela linha representara e atraves do set inserimos os dados da dimensao X e Y nesta sequencia.
Em criarModelo eu percorri todos os Times criando uma linha para representar cada um, depois preenchi os dados dos pontos em cada rodada formando o grafico da evolucao dos time, confira no final do post.

Abaixo voces podem conferir a view index.xhtml:

        Exemplo de Gráficos com Primefaces - Linha

Em value definimos o objeto do bean que representará o gráfico, a posição da legenda, o valor minimo de X e Y e os rotulos de X e Y, um titulo e o estilo(tamanho, margem, etc).

Ah! Tentem clicar sobre o nome de um dos time para ver o resultado,  bem interessante. Bem, e isso! Abraco e espero que gostem do resultado.

Gráficos com JSF 2 e Primefaces – Torta

Olá pessoal, tudo bem?

Espero que me perdoem a demora em postar novo material, mas estou com alguns projetos em adamento e ando um pouco sem tempo.

Neste novo post daremos início a uma série onde mostrarei como criar alguns tipos de gráficos com Primefaces. Como pontapé inicial veremos a criação de um gráfico de torta onde mostraremos a probabilidade de título do Camp. Brasileiro.

Utilizaremos em nosso projeto exemplo:

– Netbeans 7.0.1
– Primefaces 3.0M3

Obs.: Com primefaces, não há a necessidade de adicionar nenhuma lib para a criação de gráficos, a não ser, que você deseje interagir com o JFreeChart.

Para começar crie um projeto, no nosso caso ExGraficoTorta. Neste projeto construa uma estrutura de pacotes conforme exibido abaixo:

Criamos uma classe Time, outra TimeDAO e um managedbean GraficoBean. Todas estas classes serão detalhadas mais abaixo:

Veja a classe Time.java


public class Time {

    private long id;
    private String nomeTime;
    private double probabilidade;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getNomeTime() {
        return nomeTime;
    }

    public void setNomeTime(String nomeTime) {
        this.nomeTime = nomeTime;
    }

    public double getProbabilidade() {
        return probabilidade;
    }

    public void setProbabilidade(double probabilidade) {
        this.probabilidade = probabilidade;
    }
}

Utilizaremos este modelo para, através do DAO, buscar os dados que desejamos exibir no gráfico de torta. Vamos agora ver como ficará o managedbean utilizado para gerenciar a página. Abaixo confira o código:

@ManagedBean
public class GraficoBean implements Serializable {

    private PieChartModel modelo;

    public GraficoBean() {
        criarModeloGrafico();
    }

    public PieChartModel getModelo() {
        return modelo;
    }

    public void setModelo(PieChartModel modelo) {
        this.modelo = modelo;
    }

    private void criarModeloGrafico() {
        modelo = new PieChartModel();
        List<time> listaTime = new ArrayList<time>();
 TimeDAO timeDAo = new TimeDAO();
 listaTime = timeDAo.listaTodos();
 for (Time time : listaTime) {
 modelo.set(time.getNomeTime(), time.getProbabilidade());
 }
 }
}

Declaramos um objeto do tipo PieChartModel para espelhar o modelod o gráfico de torta que usaremos na nossa página. Como este é um exemplo simples e prático, decidi simplesmente criar um método para preencher o modelo e chamá-lo no construtor. Provavelmente, em suas apps, você deverá invocar o método através de uma action de um botão, menuitem, etc.

Confira abaixo um pouco sobre os principais atributos da tag pieChart

 Nome

Valor Padão

Tipo

Descrição

id

null

String

Identificador único

rendered

TRUE

Boolean

Indica que o componente deve ou não ser renderizado na tela

binding

null

Object

Uma expression language que faz o mapeamento do componente com um objeto UICOmponente localizado no backingbean.

value

null

Collection

É o modelo do gráfico

diameter

null

Integer

Tamanho do diâmetro da torta.

legendPosition

null

Object

Campo que indica a posição da legenda. Coloque as siglas dos pontos cardeais em inglês. Ex.: w, ne, n, etc.

style

null

String

Define o estilo do painel do gráfico, tamanho, tamanho de fonte, etc.

seriesStyle

null

String

Cores dos items. Coloque as cores em formato RGB sem o #.

Não explicarei todos os atributos, até porque você não os utilizará, mas em caso de dúvida post um comentário. Segue o código da nossa página que exibirá o gráfico:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:p="http://primefaces.prime.com.tr/ui"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Gráficos com JSF 2.0</title>
    </h:head>
    <h:body>
        <p:pieChart value="#{graficoBean.modelo}"
                    legendPosition="w"
                    title="Probabilidade de Título - Brasileirão 2011"
                    style="width:800px;height:600px;"/>
    </h:body>
</html>

Veja na imagem abaixo como ficou:
Gráfico de Torta

É isso ai, bem simples, qualquer dúvida coloca um comentário. Valeu!

Novo Dialog – Primefaces 3.0 M3

Ae pessoal, acabei de ver no blog do líder do projeto Prime Faces,  Cagatay Civici, uma grande novidade que me chamou bastante a atenção. Na versão M3 do primefaces 3, teremos algumas novas funcionalidades do componente dialog.

Nas versões anteriores a dialog era baseada no JQuery, com impossibilidade de atualização com Ajax, além de ter um tamanho padrão fixo em 300px. Nesta nova versão todas as funcionalidades antigas foram mantidas e incluiram as que veremos abaixo:

– Possibilidade de minimizar a dialog(Minimizable);

– Possibilidade de maximizar a dialog(Maximizable);

– Inclusão de conteúdo dinâmico(Lazy Content);

– Utilização do footer e header com Facet, para uma maior flexibilidade ao criar cabeçalho  e rodapé;

– Tamanho automático, onde a janela se adequa ao tamanho do conteúdo(Auto width);

– Podemos atualizar a dialog utilizando AJAX através de seu id;

A versão M3 deve estar disponível para download no fim de agosto.

 

abraços,

 

Benigno.

 

Resolvendo problema com ACENTUAÇÃO no nome do ARQUIVO com FILEUPLOAD do PRIMEFACES

Nesta última semana tive uns probleminhas com o FileUpload ao pegar o nome do arquivo que estava realizando um upload, os nome dos arquivos que possuiam acentuação sempre vinham com estes caracteres trocados por caracteres especiais. O cliente não ficou satisfeito, pois se eu fizesse o upload de uma arquivo DECLARAÇÃO_IMPOSTO_RENDA_20011.PDF vinha algo assim DECLARA≤Â÷ÆO_IMPOSTO_RENDA_2011.PDF.

Após várias tentativas consegui uma resolução para o problema de forma fácil e elegante. Para resolver, basta criarmos um filtro para setar o tipo de codificação do texto contido na resposta e na requisição.

Vamos por a mão na massa! Crie um pacore filters no seu projeto e dentro dele crie uma classe CharacterEncodingFilter.java. Abaixo o exemplo do código desta classe:

public class CharacterEncodingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}

Bem simple, apenas setamos a codificação na resposta e na requisição. Além disso precisamos declarar este filtro no web.xml:

    <filter>
        <filter-name>Character Encoding Filter</filter-name>
        <filter-class>br.com.tecnodocs.vdocs.filters.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Character Encoding Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>

Com isso você conseguirá pegar os nomes dos arquivos através do p:fileUpload em qualquer SO sem problemas de acentuação.

Espero que a dica ajude outros da mesma forma que me ajudou, abraço!

Benigno M. Sales

“Ame seus inimigos, faça o bem para aqueles que te odeiam, abençoe aqueles que te amaldiçoam, reze por aqueles que te maltratam. Se alguém te bater no rosto, ofereça a outra face. “
( Jesus Cristo )

JSF 2.0 – Primefaces 2.2 – FileUpload com ImageCropper

 

FileUpload

O componente FileUpload, como o prórprio nome diz, é responsável pelo envio de imagens da máquina cliente para o lado servidor. Este componente vai além da navegação da tag html <input type=”file”>, trazendo funcionalidades flashjavascript. Podemos filtrar arquivos, fazer múltiplos uploads, processamento parcial da página e uma barra para acompanhamento do progresso do upload. Caso o navegador cliente não suporte flash ou javascrip o fileupload retorna a funcionalidade padrão de <input type=”file”>.

Em um post anterior, já descrevi como utilizar FileUpload, porém, da versão utilizada no post até a atual tivemos algumas modificações na forma de configuração, o que me leva a descrever alguns procedimentos novamente.

Bibliotecas necessárias:

Configuração do web.xml:

<filter>
   <filter-name>PrimeFaces FileUpload Filter</filter-name>
   <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>

<filter-mapping>
   <filter-name>PrimeFaces FileUpload Filter</filter-name>
   <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

Abaixo descrição dos principais atributos do componente:

  • id:  Identificador único do componente
  • rendered: Valor boleano para especificar se o componente deve ou não ser exibido
  • fileUploadListener:  Método a ser executado quando sempre que um arquivo for ser enviado
  • multiple:  Habilita o envio de múltiplos arquivos
  • update: id de um componente a ser atualizado após o término do envio do arquivo
  • auto: Quando habilitado(true) o upload do arquivo começa logo após a seleção
  • label: Rótulo do botão, o padrão é ‘Browse’
  • image: Imagem de fundo do botão
  • cancelImage: Imagem do botão cancelar
  • width: Largura do botão de procura
  • height: Altura do botão de procura
  • allowTypes: Lista de extensões de arquivos aceitas
  • description: Rótulo que descreve quais tipos de arquivo podem ser enviados
  • sizeLimit: Número máximo de bytes aceitos
  • wmode: Propriedade wmode do objeto flash
  • customUI: Quando habilitado(true) os links upload e cancel  não são exibidos
  • widgetVar: Nome do widget para referências em javascript

ImageCropper

O componente ImageCropper  tem como funcionalidade recortar determinadas regiões de uma imagem. Esta funcionalidade criauma nova imagem contendo a região recordada e associando-a a um objeto do tipo CroppedImage instanciado no lado servidor.

Abaixo descrição dos principais atributos do componente:

  • id:  Identificador único do componente
  • rendered: Valor boleano para especificar se o componente deve ou não ser exibido
  • required: Indica se o campo é obrigatório
  • value:  EL para um Objeto do tipo CroppedImage instanciado no managed bean.
  • image:  Caminho para a imagem(context path)
  • initialCoords:  Coordenadas da posição inicial da região de corte

Criação de Aplicação integrando FileUpload e ImageCropper

Para criação desta aplicação iremos criar uma view(index.xhtml), uma pasta imagens onde armazenaremos as imagens utilizadas no sistema e uma pasta upload para colocar as imagens enviadas através do file upload. A estrutura do projeto ficará conforme imagem abaixo:

Para este projeto simples devemos criar um bean gerenciado de escopo de sessão para controlar a nossa view, abaixo confira o código.
Obs.: Desconsideramos os getters e setters.

IndexManagedBean.java

@ManagedBean
@SessionScoped
public class IndexManagedBean {

private StreamedContent imagemEnviada = new DefaultStreamedContent();
private String imagemTemporaria;
private CroppedImage croppedImage;
private boolean exibeBotao = false;

/* getters e setters */

   public void criaArquivo(byte[] bytes, String arquivo) {
      FileOutputStream fos;
      try {
         fos = new FileOutputStream(arquivo);
         fos.write(bytes);
         fos.close();
      } catch (FileNotFoundException ex) {
         Logger.getLogger(IndexManagedBean.class.getName()).log(Level.SEVERE, null, ex);
      } catch (IOException ex) {
         Logger.getLogger(IndexManagedBean.class.getName()).log(Level.SEVERE, null, ex);
      }
   }

   public void enviarImagem(FileUploadEvent event) {
      byte[] img = event.getFile().getContents();
      imagemTemporaria = event.getFile().getFileName();
      FacesContext facesContext = FacesContext.getCurrentInstance();
      ServletContext scontext = (ServletContext) facesContext.getExternalContext().getContext();
      String arquivo = scontext.getRealPath("/upload/" + imagemTemporaria);
      criaArquivo(img, arquivo);
      setExibeBotao(true);
   }

   public void crop() {
      setImagemEnviada(new DefaultStreamedContent(new ByteArrayInputStream(croppedImage.getBytes())));
   }
}

O método enviarImagem(FileUploadEvent event) é utilizado no atributo fileUploadListener para ser executado sempre que uma imagem estiver sendo enviada. É neste método onde poderemos fazer conversões, criação de arquivos, etc.

Observem que no método é passado um parâmetro event com o qual eu consigo retirar todos os dados que preciso, como nome de arquivo, caminho, array de bytes referentes ao arquivo, etc. Iremos criar um arquivo temporário que será utilizado na view com o imageCropper, este arquivo é criado na pasta upload através do método criaArquivo, e também salvar o nome do arquivo criado em uma String, a imagemTemporaria.

Em seguida criamos o método crop() para coletar a imagem recortada e jogar dentro da imagemEnviada que é do tipo StreamedContent, que pode ser trabalhado dinamicamente com o um p:graphicImage. Abaixo confira a utilização de todos os métodos e atributos na view:

<h:form>
   <p:panel header="ImageCropper com FileUpload - QuebrandoParadigmas.com" style="width: 900px; margin: 0 auto; margin-top: 0px">
      <p:fileUpload fileUploadListener="#{indexManagedBean.enviarImagem}" sizeLimit="204800" auto="true"
                            image="/imagens/imgBuscar.png" customUI="true" update="outputPanelUpload"/>
      <p:outputPanel id="outputPanelUpload">
         <h:panelGrid columns="2">
            <h:outputText value="Imagem" rendered="#{indexManagedBean.exibeBotao}"/>
             <h:outputText value="Pre-visualização" rendered="#{indexManagedBean.exibeBotao}"/>
             <p:imageCropper id="imageCropperImagemTemporaria" value="#{indexManagedBean.croppedImage}"
              image="#{pageContext.servletContext.contextPath}/upload/#{indexManagedBean.imagemTemporaria}"/>
              <p:graphicImage value="#{indexManagedBean.imagemEnviada}" cache="false"/>
         </h:panelGrid>
         <p:commandLink action="#{indexManagedBean.crop}" update="outputPanelUpload"
                                   rendered="#{indexManagedBean.exibeBotao}">
            <p:graphicImage style="margin-top: 5px; border: none;" value="/imagens/imgCortar.png"/>
         </p:commandLink>
      </p:outputPanel>
   </p:panel>
</h:form>

Criamos um outputPanel de nome outputPanelUpload que é  atualizado sempre que algum dado no managed bean é alterado, como quando a imagem de upload é enviada e damos um update para exibi-la ou quando cortamos a imagem e atualizamos para exibir a região cortada em uma outra imagem. Gostaria de salientar o código abaixo, pois é nele onde carregamos  a imagem que foi criada no na pasta upload do servidor:
image=”#{pageContext.servletContext.contextPath}/upload/#{indexManagedBean.imagemTemporaria}”

Perceba que pego o caminho do contexto(pasta web) e dentro dele a pasta upload e, em seguida, acrescento com uma EL que representa o nome do arquivo que foi definido no fileUploadListener(enviaImagem).

O resultado você pode conferir no vídeo abaixo:





Twitter: @benignoms

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.

Internacionalização com JSF

Vamos supor o seguinte, se tivermos uma excelente aplicação que resolve todos os problemas de determinada empresa e esta abrir uma filial em outro país, seria necessário uma refatoração das páginas para modificar todos os rótulos dos botões, labels e mensagens?

Neste post veremos que há uma certa “facilidade” com java e JSF de se programar com internacionalização de forma rápida e dinâmica, para suas aplicações possam ser usadas e compreendidas em várias linguas sem a necessidade de um gigantesco retrabalho.

Para nosso exemplo utilizei:

– Mojarra 2.0.3
– Primefaces 2.2 RC2

Crie um pacote onde colocaremos os nossos arquivos .properties. Eu chamei o meu pacote de messages, mas fique a vontade para colocar o nome que quiser. Veja na imagem:

Observe que criei dois arquivos iguais onde mudo somente um sufixo pt ou en de acordo com a língua que nos interessar. O conteúdo destes arquivos serão os rótulos do botões e textos dos labels dos campos.

Veja abaixo como ficarão cada um dos arquivos:

rotulos_pt.properties

rotulos_en.properties

Para uma configuração mais fácil dos arquivos, após cria-los clique com o botão direito em um deles e depois clique em abrir. Veja abaixo a tela de configuração:

Após a digitação dos rótulos você deverá realizar uma configuração no arquivo faces-config.xml, veja abaixo a configuração:

 

<application>
<resource-bundle>
<base-name>messages.rotulos</base-name>
<var>msgs</var>
</resource-bundle>
<locale-config>
<default-locale>pt_BR</default-locale>
<supported-locale>en_US</supported-locale>
</locale-config>
 </application>

Veja em <base-name> colocamos o nome do arquivo sem o sufixo inlcuindo o pacote, em<var> definimos a variável que será usada para referenciarmos o arquivo de internacionalização nas views. Posteriormente configuramos no <locale-config>  as línguas disponiveis utilizando <supported-locale> para cada uma delas e em <default-localte>  definimos a padrão, no nosso caso o português do Brasil.

Com isso estamos aptos a utilizar nossos rótulos em todas as views. Basta usarmos a variável msgs dentro de uma EL seguida do campo que queremos referenciar, veja um exemplo abaixo:

<h:outputText value="#{msgs.campoId}"/>
<h:inputText readonly="true" value="#{cadastroAlunoManagedBean.aluno.id}" size="4"/>
<h:outputText value="#{msgs.campoNome}"/>
 <h:inputText value="#{cadastroAlunoManagedBean.aluno.nome}" size="50" required="true" requiredMessage="#{msgs.msgCampoNomeObrigatorio}"/>

Veja como fica o resultado:

Para verificar se funcionou, no firefox, vá em preferências conteúdo e mude a língua do navegador para en_US

Antes de finalizar, gostaria de comentar um detalhe importante que quase não encontrei em posts que falam sobre internacionalização. Como fazer para chamar uma exceção no managed bean(controller) com internacionalizada?

Bom, a forma mais interessante que encontrei foi através da classe ResourceBundle passando como parâmetros a propriedade e o locale, veja abaixo:


FacesContext fc = FacesContext.getCurrentInstance();
ResourceBundle rb = ResourceBundle.getBundle("messages.rotulos",fc.getViewRoot().getLocale();
String mensagem = rb.getString(valor);

No código acima você define o ResourceBundle passando o locale padrão do navegador e o arquivo com o pacote. Depois passa chamar o método toString passando a propriedade que você quer o valor e receberá o resultado esperado.

É isso ai, abraço a todos!