13 de novembro de 2012

PrimeFaces 3.4.1: GMap

Olá!
Depois de algum tempo, aqui estou eu com mais uma postagem sobre PrimeFaces, desta vez estou usando a versão 3.4.1. Peço desculpas se por acaso eu perdi a didática de escrever aqui, é que faz muito tempo que não escrevo mais.
Mas vamos lá... Hoje a postagem é sobre o GMap, pra quem ainda não sabe o PrimeFaces já tem um componente com a biblioteca GMap, pra usá-la é bem simples.
Primeiramente vamos baixar a biblioteca do Prime, basta clicar aqui.
Para este projeto estarei usando JPA, para quem ainda não sabe como usar: é só ver os primeiros links da página Nível: Intermediário.

Meu projeto ficou com essa estrutura:

Começando... adicione a biblioteca do PrimeFaces às bibliotecas do projeto. E na página index:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true" />
        <title>GMap</title>
    </h:head>
    <h:body>
        <p:gmap center="-15.565986,-54.309782" zoom="15" type="HYBRID" style="width:600px;height:400px" />  
    </h:body>
</html>

Vamos aos pontos importantes do código acima:
Linha 3: lembre-se de adicionar a taglib do prime na página
Linha 5: Ponto importante para o funcionamento do p:gmap, que é a biblioteca do Google para o maps funcionar.
Linha 9: Este código é suficiente para aparecer o mapa, e você já poderá navegar pelo mundo! Mas vamos aos detalhes dessa linha: a propriedade center se refere à latitude e longitude, esta propriedade indica qual será o ponto onde o mapa deverá abrir inicialmente; a propriedade zoom se refere ao zoom do mapa, que pelos meus testes pode ir de 0 até 20 (talvez em alguns lugares possa ir a mais ou menos que isso); a propriedade type trata da forma de visualizar o mapa, que pode ser HYBRID (mapa e satélite), ROADMAP (apenas mapa), TERRAIN (terreno: uma opção que fica abaixo do mapa) ou SATELLITE (visão do satélite, mas vi que ele habilita a opção mapa também, mas se escolher ela, o mapa não aparece, uma solução para usar apenas o satélite seria usar a propriedade mapTypeControl="false").
Resultado:

Capturar Latitude e Longitude

Seguindo ainda a mesma base usado anteriormente, irei usar para este exemplo minha classe LocalBean (vide imagem da estrutura do meu projeto lá em cima), nela faça o seguinte:
@javax.faces.bean.ManagedBean
@javax.faces.bean.ViewScoped
public class LocalBean {
    
    public void pontoSelecionado(PointSelectEvent event) {  
        LatLng latituteLongitude = event.getLatLng();  
          
        FacesContext.getCurrentInstance().addMessage(
            null,
            new FacesMessage(
                FacesMessage.SEVERITY_INFO, 
                "Ponto selecionado", 
                "Lat:" + latituteLongitude.getLat() + ", Long:" + latituteLongitude.getLng()
            )
        );  
    }  
}
Detalhes do código
Linha 5 e 6: as classes PointSelectEvent e LatLng devem ser importadas da biblioteca do PrimeFaces.


E a index deve ser editada para:
<h:form>
    <p:growl id="mensagem"  showDetail="true" />

    <p:gmap center="-15.565986,-54.309782" zoom="15" type="HYBRID" style="width:600px;height:400px">
        <p:ajax event="pointSelect" listener="#{localBean.pontoSelecionado}" update="mensagem" />
    </p:gmap>
</h:form>
Adicionamos tudo dentro de um h:form por conta do p:growl, então na linha 2 adicionamos o p:growl.
Linha 5: é adicionado a tag p:ajax, onde temos a propriedade event, listener que chama o método da nossa classe LocalBean, e por fim atualizamos o growl.
Resultando em:


Adicionando e carregando marcadores de um banco de dados
Para este exemplo estaremos gravando os marcadores em um banco de dados, e como disse anteriormente, estarei usando JPA para agilizar este desenvolvimento, então, para começo de conversa vamos fazer nossa classe model.Local:
@Entity
@Table(name="local")
public class Local implements Serializable{
    
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Column(name="codigo", nullable=false, unique=true)
    private Long codigo;
    @Column(name="descricao")
    private String descricao;
    @Column(name="latitude")
    private double latitude;
    @Column(name="longitude")
    private double longitude;

