Arquivo por categoria Primefaces

Iniciando Se No JSF – 03 – A Arquitetura Da Aplicação



Bom a imagem abaixo representa a estrutura de pacotes em que se divide nossa aplicação. De cima para baixo temos as pastas META-INF e WEB-INF a primeira delas não tem muita relevância nesse caso já a segunda é reponsável por armazenar os arquivos de configuração de nossa aplicação como faces.config.xml que armazena as configurações do JSF, o web.xml que mapeia listeners, servlets e demais configurações da aplicação e por fim temos o spring-security.xml que armazena as configurações de segurança de nossa aplicação. Um pouco abaixo temos as pastas public, restrict e resources. A pasta public no nosso projeto conterá as páginas que poderão ser acessadas sem a necessidade de autenticação por parte do usuário a restrict por sua vez armazena as páginas que só serão acessadas por usuários autenticados e autorizados. A pasta resources contém outras duas pastas public e restrict onde são armazenados arquivos de css, javascript e templates Facelets correspondentes as páginas publicas e restritas.
Logo abaixo temos nossa estrutura de pacotes. Inicialmente temos o pacote br.com.semeru.controller que armazena as classes da camada de controle de nossa aplicação. Logo abaixo temos o pacote br.com.semeru.conversores que armazena as classes responsáveis por converter dados, como por exemplo criptografar uma senha. Logo abaixo temos o pacote br.com.semeru.exceptions que armazena as classes responsáveis por tratar as exceções ocorridas na aplicação. Logo abaixo temos o pacote br.com.semeru.i18n que é responsável por prover internacionalização da aplicação, entretanto isso ainda não foi aplicado no projeto atual. Mais abaixo temos o pacote br.com.semeru.dao que armazena a uma interface do DAO e uma classe de DAO Genérico que é responsável por acessar os a base de dados. Um pouco mais abaixo temos o pacote br.com.semeru.entities que armazena as entidades que representam as tabelas do banco de dados da nossa aplicação. Vale destacar que nossa arquitetura segue o padrão MVC onde as páginas representam a camada de visão (V) os DAO’s e as Entidades representam o modelo (M) e o controle é representado pelos nossos ManagedBeans. Logo abaixo temos o pacote br.com.semeru.suport que armazena os BackingBeans de nossa aplicação essas classes são reponsáveis por oferecer suporte à página não processando nada e raramente contendo regras de negócio. Por fim temos o pacote br.com.semeru.validators que armazena as classes responsáveis por realizar validações de dados no projeto.
Temos ainda no pacote default o arquivo hibernate.cfg.xml, a fim de manter o projeto levemente mais simples vamos mantê-lo no pacote default. Pouco depois temos o pacote ScriptsSQL que contem o backup de alguns dados do nosso banco e depois o arquivo pom.xml que é o responsável por armazenar as configurações do Maven. Não irei me aprofundar muito em explicações do Maven para entender melhor sobre o maven acesse este link, este e este.

ArquiteturaSemeru

05 – Curso De JSF Do Zero À Nuvem – Definindo A Estrutura De Pacotes

Nesse vídeo iremos montar toda a estrutura de pacotes onde é explicado com mais detalhe todo o projeto.



Aqui temos a classe HibernateUtil que é responsável por criar a SessionFactory que nos permitirá acessar a base de dados. Inicialmente declaramos uma instância de SessionFactory e depois uma constante com a sessão do Hibernate. Logo abaixo temos um bloco estático que é responsável por tentar criar uma SessionFactory. Inicialmente declaramos uma instância de Configuration. Posteriormente tentamos registrar uma SessionFactory para isso passamos como parâmetro no método applySettings as informações do nosso hibernate.cfg.xml se mudarmos esse arquivo para um pacote diferente do default deveremos passar sua localização como parâmetro configuration.getProperties, caso contrário o Hibernate não saberá se localizar. Caso ocorra alguma falha nesse processo uma exception será lançada. Por fim temos o o método getSessionFactory que é o responsável por permitir a obtenção da SessionFactory pelo nosso PhaseListener, que será abordado mais abaixo.

package br.com.semeru.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil {
    
    private static final SessionFactory sessionFactory;
    public static final String HIBERNATE_SESSION = "hibernate_session";
    
    static{
        
        try {     
            Configuration configuration = new Configuration().configure();
            
            ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().
                applySettings(configuration.getProperties()).buildServiceRegistry();            
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);                        
        } catch (Exception ex) {
            throw new ExceptionInInitializerError(ex);
        }                
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    
}



06 – Curso De JSF Do Zero À Nuvem – Criando A Classe HibernateUtil

