Parte 2 – Projeto JEE configurando web.xml e o Filter

Galera, dando inicio ao segundo post das configurações do projeto JavaEE, hoje veremos as configurações do arquivos web.xml, a configuração do Hibernate Envers e a implementação do padrão Open Session in View, este ultimo resolve vários problemas enfrentados por quem está iniciando no mundo web.
A sequencia de explicação dos post é a mesma sequencia de criação do projeto e configurações.

O web.xml

O primeiro passo é conferir a estrutura inicial do arquivo em seu corpo deve conter apenas a pagina de index.jsp que é o inicial que será lido quando acessarmos o sistema pelo navegador.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp" 
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" metadata-complete="true" version="3.0">
	<display-name>CaixakiWeb</display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

Tempo limite da sessão, caso o usuário fique 15 minutos sem manipular o sistema a sessão é encerrada automaticamente.

<session-config>
		<session-timeout>15</session-timeout> <!-- Invalida a sessao em 15 minutos -->
		<tracking-mode>COOKIE</tracking-mode>
</session-config>

Como vamos trabalhar com paginas jsp e xhtml juntas se faz necessário a configuração de grupos para o jsp.

<jsp-config>
		<jsp-property-group>
			<url-pattern>/**</url-pattern>
			<el-ignored>false</el-ignored>
		</jsp-property-group>
</jsp-config>

Permitindo comentários em paginas JSF, a configuração abaixo permite efetuar comentários dentro das paginas jsf, comentários de expression language somente são permitidos com a configuração abaixo.

<context-param>
		<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
		<param-value>true</param-value>
</context-param>

Habilitando a renderização de filhos de componentes UIInput and UIOutput, a partir da versão 2.0 essa configuração se faz necessária mas não obrigatória.

<context-param>
		<param-name>com.sun.faces.allowTextChildren</param-name>
		<param-value>true</param-value>
</context-param>

Resolve problemas de incompatibilidade nas versões do Tomcat e jsp.

<context-param>
		<param-name>com.sun.faces.expressionFactory</param-name>
		<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>

Inicializando os arquivos de contexto do Spring Frameworks, Spring Servlet e Spring Security, estes iremos criar no próximo post, porem já deixamos declarado corretamente.

<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
				/WEB-INF/applicationContext.xml 
				/WEB-INF/spring-servlet-servlet.xml
				/WEB-INF/applicationContext-security.xml
  		</param-value>
</context-param>

Define período para atualizar as mudanças do sistema.

<context-param>
		<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
		<param-value>2</param-value>
</context-param>

Define a lista de extensões de paginas que o projeto irá suportar.

<context-param>
		<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
		<param-value>.xhtml .html .jsp</param-value>
</context-param>

Define o estágio do nosso projeto, normalmente se define como development mas para não termos surpresas quando o projeto for para produção iremos definir já como Production.

<context-param>
		<param-name>javax.faces.PROJECT_STAGE</param-name>
		<param-value>Production</param-value>
</context-param>

Definindo o tema do PrimeFaces, é este o tema que o projeto do vídeo etá usando, claro com algumas modificações que fizemos no css.

<context-param>
		<param-name>primefaces.THEME</param-name>
		<param-value>smoothness</param-value>
</context-param>

Declaração da classe FilterOpenSessionInView, está classe é a responsável por interceptar as requisições do nosso projeto, tanto a requisição como as respostas do http passam por este filtro.
Atribuições do filtro:
Iniciar o Hibernate quando o servidor sobe a aplicação.
Para cada requisição iniciar uma nova transação, efetuar commit ou dar roolback e fechar a transação.
Efetuar commit ou rollback em transação do SpringJdbc.
Identificar o usuário logado para o Hibernate envers que faz o controle de log de registro.

O FilterOpenSessionInView

Para a criação do filtro vamos precisar das outras classe que compõe a sua arquitetura, a classe Entidade a classe UtilFramework e a classe ContextLoaderListenerCaixakiUtils.

A classe Entidade

Crie o pacote br.com.project.model.classes e iremos adicionar a classe dentro do mesmo, esta classe será responsável por persistir dados de pessoas, usuários ou sendo será a classe de modelo de negocio quando se refere a uma pessoa dentro do sistema.

package br.com.project.model.classes;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.hibernate.envers.Audited;

@Audited
@Entity
@Table(name = "entidade")
@SequenceGenerator(name = "entidade_seq", sequenceName = "entidade_seq", initialValue = 1, allocationSize = 1)
public class Entidade implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "entidade_seq")
	private Long ent_codigo;

	@Column(length = 100)
	private String ent_nomefantasia;

	public Long getEnt_codigo() {
		return ent_codigo;
	}

	public void setEnt_codigo(Long ent_codigo) {
		this.ent_codigo = ent_codigo;
	}

	public String getEnt_nomefantasia() {
		return ent_nomefantasia;
	}

	public void setEnt_nomefantasia(String ent_nomefantasia) {
		this.ent_nomefantasia = ent_nomefantasia;
	}

}

Estrutura do projeto

entiade_post_2

Mapeando a classe Entidade no Hibernate

<mapping class="br.com.project.model.classes.Entidade" />

A classe UtilFramework

Essa classe será responsável por trazer o nosso usuário logado para o Hibernate envers. Crie o pacote br.com.framework.utils e adicione a classe UtilFramework.

package br.com.framework.utils;

import java.io.Serializable;

import org.springframework.stereotype.Component;

@Component
public class UtilFramework implements Serializable {

	private static final long serialVersionUID = 1L;

	private static ThreadLocal<Long> threadLocal = new ThreadLocal<Long>();

	public synchronized static ThreadLocal<Long> getThreadLocal() {
		return threadLocal;
	}

}

Ficando com a seguinte estrutura

util_post_2

A classe ContextLoaderListenerCaixakiUtils

Está classe extends de ContextLoaderListener do Spring Framework com isso podemos obter todos os objetos do contexto do Spring dentro de nossa aplicação.
Crie o seguinte pacote br.com.project.listener e adicione a a classe ContextLoaderListenerCaixakiUtils.

package br.com.project.listener;

import java.io.Serializable;

import javax.faces.bean.ApplicationScoped;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

@ApplicationScoped
public class ContextLoaderListenerCaixakiUtils extends
		org.springframework.web.context.ContextLoaderListener implements Serializable {
	
	private static final long serialVersionUID = 1L;

	private static WebApplicationContext getWac() {
		return WebApplicationContextUtils
				.getWebApplicationContext(getCurrentWebApplicationContext().getServletContext());
	}
	
	public static Object getBean(String idNomeBean) {
		return getWac().getBean(idNomeBean);
	}
	
	public static Object getBean(Class<?> classe) {
		return getWac().getBean(classe);
	}

}

Ficando com a seguinte estrutura.
context_loader_listener_post_2

Crie o seguinte pacote br.com.project.filter que receberá o nosso filter.

package br.com.project.filter;

import java.io.IOException;
import java.io.Serializable;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
import org.hibernate.SessionFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.filter.DelegatingFilterProxy;

import br.com.framework.hibernate.session.HibernateUtil;
import br.com.framework.utils.UtilFramework;
import br.com.project.listener.ContextLoaderListenerCaixakiUtils;
import br.com.project.model.classes.Entidade;

@SuppressWarnings("unused")
@WebFilter(filterName = "conexaoFilter")
public class FilterOpenSessionInView extends DelegatingFilterProxy implements
		Serializable {

	private static final long serialVersionUID = 1L;
	private static SessionFactory sf;

	@Override
	public void initFilterBean() throws ServletException {
		sf = HibernateUtil.getSessionFactory();
	}

	@Override
	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain chain)
			throws IOException, ServletException {

		BasicDataSource springDataSource = (BasicDataSource) ContextLoaderListenerCaixakiUtils.getBean("springDataSource");
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		PlatformTransactionManager transactionManager = new DataSourceTransactionManager(springDataSource);
		TransactionStatus status = transactionManager.getTransaction(def);

		try {

			servletRequest.setCharacterEncoding("UTF-8");

			HttpServletRequest request = (HttpServletRequest) servletRequest;
			HttpServletResponse response = (HttpServletResponse) servletResponse;
			HttpSession sessao = request.getSession();
			Entidade userLogadoSessao = (Entidade) sessao.getAttribute("userLogadoSessao");

			if (userLogadoSessao != null) {
				UtilFramework.getThreadLocal().set(userLogadoSessao.getEnt_codigo());
			}

			sf.getCurrentSession().beginTransaction();
			chain.doFilter(servletRequest, servletResponse);

			transactionManager.commit(status);

			if (sf.getCurrentSession().getTransaction().isActive()) {
				sf.getCurrentSession().flush();
				sf.getCurrentSession().getTransaction().commit();
			}

			if (sf.getCurrentSession().isOpen()) {
				sf.getCurrentSession().close();
			}

			servletResponse.setCharacterEncoding("UTF-8");
			servletResponse.setContentType("text/html; charset=UTF-8");

		} catch (Exception e) {

			transactionManager.rollback(status);

			e.printStackTrace();

			if (sf.getCurrentSession().getTransaction().isActive()) {
				sf.getCurrentSession().getTransaction().rollback();
			}
			if (sf.getCurrentSession().isOpen()) {
				sf.getCurrentSession().close();
			}
		} finally {
			if (sf.getCurrentSession().isOpen()) {
				if (sf.getCurrentSession().beginTransaction().isActive()) {
					sf.getCurrentSession().flush();
					sf.getCurrentSession().clear();
				}
				if (sf.getCurrentSession().isOpen()) {
					sf.getCurrentSession().close();
				}
			}

		}
	}
}

Continuando a configuração do web.xml, declaração do filter open session in view.

<filter>
		<filter-name>conexaoFilter</filter-name>
		<filter-class>br.com.project.filter.FilterOpenSessionInView</filter-class>
</filter>

Declaração do filter do SpringSecurity.

<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Declaração da codificação de caracteres para o filter do Spring.

<filter>
		<filter-name>encoding-filter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>ISO-8859-1</param-value>
		</init-param>
</filter>

Declaração do filter para Upload de arquivos em PrimeFaces

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

Declaração do mapeamento do filter de codificação de caracteres

<filter-mapping>
		<filter-name>encoding-filter</filter-name>
		<url-pattern>/*</url-pattern>
</filter-mapping>

Declaração do mapeamento do nosso filer open session in view

<filter-mapping>
		<filter-name>conexaoFilter</filter-name>
		<url-pattern>/*</url-pattern>
</filter-mapping>

Declaração do mapeamento do filtro do Spring Security

<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
</filter-mapping>

Declaração do mapeamento do filter para upload de arquivos com PrimeFaces

<filter-mapping>
		<filter-name>PrimeFaces FileUpload Filter</filter-name>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.jsf</url-pattern>
</filter-mapping>

Declaração do listener ContextLoaderListenerCaixakiUtils

<listener>
		<listener-class>br.com.project.listener.ContextLoaderListenerCaixakiUtils</listener-class>
</listener>

Declaração do RequestContextListener do Spring

<listener>
		<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

A classe InformacaoRevisao do Hibernate Envers

Essa classe é responsável por armazenar a sequencia de operações na base de dados e qual usuários as efetuou. Crie a classe com o nome InformacaoRevisao e adicione pacote br.com.project.model.classes.

package br.com.project.model.classes;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.envers.DefaultRevisionEntity;
import org.hibernate.envers.RevisionEntity;
import br.com.project.listener.CustomListener;

@Entity
@Table(name = "revinfo")
@RevisionEntity(CustomListener.class)
public class InformacaoRevisao extends DefaultRevisionEntity implements
		Serializable {

	private static final long serialVersionUID = 1L;

	@ManyToOne
	@ForeignKey(name = "entidade_fk")
	@JoinColumn(nullable = false, name = "entidade")
	private Entidade entidade;

	public Entidade getEntidade() {
		return entidade;
	}

	public void setEntidade(Entidade entidade) {
		this.entidade = entidade;
	}

}

O CustomListener do Hibernate Envers

Esse listener será o responsável por ativar o Hibernate envers responsável pelo log de resgistro da nossa aplicação.
Dentro do pacote br.com.project.listener que criamos anteriormente adicione a classe CustomListener.

 package br.com.project.listener;

import java.io.Serializable;

import org.hibernate.envers.RevisionListener;
import org.springframework.stereotype.Service;

import br.com.framework.utils.UtilFramework;
import br.com.project.model.classes.Entidade;
import br.com.project.model.classes.InformacaoRevisao;


@Service
public class CustomListener implements RevisionListener, Serializable {
	private static final long serialVersionUID = 1L;

	@Override
	public void newRevision(Object revisionEntity) {
			InformacaoRevisao informacaoRevisao = (InformacaoRevisao) revisionEntity;

			Long codUser = UtilFramework.getThreadLocal().get();
			Entidade user = new Entidade();
			if (codUser != null && codUser != 0L) {
				user.setEnt_codigo(codUser);
				informacaoRevisao.setEntidade(user);
			}
	}

}

Declaração do listener do Hibernate Envers no web.xml

<listener>
	<listener-class>br.com.project.listener.CustomListener</listener-class>
</listener>

Declaração do listener HttpSessionEventPublisher do Spring para concorrência entre sessões de usuários da aplicação.

<listener>
		<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

Declaração da nossa fonte de dado e do nosso datasource de conexão com o banco de dados.

<resource-ref>
		<description>DataSource datasouce</description>
		<res-ref-name>jdbc/datasouce</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
</resource-ref>

Declaração do DispatcherServlet do Spring para permitir o nosso projeto gerenciar nossas sevlets.

<servlet>
		<servlet-name>spring-servlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
</servlet>

Declaração do mapeamento do DispatcherServlet do Spring.

<servlet-mapping>
		<servlet-name>spring-servlet</servlet-name>
		<url-pattern>/</url-pattern>
</servlet-mapping>

Declaração do FacesServlet do JSF.

<servlet>
	<servlet-name>Faces Servlet</servlet-name>
	<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
	]<load-on-startup>1</load-on-startup>
</servlet>

Declaração do mapeamento do FacesServlet do JSF.

<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.jsf</url-pattern>
</servlet-mapping>

Galera chegamos ao fim do segundo post do desenvolvimento do projeto JavaEE completo espero que tenham gostado.
No próximo post vamos ver as configurações do Spring Security.
Abraços e bons estudos.

Comprar Projeto R$ 22,99


compra-segura


Anterior

Próximo


Acesse
Cursos e Projetos
Java
Acesse
Outros Cursos
PHP MySQL Android
Acesse
Encomende um Projeto
Feito pra Você
Acesse
Tire as Dúvidas On-line
Consultor
Acesse
Aulas de Java só suas
Encomende Agora
Acesse
Dividindo Conhecimento
Posts e Tutoriais
Acesse
Sites e Parceiros
Associados
Acesse
Menu Inicial
Home Page

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Instrutor Java Quer se tornar aluno VIP? CLIQUE AQUI!
Instrutor Java Alex Fernando Egidio
Autor, criador e fundador do Java Avançado Cursos TI. Atua no mercado como desenvolvedor e engenheiro de sistemas em Java é apaixonado por desenvolvimento web em Java e pela “mágica” que seus frameworks trazem para o dia a dia de nós desenvolvedores.
Com mais de 10 anos de experiência ajuda programadores do Brasil todo a se tornarem profissionais.