    /*
     * Getters e Setters
     */
}

Agora vamos fazer nossa classe dao.LocalDAO:
@Stateless
public class LocalDAO {
    
    @PersistenceContext(unitName="PrimeGmapPU")
    private EntityManager em;
    
    public void gravar(Local local){
        try {
            em.persist(local);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public List<Local> listar(){
        List<Local> locais = new ArrayList<Local>();
        try {
            Query query = em.createQuery("SELECT l FROM Local l");
            locais = query.getResultList();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return locais;
    }
    
}

Lembrando que na Linha 4, o unitName, é da minha unidade de persistência, o que pode mudar de acordo como você criou sua conexão.
Agora vamos para nossa classe controller.LocalBean, eu refiz ela, ou seja tirei do projeto aquela questão do growl, ela ficou dessa forma:

@javax.faces.bean.ManagedBean
@javax.faces.bean.ViewScoped
public class LocalBean implements Serializable{

    @EJB
    private LocalDAO localDAO;
    private Local local;
    private MapModel locais;

    public void novo(PointSelectEvent event) {
        local = new Local();
        LatLng coord = event.getLatLng();
        local.setLatitude(coord.getLat());
        local.setLongitude(coord.getLng());
    }

    public void gravar() {
        localDAO.gravar(local);
        carregarLocais();
    }

    private void carregarLocais() {
        locais = new DefaultMapModel();

        List<Local> locaisList = localDAO.listar();
        for (Local l1 : locaisList) {
            locais.addOverlay(
                    new Marker(
                    new LatLng(l1.getLatitude(), l1.getLongitude()),
                    l1.getDescricao()));
        }
    }

    /*
     * Getters e Setters
     */
    public MapModel getLocais() {
        if (locais == null) {
            carregarLocais();
        }
        return locais;
    }

}

Linha 8: a classe MapModel deve ser importada da biblioteca do Primefaces;
Linha 10: método novo, responsável por pegar as coordenadas geográficas e setar no meu objeto Local;
Linha 17: método gravar, responsável por chamar o DAO e gravar o método no banco de dados;
Linha 22: método carregarLocais, este método é responsável por converter uma lista de locais em um MapModel;
Linha 37: neste caso estou mostrando apenas esse get, por ter um diferencial que é carregar os locais caso o mesmo esteja null.

E por fim nossa página index.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true" />
        <title>GMap</title>
    </h:head>
    <h:body style="font-size: 12px">
        <p:gmap id="mapa" center="-15.565986,-54.309782" zoom="15" model="#{localBean.locais}" onPointClick="dlgLocal.show()" type="HYBRID" style="width:600px;height:400px">
            <p:ajax event="pointSelect" listener="#{localBean.novo}" update="formLocal" />
        </p:gmap>

        <p:dialog widgetVar="dlgLocal" width="280" height="100">  
            <h:form id="formLocal">  
                <p:focus for="desc" />
                <h:panelGrid columns="2" style="width: 100%">
                    <h:outputLabel for="desc" value="Descrição:" />  
                    <p:inputText id="desc" value="#{localBean.local.descricao}" /> 
                </h:panelGrid>
                <p:toolbar>
                    <p:toolbarGroup align="right">
                        <p:commandButton value="Gravar" actionListener="#{localBean.gravar()}" oncomplete="dlgLocal.hide()" update=":mapa" />
                    </p:toolbarGroup>
                </p:toolbar>
            </h:form>  
        </p:dialog>
    </h:body>
</html>

Agora vamos entender o que está acontecendo nesta página:
Linha 9:  temos o gmap, com a propriedade model, que está relacionada ao MapModel do nosso controller, e a propriedade onPointClick, que abre o dialog de cadastro de um novo marcador;
Linha 10: chama o método novo quando é clicado no mapa;
Linha 13: temos o dialog que faz o cadastro de um novo marcador.
Ficando dessa forma:


Este projeto foi apenas para dar uma base de como carregar e adicionar marcadores no gmaps com o PrimeFaces. Também não tratei o dialog, ou seja, precisaria de um "trato especial" no caso dele não fechar quando o campo descrição estiver vazio. Bom eu tenho o código que faz isso, mas para não deixar essa postagem mais extensa, não coloquei aqui, provavelmente eu deva criar uma postagem sobre como controlar o dialog, até mesmo como abrir ou fechar ele pelo controller.

Até mais! :)

22 de julho de 2012

PrimeFaces 3.3: Começando...

Vamos começar criando um projeto básico do básico. Para os exemplos futuros, estarei usando o NetBeans 7.1 e o GlassFish 3.1.1. Então crie uma Aplicação Web no netBeans, caso não saiba como fazer isso, veja aqui
Para baixar o PrimeFaces, clique aqui, basta selecionar a versão que quer utilizar, estarei usando a versão 3.3, irei aguardar um pouco para testar a 3.3.1.

A estrutura do projeto será a seguinte:

Depois de criado o projeto, adicione a biblioteca do PrimeFaces no projeto (para fazer isso, botão direito em Bibliotecas e Add jar/pasta, e encontre a biblioteca que foi baixada).

Aproveitando a página index.xhtml (criada automaticamente ao criar o projeto), vamos adicionar a namespace do PrimeFaces na tag html: 

xmlns:p="http://primefaces.org/ui"

A página deverá ficar dessa forma:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Start com PrimeFaces 3.3</title>
    </h:head>
    <h:body>
        <h:form>
            <p:editor />
        </h:form>
    </h:body>
</html>

Lembrando que para o PrimeFaces funcionar, é extremamente necessário que haja a tag head. para este exemplo, apenas utilizei o componente p:editor, o resultado é o seguinte:


Como eu falei, esse é só o começo de como usar o PrimeFaces...


Temas


Quanto aos temas, podem ser visualizados aqui: Temas PrimeFaces. e podem ser baixados pelo repositório do próprio Prime, aqui. Para baixar um tema escolha-o pelo nome na galeria de temas, e o procure no repositório, aconselho utilizar a ultima versão, a maioria dos temas se encontram (até o momento da postagem) na versão 1.0.6.
Depois e escolhido o tema, adicione às bibliotecas juntamente com a biblioteca do PrimeFaces, e no WEB-INF/web.xml, adicione as seguintes tags:
<context-param>  
    <param-name>primefaces.THEME</param-name>  
    <param-value>bluesky</param-value>  
</context-param> 

Para este exemplo, escolhi a biblioteca Bluesky, por isso dentro da tag param-value deve ser colocado o nome do tema, sem a versão.
Para quem deseja ter seu próprio tema, use o JQuery UI - ThemeRoller, para saber como utilizar seu próprio tema, veja o final desta postagem.

Até mais!

21 de março de 2012

JSF 2.0: Template em Facelets com Layout do PrimeFaces 3.0

Olá pessoas!
Depois de meses ausente, estou voltando a escrever mas a partir de agora é sobre a versão 3 do PrimeFaces!
Primeiramente baixe a versão 3.0 do PrimeFaces aqui. Agora vamos criar um projeto, no meu caso o nome  do meu projeto será "template", este terá a seguinte estrutura:

O que eu fiz de diferente... para ficar um projeto mais organizado, eu criei uma pasta tema dentro de Páginas Web, ainda dentro da pasta tema eu criei uma pasta imagens, que é onde eu guardo todas as imagens do design do sistema, nesse caso só coloquei a imagem que será o topo do nosso template.
O principal de tudo isso é o nosso padrao.xhtml que foi criado dentro do tema, ele será o responsável pelo nosso template, nele eu coloco tudo o que será comum a todas as páginas que terão template, por exemplo, o componente growl (que mostra avisos ao usuário, visto em postagens anteriores), além de styles CSS que as vezes é necessário.
O meu template ficará assim:


Então meu template (padrao.xhtml) ficou assim:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Meu Sistema</title>
        <style type="text/css">
            body {background-color: #eeeeee; font-size: 12px}
        </style> 
    </h:head>
    <h:body>
        <div align="center">
            <p:layout style="min-width:1020px;max-width:1020px;min-height:600px">  
                <p:layoutUnit position="north" size="100">  
                    <h:graphicImage url="/tema/imagens/topo.jpg" />
                </p:layoutUnit>  

                <p:layoutUnit position="west" size="220">  
                    <ui:insert name="menu">
                        <h:form>
                            <p:menu style="width: 200px">
                                <p:submenu label="Menu">
                                    <p:menuitem value="Login" icon="ui-icon-key" />
                                    <p:menuitem value="Fazer meu cadastro" icon="ui-icon-contact" />         
                                </p:submenu>
                            </p:menu>
                        </h:form>
                    </ui:insert>
                </p:layoutUnit>  
                <p:layoutUnit position="center">  
                    <ui:insert name="centro">
                        O que estiver aqui será substituido!
                    </ui:insert>
                </p:layoutUnit>  
            </p:layout>  
        </div>
    </h:body>
</html>

Vamos às observações quanto ao código:
Linha 4: Devemos observar que para usar a versão 3.0 do PrimeFaces a namespace é outra agora!
Linha 15: Criação de uma div centralizada, pois meu layout deverá ficar centralizado.
O segredo do template estão nas linhas 22 e 34 por conta das tags ui:insert, ou seja são elas que definem onde ficará meus componentes. Perceba que eu já coloquei o menu diretamente no meu template, já que será algo para o projeto inteiro, caso precise de um outro menu para uma página exclusiva, apenas sobrescreva o menu na página que deseja. Observação: sempre fique atento ao name da tag ui:insert, pois são eles que definem o que será o menu, ou que será o centro da nossa página (não é obrigado a usar os mesmos nomes que eu coloquei).
Agora vamos ver como vai ficar nosso index.xhtml:


Veja que só mudou nossa frase do centro... agora vamos ver como usar o tal template!
Página index.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <ui:decorate template="/tema/padrao.xhtml">
        <ui:define name="centro">
            Aqui é o centro do index!
        </ui:define>
    </ui:decorate>
</html>

Vamos às observações:
1 - veja que na nossa página não temos mais as tags h:head e h:body ... elas foram substituídas pela tag ui:decorate (caso não saiba do que eu estou falando, veja essa postagem sobre facelets) nela eu defino qual é o template que eu estou usando nessa página, ou seja, é possível ter mais de um template no mesmo sistema sem problemas!
2 - observe que eu só sobrescrevi o centro (linha 5), tudo que deve ficar no centro da página deve ficar dentro da tag ui:define.

Conclusão: quando se utilizo templates, temos geralmente apenas uma página que contém h:head e h:body que é o próprio template (a não ser que o sistema tenha outras páginas sem template), quanto as outras páginas com template, elas precisam ter o ui:decorate ou ui:composition (veja a postagem de facelets, link acima). Ao executar seu sistema, olhe o código fonte, e veja que o código do template fica embutido com o código da sua página, como se tudo estivesse na mesma página.

Vantagem: Quer alterar o seu design? Quando começou o sistema o seu design era um, e agora já se cansou dele? Então, essa pode ser uma boa solução para você, pois a vantagem é bem essa, ter que fazer alterações em apenas uma página para trocar o design do sistema inteiro. Imagina o que seria um sistema com 50 páginas sem utilizar template? Seria necessário passar de página por página alterando o design, ainda correndo o risco de deixar uma página de fora das alterações.

Nesse exemplo eu fiz uma junção do componente p:layout do PrimeFaces com o Facelets (responsável pelas tags: ui:insert, ui:define ui:.... etc...), mas se preferir usar CSS, nada te impede, coloque o ui:insert dentro de div formatadas na posição que desejar.

Bom... o post de hoje foi curto, mas espero que seja útil!

12 de março de 2012

Tutorial PDFBox



PDFBox é uma biblioteca que permite manipular arquivos PDF, seja para criação de novos documentos ou mesmo de documentos já existentes, permitindo a extração de seu conteúdo.
Essa ferramenta possui as seguintes características:

  • PDF to text extraction
  • Merge PDF Documents
  • PDF Document Encryption/Decryption
  • Lucene Search Engine Integration
  • Fill in form data FDF and XFDF
  • Create a PDF from a text file
  • Create images from PDF pages
  • Print a PDF

Este tutorial demonstra o uso do PDFBox, implementando exemplos de cada funcionalidade disponível pela biblioteca. Com o objetivo secundário, busca apresentar o Apache Maven aos desenvolvedores que estão iniciando com essa ferramenta.

Videos em breve.

Gostaria de agradecer a oportunidade de escrever meus artigos e tutoriais no java sem café. É uma honra poder compartilhas minhas experiencias e ideias neste espaço tão especial construído pela professora Andréia.
Java sem café, sem dúvida nenhuma se tornou um ponto de referencia para aqueles que buscam conteúdo de qualidade. Espero contribuir e continuar o excelente trabalho que Andréia vem realizando.

Obs. Gosto muito de café!
Ivan Salvadori