Aqui temos o processo de criação da classe HibernateUtil que detalha um pouco mais essas informações.



07 – Curso De JSF Do Zero À Nuvem – Removendo Dependência Duplicada E slf4j



Nesse vídeo removemos uma dependência duplicada e o slf4j que estavam impedindo a execução de nosso projeto.





Aqui temos as nossa InterfaceDAO que define os métodos que o nosso DAO genérico deverá implementar. São eles save, update, remove, merge responsáveis por salvar, atualizar, remover e tanto salvar quanto atualizar respectivamente. Temos também os métodos de leitura como por exemplo o getEntity que obtém um objeto no banco, o getEntityByDetachedCriteria que obtém um objeto no banco através de uma DetachedCriteria, o getEntities que obtém uma lista de objetos no banco e getListByDetachedCriteria que obtém uma lista de objetos no banco através de uma DetachedCriteria.

package br.com.semeru.model.dao;

import java.io.Serializable;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;

public interface InterfaceDAO<T> {
    
    void save (T entity);
    void update (T entity);
    void remove (T entity);
    void merge (T entity);
    T getEntity(Serializable id);
    T getEntityByDetachedCriteria(DetachedCriteria criteria);
    List<T> getEntities();
    List<T> getListByDetachedCriteria(DetachedCriteria criteria);    
    
}


Aqui temos a nossa classe HibernateDAO que é de tipagem genérica, o que siginfica que o nosso DAO possibilitará a persistencia de todas as entidades da nossa aplicação. No nosso construtor obrigamos a sempre passar o tipo da entidade que queremos persistir e a sessão do hibernate para que o DAO faça o serviço. Além disso toda a implementação é bastante simples, sendo necessário apenas usar a session do hibernate e executar seus métodos passando a entidade envolvida como parâmetro.


package br.com.semeru.model.dao;

import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;

public class HibernateDAO<T> implements InterfaceDAO<T>, Serializable {

    private static final long serialVersionUID = 1L;
    
    private Class<T> classe;
    private Session session;

    public HibernateDAO(Class<T> classe, Session session) {
        super();
        this.classe = classe;
        this.session = session;
    }
    
    
    @Override
    public void save(T entity) {
        session.save(entity);
    }

    @Override
    public void update(T entity) {
        session.update(entity);
    }

    @Override
    public void remove(T entity) {
        session.delete(entity);
    }

    @Override
    public void merge(T entity) {
        session.merge(entity);
    }

    @Override
    public T getEntity(Serializable id) {
        T entity = (T)session.get(classe, id);
        return entity;
    }

    @Override
    public T getEntityByDetachedCriteria(DetachedCriteria criteria) {
        T entity = (T)criteria.getExecutableCriteria(session).uniqueResult();
        return entity;
    }

    @Override
    public List<T> getListByDetachedCriteria(DetachedCriteria criteria) {
        return criteria.getExecutableCriteria(session).list();
    }
    
    @Override
    public List<T> getEntities() {
        List<T> enties = (List<T>) session.createCriteria(classe).list();
        return enties;
    }    
    
}


08 – Curso De JSF Do Zero À Nuvem – Criação Do DAO Genérico

Nesse vídeo nós criamos a interface e o DAO genérico, neles você terá informações com maiores detalhes.


Aqui temos a classe FacesContextUtil que é responsável por colocar na sessão do usuário (FacesContext) do JSF, a sessão do Hibernate. Como se pode perceber ela possui um atributo estático que é a chave da sessão do Hibernate e dois métodos set e get. O primeiro deles captura o RequestMap do FacesContext e atribui a ele a sessão do Hibernate. O segundo método obtém de volta a sessão do Hibernate para que o PhaseListenerSemeru possa realizar o commit na transação como será explicado mais abaixo.


package br.com.semeru.util;

import javax.faces.context.FacesContext;
import org.hibernate.Session;

public class FacesContextUtil {

    private static final String HIBERNATE_SESSION = "hibernate_session";

    public static void setRequestSession(Session session){
        FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(HIBERNATE_SESSION, session);
    }
    
    public static Session getRequestSession() {
        return (Session)FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get(HIBERNATE_SESSION);
    }
    
}

Antes de partir para a próxima etapa recomendo que você leia este post que explica como funciona o ciclo de vida do JSF. Agora aproveite para assistir também a parte teórica do video abaixo em que isso é abordado com mais detalhes.

09 – Curso De JSF Do Zero À Nuvem – O Ciclo De Vida De Uma Request No JSF E O FacesContextUtil



