Como criar um componente com JSF e PostgreSQL
Veja nesse artigo como criar um componente utilizando o JSF (JavaServer Faces), um framework Java que segue o padrão MVC (Model – View – Controller), utilizando banco de dados PostgreSQL.
Com a crescente demanda no uso de aplicativos em quaisquer dispositivos que contenham recursos necessários para o uso de internet e o surgimento de novas tecnologias, vem aumentando repentinamente e a busca por novas soluções, permitindo uma proposta inovadora para a criação própria de ferramentas que facilitam e agilizam as aplicações web.
Apresentando um conceito inicial, Java é uma linguagem de programação que possui inúmeros recursos por ser multiplataforma: independente de arquitetura e sistema operacional e também possui características como portabilidade, orientação a objetos, além de ser concisa e simples.
Ao ser compilada, a linguagem Java gera um bytecode que consiste num resultado de comunicação, em tempo de execução, entre o sistema operacional e o lado cliente a ser executado para o usuário.
Para criar componentes utilizando JSF, é necessário um ambiente de desenvolvimento capaz de interpretar a linguagem Java, além de fazer a comunicação com o HTML, com o servidor web, com o JDBC (conector para a fonte de dados) e por fim com o banco de dados, tudo isso no formato para a web. Existem inúmeros ambientes de desenvolvimentos, mas recomendamos o NetBeans IDE que se encontra na versão 8.0.1.
Já na parte de banco de dados, há o PostgreSQL que é um banco de dados robusto e possui características simples e sua manipulação é de maneira muito facilitada. Poderíamos escolher qualquer outro banco de dados para ilustrar este artigo, mas o PostgreSQL é muito rápido quando trata das transações de dados. Além disso, o NetBeans IDE já tem em suas opções uma para anexar a biblioteca JDBC própria e pronta para o projeto a ser desenvolvido.
Primeiros Passos para a Criação do Projeto Web
Feito o download do ambiente de desenvolvimento e do gerenciador do banco de dados e ter instalado ambos, agora podemos iniciar a criação de um componente JSF. Após ter aberto o NetBeans IDE, é necessário ir na barra de menus → Arquivo → Novo Projeto. Vai aparecer uma janela de opções, como a demonstrada na Figura 1.
Após isso, clicar em Próximo e logo aparecerá uma janela para colocar o nome do projeto (que pode ser Componentes) e o local do mesmo (que pode ser num local seguro e de qualquer preferência) como ilustra a Figura 2.
Feito isso, e ter clicado em Próximo, vai aparecer uma janela para definir qual o servidor web que rodará a aplicação. Por preferência, a escolha é do Apache Tomcat (embora o GlassFish Server também seja muito bom) e a versão do Java EE web é a 7. O caminho do contexto deixa do jeito que foi criado automaticamente, como mostra a Figura 3.
E finalmente, após ter clicado em próximo, aparecerá a última janela de escolha de configuração: por se tratar de JSF, seleciona-se a opção JavaServer Faces e por fim clique em Finalizar, como mostra a Figura 4.
Projeto criado então agora o próximo passo é colocar em prática a idéia de como será criado o componente e onde será utilizado.
Como a linguagem Java possui recursos de JDBC suficientemente para conectar com o banco de dados, como já havia dito, o PostgreSQL será necessário para a armazenagem de dados onde a aplicação será encarregada de ter uma parte responsável de obter tais dados e mostrar para o usuário.
Adicionando Driver JDBC ao Projeto
Para adicionar o driver JDBC para o projeto, é só clicar com o botão direito em Bibliotecas, navegar até a opção Bibliotecas Disponíveis, selecionar Driver JDBC do PostgreSQL e finalmente clicar em Adicionar Biblioteca, como mostra a Figura 5.
Inicialmente, ao dar os primeiros passos com a implementação, é necessário criar uma tabela no PostgreSQL com o nome de estados,cujo princípio é ter um conjunto de dados já armazenados que possam facilitar na hora de chamar os mesmos durante a execução do projeto.
Configurando PostgreSQL
Com o PostgreSQL já instalado, agora temos que criar um banco de dados internamente,e para isso é preciso iniciar o gerenciador, que no caso é pgAdmin. Dê dois cliques em cima de PostgreSQL X.Y (onde X.Y é a versão atual instalada, provavelmente são dois números), clique com o botão direito em: Databases e depois em New Database, ou vá à barra de menu superior e selecione a opção Edit e clicar em Create. Em seguida aparecerá a seguinte tela da Figura 6.
Colocado um nome, é só clicar em OK. Para conectar, basta dar duplo clique em cima do banco de dados criado e para adicionar a tabela que será com o nome de uf, clique no botão SQL (Execute arbitrary SQL queries), como mostra na Figura 7logo abaixo.
Agora é hora de criar de fato a tabela uf e para isso, coloque o seguinte código descrito na Listagem 1 e logo após apertar a tecla F5 e a tabela será criada.
CREATE TABLE uf
(
uf_codigo integer NOT NULL,
uf_nome character varying(20) NOT NULL,
uf_sigla character varying(2) NOT NULL,
CONSTRAINT uf_pkey PRIMARY KEY (uf_codigo)
)
WITH (
OIDS=FALSE
);
ALTER TABLE uf
OWNER TO postgres;
CREATE INDEX uf_uf_codigo_idx
ON uf
USING btree
(uf_codigo);
Após ter executado e não ter dado erro, agora temos que cadastrar alguns estados e, para isso, basta colocar esse conjunto de comandos descritos na Listagem 2 e executar que os estados ficarão armazenados.
insert into uf (uf_codigo, uf_nome, uf_sigla) values (1,'Acre','AC');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (2,'Alagoas','AL');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (3,'Amazonas','AM');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (4,'Amapá','AP');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (5,'Bahia','BA');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (6,'Ceará','CE');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (7,'Distrito Federal','DF');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (8,'Espirito Santo','ES');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (9,'Goiás','GO');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (10,'Maranhão','MA');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (11,'Minas Gerais','MG');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (12,'Mato Grosso do Sul','MS');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (13,'Mato Grosso','MT');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (14,'Pará','PA');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (15,'Paraiba','PB');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (16,'Pernambuco','PE');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (17,'Piauí','PI');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (18,'Paraná','PR');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (19,'Rio de Janeiro','RJ');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (20,'Rio Grande do Norte','RN');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (21,'Rondonia','RO');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (22,'Roraima','RR');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (23,'Rio Grande do Sul','RS');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (24,'Santa Catarina','SC');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (25,'Sergipe','SE');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (26,'São Paulo','SP');
insert into uf (uf_codigo, uf_nome, uf_sigla) values (27,'Tocantins','TO');
Feito isso, é só fechar a janela do SQL (pode ser sem salvar mesmo), que agora temos que dar continuidade a criação do componente. Mas para isso é preciso ter em mente que antes haverá uma caixa de seleções de itens (selectItems) via HTML para buscar todos os estados cadastrados que estão dentro do banco de dados. E isso se transformará em um componente.
Criação de um Novo Projeto Java Auxiliar
Para que tenha uma comunicação com o banco de dados, é recomendado criar uma Nova Aplicação Java que contenha todos esses requisitos. O nome pode ser DAO (que costumeiramente se usa para dizer que é uma camada intermediária entre a aplicação e o acesso a dados). Após isso é preciso criar três pacotes: um para conexão com o banco de dados, o segundo para encapsular dados e o terceiro para executar comandos de SQL e tratar possíveis erros. Por fim, dentro de cada pacote, as seguintes classes deverão estar conforme demonstra aFigura 8.
Agora, é necessário implementar dentro do arquivo Conexao.java, o seguinte código da Listagem 3, pois o mesmo ficará responsável por conectar com o banco de dados.
package conexao;
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class Conexao {
private static final String usuario = "postgres";
//usuário do banco de dados
private static final String senha = "postgres123";
//senha do banco de dados
private static final String url = "jdbc:postgresql:
//127.0.0.1:5432/postgres"; //driver
public static Connection open() { //abrir conexão
try {
Class.forName("org.postgresql.Driver");
return DriverManager.getConnection(url, usuario, senha);
} catch (SQLException | ClassNotFoundException ex) {
Logger.getLogger(Conexao.class.getName())
.log(Level.SEVERE, null, ex);
return null;
}
}
public static void close(ResultSet rs, Statement st,
Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
} // fechar conexão
public static void close(Statement st, Connection conn) {
close(null, st, conn);
}
public static void close(Connection conn) {
close(null, null, conn);
}
}
Dentro do arquivo DAO.java é necessário programar uma interface e para isso utilizaremos o código descrito na Listagem 4.
package dao;
import java.util.List;
public interface DAO<T> {
/**
* Recupera um registro de uma tabela, baseado na sua chave primária
*
* @param chave a chave primária
* @return o registro correspondente, ou
* <code>null</code> se nada for encontrado
*/
public T getSingle(Object... chave);
/**
* Recupera uma lista de registros
*
* @return a lista de registros, ou
* <code>null</code> se nada for encontrado
*/
public List<T> getList();
/**
* Recupera uma lista de registros, o tamanho da lista é limitado pelo
* parâmetro
*
* @param top o número máximo de registros selecionados
* @return a lista de registros, ou
* <code>null</code> se nada for encontrado
*/
public List<T> getList(int top);
}
Dentro do arquivo DAOException.java teremos o tratamento de erros e utilizaremos o seguinte código da Listagem 5.
package dao;
public class DAOException extends Exception {
public DAOException(Throwable cause) {
super(cause);
}
public DAOException(String message, Throwable cause) {
super(message, cause);
}
public DAOException(String message) {
super(message);
}
public DAOException() {
super();
}
}
Agora vamos precisar de uma entidade para fazer a busca de dados, então é necessário programar dentro do arquivo UfDAO.java, o seguinte código descrito na Listagem 6.
package dao;
import daoentidades.UF;
import conexao.Conexao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class UfDAO
implements DAO<UF> {
@Override
public UF getSingle(Object... chave) {
if (chave[0] instanceof Integer) {
Connection conn = Conexao.open();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement("select uf_codigo,
uf_nome, uf_sigla from uf where uf_codigo = ?");
ps.setInt(1, (Integer) chave[0]);
rs = ps.executeQuery();
if (rs.next()) {
return new UF(rs.getInt("uf_codigo"),
rs.getString("uf_nome"), rs.getString("uf_sigla"));
}
} catch (SQLException ex) {
} finally {
Conexao.close(rs, ps, conn);
}
}
return null;
}
@Override
public List<UF> getList() {
return getList(0);
}
@Override
public List<UF> getList(int top) {
if (top < 0) {
return null;
}
List<UF> lista = null;
Connection conn = Conexao.open();
Statement ps = null;
ResultSet rs = null;
try {
ps = conn.createStatement();
rs = ps.executeQuery("select " + (top > 0 ?
"top " + top : "") + "uf_codigo, uf_nome, uf_sigla from uf");
lista = new ArrayList<>();
while (rs.next()) {
lista.add(new UF(rs.getInt("uf_codigo"),
rs.getString("uf_nome"), rs.getString("uf_sigla")));
}
} catch (SQLException ex) {
} finally {
Conexao.close(rs, ps, conn);
}
return lista;
}
}
E por fim é preciso programar uma camada de negócio responsável por receber e enviar as informações, ficando assim dentro do arquivo UF.java, descrito na Listagem 7.
package daoentidades;
import java.io.Serializable;
import java.util.Objects;
public class UF
implements Serializable {
private Integer codigo;
private String nome;
private String sigla;
public UF() {
codigo = null;
nome = null;
sigla = null;
}
public UF(Integer codigo, String nome, String sigla) {
this.codigo = codigo;
this.nome = nome;
this.sigla = sigla;
}
public Integer getCodigo() {
return codigo;
}
public void setCodigo(Integer codigo) {
this.codigo = codigo;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getSigla() {
return sigla;
}
public void setSigla(String sigla) {
this.sigla = sigla;
}
@Override
public int hashCode() {
int hash = 3;
hash = 47 * hash + Objects.hashCode(this.codigo);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UF other = (UF) obj;
return Objects.equals(this.codigo, other.codigo);
}
}
Adicionando o Projeto Java ao Projeto Java Web
Agora precisamos finalizar essa parte de acesso, manipulação e comunicação entre os dados e em como serão tratados daqui em diante. Para continuar com o projetoComponentes, o mesmo tem que estar aberto no Netbeans IDE e a aplicação Java DAO, que foi criada anteriormente, deve ser adicionada como parte de uma biblioteca dentro da aplicação web. Para isso, tem que fazer o mesmo que foi feito quando adicionou-se o driver JDBC, só que ao invés de adicionar uma biblioteca, tem que escolher a opção de Adicionar um Projeto, conforme mostra na Figura 9 abaixo.
Criação de Classes Auxiliares
Seguindo a Figura 9, surge a proposta de criar um pacote chamado Estados dentro do Pacote de Códigos-Fonte. Para isso, cria-se uma classe com o nome de ListaDeEstados.java cuja funcionalidade é armazenar todos os valores obtidos num Array List, de acordo com o seguinte código descrito na Listagem 8.
package Estados;
import dao.UfDAO;
import daoentidades.UF;
import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UISelectOne;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ValueChangeListener;
@ManagedBean
@ViewScoped
public final class ListaDeEstados implements Serializable, ValueChangeListener {
private final List<UF> estadosCadastrados;
public ListaDeEstados() {
UfDAO dao = new UfDAO();
estadosCadastrados = dao.getList();
}
@Override
public void processValueChange(ValueChangeEvent vce)
throws AbortProcessingException {
escolheuEstado(vce);
}
public void escolheuEstado(ValueChangeEvent evt) {
UF estado = (UF) evt.getNewValue();
}
public void selecionaEstado(AjaxBehaviorEvent event) {
UF estado = (UF)((UISelectOne)event.getComponent()).getValue();
}
public List<UF> getEstadosCadastrados() {
return estadosCadastrados;
}
}
Após isso, só é preciso criar mais uma classe, agora com o nome de UFConverter.java, de acordo com a Listagem 9.
package Estados;
import dao.UfDAO;
import daoentidades.UF;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;
@FacesConverter("UFConverter")
public class UFConverter implements Converter {
@Override
public Object getAsObject(FacesContext fc,
UIComponent uic, String string) {
if (string != null) {
try {
int codigo = Integer.parseInt(string);
UF estado = (new UfDAO()).getSingle(codigo);
return estado;
} catch (NumberFormatException ex) {
throw new ConverterException(
new FacesMessage("Erro convertendo UF!"));
}
}
return null;
}
@Override
public String getAsString(FacesContext fc,
UIComponent uic, Object objeto) {
if (objeto == null) {
return "";
}
final UF uf = (UF) objeto;
if (uf.getCodigo() == null) {
return null;
}
return uf.getCodigo().toString();
}
}
Criando Arquivo Componente
Finalizando essa parte de criação de classes, agora é a hora tão esperada que consiste na criação do componente JSF. Para isso, com base na Figura 9, clique com o botão direito em Páginas Web → Novo → Outros e depois selecione JavaServer Faces. Por fim, selecione Componente Composto do JSF. Clicando em próximo, vai aparecer a seguinte tela da Figura 10.
Agora a página de criação de componente está pronta para ser programada. Como a ideia inicial é buscar todos os estados cadastrados, então com o código descrito na Listagem 10 dentro do arquivo componente criado estado.xhtml, já é suficiente para que traga os dados esperados.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<cc:interface>
<cc:attribute name="valor" required="true"/>
</cc:interface>
<cc:implementation>
<h:outputLabel for="selEstado"><br/>Estados</h:outputLabel>
<h:selectOneMenu id="selEstado" immediate="true"
value="#{cc.attrs.valor}"
required="true" requiredMessage="Escolha um estado!">
<f:converter converterId="UFConverter"/>
<f:selectItem itemLabel="-- Selecione um --"
itemValue="#"/>
<f:selectItems value="#{listaDeEstados.estadosCadastrados}"
var="uf"
itemLabel="#{uf.nome}"
itemValue="#"
/>
</h:selectOneMenu>
</cc:implementation>
</html>
Chamando Componente para Página Principal
Finalmente, após ter feito a implementação da página de componente, agora a proposta é chamar o componente para a página inicial. Ao criar uma aplicação Java web, sempre é vindo automaticamente um arquivo denominado index.xhtml, que é onde tudo se inicia, pois todas as páginas devidamente configuradas e ligadas a ela serão seguidas através dessa página. Ficará da mesma forma que o código da Listagem 11o index.xhtml.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ex="http://xmlns.jcp.org/jsf/composite/ex">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form prependId="false">
Hello from Facelets
<ex:estado valor=""/>
</h:form>
</h:body>
</html>
Para concluir com o projeto, é necessário salvar todos os arquivos, mas o recomendado é ir salvando arquivo por arquivo.
Agora é só executar o projeto (pode ser usando a tecla F6) e se rodar no Google Chrome, ficará de acordo com a Figura 11.
Lembrando que funciona na maioria dos navegadores existentes, mas o Mozilla Firefox é browser padrão do Netbeans IDE.
Para a criação de componentes JSF é preciso já ter um conhecimento básico/intermediário sobre a linguagem Java e HTML e principalmente na área de orientação a objetos. Qualquer passo ou procedimento não executado ou caso tenha se esquecido de programar qualquer passo descrito, você pode usar o código-fonte disponível pra download nesse post.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Vídeo