Atuando junto à classe FacesContextUtil temos a classe PhaseListenerSemeru é a responsável por auxiliar o sistema de login e por implementar o padrão Open Session in View do Hibernate. Open Session in View consiste em iniciar a transação quando é feita uma requisição e encerrá-la quando a página é renderizada. O PhaseListenerSemeru implementa a interface PhaseListener do JSF e possui três métodos beforePhase, afterPhase e getPhaseId. O método beforePhase verifica se a fase está antes da Restore View (Restaurar a Visão), se estiver ele abre a sessão do Hibernate e coloca-a na requisição do usuário passando-a para o FacesContext. O segundo método, verifica se a fase Render Response (Renderizar a Resposta) foi executada, se sim, ele tenta commitar a transação. Se ocorrer algum erro ele imprime uma mensagem no log, nesse momento, caso a sessão ainda esteja ativa ele executa um rollback e finalmente fecha a sessão. Caso não ocorram erros ele encerra a transação e fecha a sessão. Já o terceiro método, o getPhaseId é responsável por especificar em que fase o PhaseListener deve ser acionado, no nosso exemplo ele é acionado em todas as fases. Dessa forma, a classe PhaseListenerSemeru implementa o Open Session in View de forma transparente para o desenvolvedor. Essa abordagem torna desnecessário, ao desenvolvedor, se preocupar com abrir e fechar a sessão. Toda a responsabilidade pelo controle de sessão passa a ser feito pelo PhaseListenerSemeru através da verificação das fases da requisição no FacesContext, do JSF.

package br.com.semeru.util;

import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import org.hibernate.Session;

public class PhaseListenerSemeru implements PhaseListener {

    //Antes da Fase
    @Override
    public void beforePhase(PhaseEvent fase) {
        System.out.println("Antes da fase: "+ fase.getPhaseId());
        if (fase.getPhaseId().equals(PhaseId.RESTORE_VIEW)) {            
            Session session = HibernateUtil.getSessionFactory().openSession();
            session.beginTransaction();
            FacesContextUtil.setRequestSession(session);            
        }
    }
    
    //Depois da Fase
    @Override
    public void afterPhase(PhaseEvent fase) {
        System.out.println("Depois da fase: "+ fase.getPhaseId());
        if (fase.getPhaseId().equals(PhaseId.RENDER_RESPONSE)) {
            Session session = FacesContextUtil.getRequestSession();
            try {
                session.getTransaction().commit();
            } catch (Exception e) {
                if (session.getTransaction().isActive()) {
                    session.getTransaction().rollback();
                }
            } finally{
                session.close();
            }
        }
    }

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }
    
}

Para reforçar os conceitos sobre o PhaseListener assista mais essa vídeo aula.

10 – Curso De JSF Do Zero À Nuvem – O PhaseListener

Agora que temos uma visão geral mais clara botaremos para quebrar nos próximos posts. Lembrando que os comentários são importantes para que eu possa ir melhorando gradativamente os posts. Quero destacar também que os fontes desse curso podem ser baixados do GitHub. Serão feitos posts correspondentes às demais vídeo aulas e assim que possível irei realizando posts para complementar o que foi falado nos vídeos. É isso aí bons estudos.

Tags: , ,

Iniciando Se No JSF – 02 – Configurando O Ambiente E Criando O Primeiro Projeto

Nesse segundo post do Curso De JSF Do Zero À Nuvem Eu explico como instalar e configurar as duas IDE’s mais utilizadas no mercado, os plugins de versionamento e a criação do primeiro projeto.

Inicialmente explico onde baixar e como instalar a IDE Eclipse e os plugins EGit e Github MyLyn Connector para versionar o projeto no GitHub. É algo relativamente simples mas que pode ajudar muito alguém iniciante.


Instalando O Eclipse E Os Plugins m2eclipse, Subclipse E EGit





Posteriormente eu explico como instalar o Netbeans e configurar o Apache Tomcat. Diferentemente do Eclipse não é necessário instalar nenhum plugin.


Instalando O Netbeans E Configurando O Tomcat





Por fim criamos um repositório no GitHub e criamos nosso primeiro projeto.


Criando O Repositório E Iniciando O Projeto Maven



Observação importante:

Se você pretende trabalhar com o Eclipse ou mesmo com as duas IDE’s recomendo que você edite o POM e altere tudo que está entre as tags plugins de modo que fique igual ao trecho abaixo.

<plugins>           
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.6</source>
            <target>1.6</target>
            <encoding>${project.build.sourceEncoding}</encoding>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
            <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <configuration>
            <encoding>${project.build.sourceEncoding}</encoding>
        </configuration>
    </plugin>
</plugins>

No mais boa sorte e bons códigos sem bugs.

Tags: , , , ,

Iniciando Se No JSF – 01 – Apresentação, O Projeto E As Tecnologias

Olá. Este post é para apresentar o curso de JSF a vocês. Quando eu comecei a trabalhar com JSF eu usava apostilas na internet, video aulas no Youtube, livros e vivia correndo atrás de todo mundo que pudesse me ajudar a entender melhor o framework. Aprendi bastante de lá pra cá e como eu não posso retribuir diretamente a todos que me ajudaram nem outros que como eu hoje precisam de ajuda então decidi gravar uma série de video aulas a respeito. Creio que esse é a melhor forma de contribuir, e espero que ajude você a começar com JSF.

Além de JSF você aprenderá o básico de uma série de outras tecnologias que vão desde o Hibernate, Primefaces, Spring Security, Maven, Tomcat, Netbeans, Eclipse e além disso ao final do projeto você aprenderá como fazer o deploy na nuvem. No vídeo abaixo eu apresento o resultado final de todo o projeto e as tecnologias com as quais iremos trabalhar.


Curso De JSF Do Zero À Nuvem – O Projeto E As Tecnologias Envolvidas

No segundo vídeo você irá entender os principais conceitos teóricos do JSF. Além disso você terá dicas de por onde começar com o JSF.


Entendendo O JSF E Dicas

Além dos livros indicados no vídeo existem muitas apostilas gratuitas na web. Temos uma da Algaworks que apesar de abordar a versão 1.2 do JSF é bem interessante para quem está iniciando. Temos duas muito boas da K19 uma de JSF com JPA e outra de JSF com EJB a Caelum surpreendentemente não tem nada sobre o JSF talvez seja pra puchar a sardinha do VRaptor. Outras apostilas como a Do Luis Fernado e a do Diego Rezende que podem ser baixadas do Scribd. Além dessas uma rápida pesquisa no Google pode lhe mostrar uma infinidade de materiais a respeito. No Youtube além das minhas vídeo aulas existem outras que podem ajudar bastante quem está começando.

Se você quiser baixar os slides da apresentação basta ir ao SlideShare e fazer isso.

Quero destacar também que os fontes desse curso podem ser baixados do GitHub. Serão feitos posts correspondentes às video aulas e recomendo que você acompanhe por que assim que possível irei realizando posts para complementar o que foi falado nos vídeos.

Tags: , , , ,

Manipulando de Exceções no JavaServer Faces (JSF) 2.x

Uma das funcionalidades mais simples e legais introduzidas pela especificação 2.0 do JSF é a possibilidade de se criar um manipulador global de exceções. Trechos de código como esse aqui abaixo tratando as exceções previstas uma a uma no web.xml se tornaram desnecessários.

<error-page>
  <error-code>404</error-code>
  <location>/404.xhtml</location>
</error-page>

Ao invés da solução acima, o JavaServer Faces nos permite implementar um manipulador global de exceções de forma relativamente simples para todas as exceções que podem ocorrer na aplicação. Para isso, você precisa apenas de criar duas classes que estendam as classes:
ExceptionHandlerWrapper – Que fornece uma implementação simplificada da ExceptionHandler permitindo por exemplo que os desenvolvedores possam fornecer um comportamento especializado para uma instância ExceptionHandler.
ExceptionHandlerFactory – Essa classe por sua vez atua como uma Factory responsável por criar e retornar, quando necessário, uma nova instância de ExceptionHandler.
Por fim você precisa apenas algumas linhas ao arquivo “faces.config.xml” responsáveis por registrar a classe de tratamento no FacesServlet.

	
<factory>
  <exception-handler-factory>
     br.com.semeru.exceptions.CustomExceptionHandlerFactory
  </exception-handler-factory>
</factory>

No trecho de código abaixo temos a classe “CustomExceptionHandlerFactory” que é responsável por fabricar uma instância da classe “CustomExceptionHandler” que é responsável por capturar e tratar a exceção.

package br.com.semeru.exceptions;

import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {
    private ExceptionHandlerFactory parent;

    public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
        this.parent = parent;
    }

    @Override
    public ExceptionHandler getExceptionHandler() {
        ExceptionHandler handler = new CustomExceptionHandler(parent.getExceptionHandler());
        return handler;
    }

}

Já no trecho abaixo temos a classe “CustomExceptionHandler” que pode tratar a exceção da forma que você julgar mais apropriada. Você pode simplesmente imprimir a StackTrace e retornar uma página de erros, ou tratar as exceções que mais ocorrem e retornar uma página personalizada para cada uma delas. Outra coisa que pode ser interessante é enviar a StackTrace via e-mail para a equipe de desenvolvimento.

package br.com.semeru.exceptions;

//import java.io.PrintWriter;
//import java.io.StringWriter;
import java.util.Iterator;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.application.NavigationHandler;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;

//Inicialmente devemos implementar a classe CustomExceptionHandler que extende a classe ExceptionHandlerWrapper
public class CustomExceptionHandler extends ExceptionHandlerWrapper {

    private ExceptionHandler wrapped;

    //Obtém uma instância do FacesContext
    final FacesContext facesContext = FacesContext.getCurrentInstance();

    //Obtém um mapa do FacesContext
    final Map requestMap = facesContext.getExternalContext().getRequestMap();

    //Obtém o estado atual da navegação entre páginas do JSF
    final NavigationHandler navigationHandler = facesContext.getApplication().getNavigationHandler();

    //Declara o construtor que recebe uma exceptio do tipo ExceptionHandler como parâmetro
    CustomExceptionHandler(ExceptionHandler exception) {
        this.wrapped = exception;
    }

    //Sobrescreve o método ExceptionHandler que retorna a "pilha" de exceções
    @Override
    public ExceptionHandler getWrapped() {
        return wrapped;
    }

    //Sobrescreve o método handle que é responsável por manipular as exceções do JSF
    @Override
    public void handle() throws FacesException {

        final Iterator iterator = getUnhandledExceptionQueuedEvents().iterator();
        while (iterator.hasNext()) {
            ExceptionQueuedEvent event = iterator.next();
            ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();

            // Recupera a exceção do contexto
            Throwable exception = context.getException();

            // Aqui tentamos tratar a exeção
            try {

//                // Aqui você poderia por exemploinstanciar as classes StringWriter e PrintWriter
//                StringWriter stringWriter = new StringWriter();
//                // PrintWriter printWriter = new PrintWriter(stringWriter);
//                // exception.printStackTrace(printWriter);
//                // Por fim você pode converter a pilha de exceções em uma String
//                String message = stringWriter.toString();
//
//                // Aqui você poderia enviar um email com a StackTrace
//                // em anexo para a equipe de desenvolvimento
//
//                // e depois imprimir a stacktrace no log
//                exception.printStackTrace();

                // Coloca uma mensagem de exceção no mapa da request
                requestMap.put("exceptionMessage", exception.getMessage());

                // Avisa o usuário do erro
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage
                    (FacesMessage.SEVERITY_ERROR, "O sistema se recuperou de um erro inesperado.", ""));

                // Tranquiliza o usuário para que ele continue usando o sistema
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage
                    (FacesMessage.SEVERITY_INFO, "Você pode continuar usando o sistema normalmente!", ""));

                // Seta a navegação para uma página padrão.
                navigationHandler.handleNavigation(facesContext, null, "/restrict/home.faces");

                // Renderiza a pagina de erro e exibe as mensagens
                facesContext.renderResponse();
            } finally {
                // Remove a exeção da fila
                iterator.remove();
            }
        }
        // Manipula o erro
        getWrapped().handle();
    }
}

No bloco try-finally você pode converter o Throwable em qualquer exceção específica e dar um tratamento especial a cada uma delas. Um simples problema de ViewExpiredException, por exemplo, pode ser redirecionado para uma página informando que a “sessão expirou” já, no caso de uma exceção do tipo NullPointerException podemos usar uma página padrão apenas dizendo algo como “Ocorreu um erro inesperado, por favor, tente novamente mais tarde.”
Um detalhe muito importante a se lembrar é que ao lidar com exceções em desenvolvimento web, você deve garantir que não está compartilhando informações indesejadas e/ou sensíveis ao retornar o erro para a página web.

Bom é isso e espero que gostem do post.

Editado para responder ao comentário do André

Olá gravei uma vídeo aula explicando de forma clara como adotar o exception handler em um projeto JSF.

Tags: , , , , ,

Novos posts

Bom pessoal até aqui a maioria dos posts abordavam quase que completamente temas voltados à Engenharia de Software e/ou aspectos mais teóricos. Isto se deve ao fato de eu ter aproveitado grande parte do que escrevi no meu TCC como material para os posts anteriores. Até então eu usava o Blogger então migrei tudo pra cá e ainda estou “arrumando a casa”. Daqui pra frente vou começar a postar materiais relacionados à desenvolvimento. Mais especificamente sobre JSF, Primefaces, JPA, Hibernate, Spring Framework, Spring Security, Play! Framework e Grails. Além disso estou preparando uma série de vídeo-aulas, sobre estes temas e em breve estarão on-line.

Espero que gostem e voltem novamente.

Tags: , , , , ,