Apostila Java Level 2 - Versão 2.1.1
Apostila Java Level 2 - Versão 2.1.1
11-4427-4579
11-9903-3218
Sobre o autor
,
Cientista da Computacão pelo IMES-SCS,
,
Especialista em Telecomunicacões pela
FAAP-SP, mestrando em ciência da
,
computacão pela UFAbc-sp.
1
Preparation
Presentation
Teoria Introducão
, ao java ee
O curso Java Level 2 é focado nas aplicações Java para a Web, mais
precisamente nas aplicações que se utilizam do Container Web do Servidor JavaEE.
Não se preocupe com os termos, pois eles serão abordados com a devida
profundidade nos capítulos subsequentes.
Pré-requisitos
A proposta para o Treinamento Java Level 2 supõe que o aluno tenha cursado
previamente, ou possua conhecimento equivalente, ao seguinte conteúdo, todos
oferecidos pela Grande Porte como cursos independentes:
1
Lógica de Programação;
HTML e;
Java - Level 1.
É importante frisar que não haverá tempo hábil para esclarecimento de dúvidas
relacionadas à linguagem, orientação a objetos ou mesmo relativas à composição de
blocos essenciais de código, como laços de repetição e desvios condicionais. Dessa
forma, caso o aluno conclua que já possua o conhecimento por meios equivalentes,
fica a dica para relembrar e recuperar tais conceitos, pois serão primordiais no
desenrolar das aulas.
Procure ler a teoria constante da apostila ANTES da aula - Dessa forma, o que
será dito não será completamente desconhecido pelo aluno e ele poderá
inclusive já vir com perguntas formuladas sobre a matéria;
Procure resolver TODOS os exercícios. Eles são feitos de forma a consolidar
conceitos e, por que não afirmar: é a única forma de aprender a lidar com
erros!
Arrisque, teste novas maneiras de chegar ao mesmo ponto. O desenvolvimento
de software e criação de código é algo potencialmente técnico e pessoal e o
resultado da implementação feita por um desenvolvedor pode não ser claro
para outros profissionais, por mais que existam regras de boas práticas e
convenções. A única forma de compreender código alheio é testando soluções
semelhantes e procurando entender padrões conhecidos no meio Java;
Os Apêndices contém informação valiosa e terão suas leituras indicadas
durante o curso, pelo professor, nos momentos em que tal conhecimento será
utilizado. Quando receber a indicação, LEIA TODO O CONTEÚDO DOS
APÊNDICES no momento descrito, para poder aproveitar a oportunidade de
esclarecer dúvidas e agregar novas técnicas;
No momento da montagem do ambiente e compreensão dos passos de
configuração em sala de aula, observe atentamente as medidas do professor e
procure montar um ambiente parecido em casa ou em seu computador
particular. Tenha sempre em mãos um ambiente pronto para que novas ideias
sejam testadas de imediato;
Tome notas - seja com uma caneta ou em um aplicativo gráfico - anote o que
puder e sempre que possível. Quanto mais experiências forem anotadas,
menor a probabilidade de erros futuros.
E, por fim,
Divirta-se! Criar aplicativos com Java é divertido e prazeroso. Ouse com novas
soluções e arrisque-se! O resultado só pode ser positivo!
Para efeitos didáticos, a seguinte distribuição pode ser feita nas versões da
plataforma Java, conforme suas clássicas aplicações:
São elas:
J2EE: termo que refere-se ao nome descritivo Java Enterprise Edition. É sem
dúvida o maior ramo da plataforma Java e engloba as tecnologias Web e
Enterprise (Sistemas Distribuídos). baseia-se na versão J2SE e acrescenta
uma grande quantidade de APIs específicas ao seu propósito. É o foco deste
curso.
J2ME: termo que refere-se ao nome descritivo Java Micro Edition. É a menor
versão das divisões da plataforma Java e abrange todas as APIs utilizadas em
dispositivos móveis e embarcados, como celulares, tablets e equipamentos
dedicados como controladores e robôs. Parte de sua arquitetura baseia-se na
JVM como todas as outras versões porém abrange algumas tecnologias não
baseadas na Java Virtual Machine como MIDP e CLDC.
Servlet;
Java Server Faces (JSF);
Java Server Pages (JSP);
EL (Expression Language);
Java Persistence (JPA);
Java Message Service (JMS);
Web Services (JAX-WS, JAX-RS);
BeanValidation;
EJB;
EJB Lite;
JavaMail;
1
Interceptors;
As aplicações web em geral tem algumas necessidades para que possam ser
implementadas, seja qual for a tecnologia utilizada. Essas dependências podem variar
conforme a plataforma de desenvolvimento mas, em geral, algumas são comuns. A
existência de um servidor de aplicações é uma realidade que permeia todas as
tecnologias de desenvolvimento web. Um servidor de aplicações trabalha
conjuntamente com um servidor web (Servidor HTTP) para responder a requisições de
usuários e clientes.Veja um exemplo esquemático abaixo.
1
existentes para a plataforma java, segue uma lista dos mais utilizados:
Full Profile:
Web Profile:
As formas mais comuns de se realizar tal tarefa são por meio de sessões e
cookies, mas não se preocupe. Esses conceitos serão vistos mais à frente.
Inicialmente, a solicitação por uma página ou clique feito pelo usuário em uma
página web já aberta, gera uma requisição a um servidor web que possui o seguinte
formato simplificado, para o método GET:
Host: www.exemplo.com.br
HTTP/1.1 200 OK
Etag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: bytes
Content-Length: 438
Connection: close
1
POST /index.html HTTP/1.1
Accept: text/html
Content-Type: application/x-www-form-urlencoded
Content-Length: 41
Nome=AlunoGrandePorte&Idade=23&Curso=JavaLevel2
GET: usado para solicitar algum recurso como uma página ou um componente
de servidor identificado por meio da URL. Utilizado para passar parâmetros via URL ao
servidor no formato exemplificativo:
http://www.exemplo.com.br/teste?Nome=AlunoGrandePorte&Idade=23&C
urso=JavaLevel2
HEAD: Variação do GET usado para obter metadados, informações por meio
do header da resposta, sem necessidade de recuperar o conteúdo de retorno.
Requisição:
Consistente
Resposta, passo 1:
1
Resposta, passo 2:
1
definidas: a Camada Cliente, a Camada Web, a Camada Business e a Camada EIS.
http://tomcat.apache.org/
1
o usuário é levado a uma nova página para a escolha de uma das formas de download
possíveis, como zip, tar.gz e versões específicas para o Sistema Operacional
Windows, conforme imagem abaixo:
1
configuração do Apache Tomcat.
Com o mouse no interior dessa view, clique com o botão direito e siga clicando
na sequência: New Server.
Como última etapa, dê dois cliques no servidor agora existente dentro da view
“Servers”. O eclipse apresentará na janela principal, uma página específica para
configuração do Apache Tomcat:
Na Seção Server Locations, clique no radio button do meio, o que diz: “Use
Tomcat installation (takes control of Tomcat installation)”;
Salve o arquivo.
Verifique no seu navegador que o servidor está rodando e pronto para aceitar
conexões, digitando a seguinte URL:
http://localhost:8080
<role rolename="tomcat"/>
<role rolename="role1"/>
</tomcat-users>
Vistas as regras, vamos editar esse arquivo para atribuir permissão de acesso
e privilégios para acesso ao servidor:
<role rolename="manager-gui"/>
</tomcat-users>
1
navegador e, novamente, clique no botão Manager App, inserindo em seguida as
credenciais que cadastrou no arquivo de configuração.
Practice
Performance
1
Estou fera!
Fiz Certo!
Preparation 2
Presentation
MySQL http://www.mysql.com;
PostgreSQL http://www.postgresql.org.br;
Firebird http://www.firebirdsql.org;
Sqlite http://www.sqlite.org.
Comerciais:
Tabela
Planilha de dados
CREATE TABLE
ALTER TABLE
DROP TABLE
CREATE VIEW
DROP VIEW
INSERT
UPDATE
SELECT
DELETE
2
Comumente, representamos um banco de dados pelo seu Diagrama
Entidade-Relacional (DER), também chamado de Modelo Entidade-Relacional
(MER). Para nossa compreensão, analisemos o MER abaixo, que também será
utilizado na Atividade 1 deste capítulo:
UM para UM 11
UM para MUITOS 1n
MUITOS para UM n1
MUITOS para MUITOS nn
JDBC
jdbc:mysql://<domínio>:<porta>/<nome do banco>
2
que foi feito no código e os conceitos envolvidos.
1. Carregar os drivers:
Class.forName("ClasseDriverJDBC");
2. Estabelecer conexões:
jdbc:mysql://<domínio>:<porta>/<nome do banco>
2
statement.executeUpdate("INSERT INTO aluno(nome, idade, curso)
VALUES (\"JOANA DARC\", 35, 1)");
5. Processando o ResultSet
1 import java.sql.*;
2
3 public class TesteJDBC {
4 public static void main (String [] args){
5 try {
6 String url = "jdbc:mysql://localhost:3306/grandeporte";
7 String user = <seu usuário>;
8 String password = <sua senha>;
9 Class.forName("com.mysql.jdbc.Driver");
10 Connection connection = DriverManager.getConnection(url, user,
11 password);
12 Statement statement = connection.createStatement();
13 String sql = "SELECT * FROM aluno";
14 ResultSet result = statement.executeQuery(sql);
15 while (result.next()){
16 System.out.println("ID: " + result.getString("idaluno") +
17 ", Nome: " + result.getString("nome") + ", Idade: " +
18 result.getString("idade") + ", Curso: " +
19 result.getString("curso"));
20 } //fim while
21 connection.close();
22 } catch (ClassNotFoundException e) {
23 e.printStackTrace();
24 } catch (SQLException e) {
25 e.printStackTrace();
26 }
27 }
Practice 2
Atividade Trabalho em dupla
Documentação.
2
idcurso INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
descricao VARCHAR(70) NOT NULL ,
professor INT NOT NULL ,
CONSTRAINT fk_curso_professor
FOREIGN KEY (professor)
REFERENCES professor(idprofessor)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
11. Faremos agora uma consulta nos dados cujas tabelas acabamos de
atualizar:
E o resultado...
12. Como tarefa final desta atividade, insira mais três registros em cada
tabela com os dados que você desejar. Faça um esboço abaixo dos dados
inseridos nas tabelas:
2
package com.grandeporte.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
}
}
Performance
UPDATE:
UPDATE aluno SET nome = “King Arthur” WHERE idade = 35;
DELETE:
DELETE FROM aluno WHERE idade >= 34;
Tabelas:
curso: professor:
2
aluno:
1 import java.sql.*;
2 import javax.swing.JOptionPane;
3 public class TestePreparedStatement {
4 public static void main (String [] args){
5 try {
6 //Configuração da conexão
7 String url = "jdbc:mysql://localhost:3306/grandeporte";
8 String user = "root";
9 String password = "RMP7838-";
10 Class.forName("com.mysql.jdbc.Driver");
11 Connection connection = DriverManager.getConnection(url, user,
12 password);
13
14 //Leitura dos parâmetros passados pelo usuário
15 String nome = JOptionPane.showInputDialog("Entre " +
16 com o nome do aluno para gravar no Banco de Dados: ");
17 String idade = JOptionPane.showInputDialog("Entre " +
Estou fera!
Fiz Certo!
Preparation
3
Trocando Ideias É agora que você fala !!
Presentation
Teoria servlet
A Classe HTTPServlet
3
Classes e Interfaces existentes em sua árvore de herança:
Método Descrição
doGet() Executado quando a requisição recebida é HTTP GET.
doPost() Executado quando a requisição recebida é HTTP POST.
doPut() Executado quando a requisição recebida é HTTP PUT.
doDelete() Executado quando a requisição recebida é HTTP DELETE.
doHead() Executado quando a requisição recebida é HTTP HEAD.
doTrace() Executado quando a requisição recebida é HTTP TRACE.
init() Método executado uma única vez quando o Servlet é inicializado
pelo Container.
service() Método usado para gerenciar por meio de uma única entrada, todas
as requisições recebidas, independentes de método HTTP.
Raramente deverá ser sobrescrito.
destroy() Chamado quando o Container inicia o processo de destruição do
Servlet. Após sua chamada, esse objeto é coletado pelo GC
(GarbageCollector).
Uma importante observação a ser feita e que deve estar constantemente sob
atenção do desenvolvedor é que o Container cria somente uma instância de cada
Servlet declarado. Para cada requisição é criada uma nova thread sobre a mesma
instância do Servlet. Logo, Servlets NÃO CONSTITUEM UM BOM LUGAR PARA SE
GUARDAR DADOS REFERENTES A USUÁRIOS EM PARTICULAR, DADA QUE A
INSTÂNCIA É COMPARTILHADA ENTRE AS REQUISIÇÕES. ALÉM DISSO NÃO HÁ
COMO SE OBTER UMA REFERÊNCIA DO SERVLET. SEU CONTROLE RESIDE NO
CONTAINER APENAS.
Ocorre que essa versão ainda hoje não é largamente aplicada nas empresas,
vigorando, por vezes em grande escala, as versões que se utilizam do Java EE 5 e,
nesse caso, o aluno deve conhecer o Deployment Descriptor com uma certa liberdade
pois, independente do porte da aplicação, esse arquivo estará, invariavelmente,
presente na raiz da aplicação.
<?xmlversion="1.0"encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.s
un.com/xml/ns/javaee/web-
app_2_5.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-
app_2_5.xsd"id="WebApp_ID"version="2.5">
<display-name>GrandePorteWebProject</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>GrandePorteServlet</display-name>
<servlet-name>GrandePorteServlet</servlet-name>
<servlet-class>br.com.grandeporte.servlet.GrandePorteServlet</servlet-
class>
</servlet>
<servlet-mapping>
<servlet-name>GrandePorteServlet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
</web-app>
<servlet>
3
<display-name>GrandePorteServlet</display-name>
<servlet-name>GrandePorteServlet</servlet-name>
<servlet-class>
br.com.grandeporte.servlet.GrandePorteServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GrandePorteServlet</servlet-name>
</servlet-mapping>
Tag Descrição
<servlet> Tag raiz que abre o bloco de declaração para cada Servlet da
aplicação
<servlet-name> Nome dado ao Servlet que serve somente para referenciá-lo no
próprio web.xml. Esse nome será usado como referência para o
Servlet na tag<servlet-mapping>
<servlet-class> Nome totalmente qualificado da classe que representa o respectivo
Servlet. Utiliza a mesma sintaxe que o utilizado para importar
classes em Java.
<servlet-mapping> Tag utilizada para mapear um determinado Servlet a um padrão de
URL, utilizando para tanto, a tag<servlet-name> que identifica o
servlet específico.
<url-pattern> Tag usada dentro da anterior para mapear um padrão de URL a ser
atendida por um determinado Servlet.
HttpServletRequest e HttpServletResponse.
A interface HttpServletRequest
Métodos Descrição
getAttribute(name:String):Object Retorna um Object que representa um atributo
gravado na Request.
getAttributeNames():Enumeration Retorna uma Enumeration com todos os nomes
dos atributos contidos na request.
setAttribute(name:String, Armazena um atributo na Request, recebendo seu
value:Object):void nome e valor.
removeAttribute(name:String):void Remove o atributo da Request cujo nome é
passado por parâmetro.
getParameter(name:String):String Retorna o valor String de um parâmetro cujo
nome seja o passado para o método, ou null.
getParameterMap():Map Retorna um mapa com todos os parâmetros dessa
request.
getParameterValues(name: Retorna um array de Strings contendo o valor de
String):String[] cada um dos parâmetros passados a essa Request,
ou null.
getParameterNames():Enumeration Retorna uma Enumeration de objetos String com
o nome de cada um dos parâmetros passados à
Request.
getMethod():String Retorna o nome do método HTTP usado para essa
requisição.
getHeader(name:String):String Retorna o valor em String do header especificado
por parâmetro
getCookies():Cookie[] Retorna um array com os objetos Cookie
provindos do cliente na Request.
getInputStream():InputStream Retorna um InputStream - os dados constantes do
corpo da Request como dados binários.
3
getRequestURL():StringBuffer Retorna a URL completa usada para realizar a
Request.
getServletPath():String Retorna a porção da URL usada para chamar o
Servlet
A interface HttpServletResponse
Métodos Descrição
setContentType(len:String):void Envia o MIME Type ao navegador do
solicitante de forma a alertá-lo sobre o tipo
de conteúdo sendo enviado.
getWriter():PrintWriter Retorna um objeto PrintWriter, um stream
pronto para enviar texto ao cliente.
getOutputStream(): Retorna um objeto ServletOutputStream, um
ServletOutputStream stream necessário para envio de dados
binários ao cliente
encodeURL(url:String):String Recebe uma URL e a retorna codificada com
o ID da sessão, se necessário.
sendRedirect(location:String):void Redireciona a response para o cliente,
encaminhando-o para a URL passada.
addCookie(cookie:Cookie):void Adiciona um cookie na Response do cliente.
addHeader(name:String, Adiciona um header na Response com o
value:String):void nome e valor especificados.
containsHeader(name:String): Verifica se existe na Response um header
boolean com o nome passado e retorna um boolean.
sendError(sc:int [, msg:String]):void Envia um erro para a Response com o status
especificado.
setStatus(sc:int):void Define o código de Status para essa
Response.
Por vezes, pode ser necessário apenas encaminhar o usuário a uma outra URL,
absoluta ou relativa, que aponte para um endereço em nossa própria aplicação ou
mesmo em outro servidor. Esse tipo de comunicação é chamado de Redirecionamento
ou Redirect e não preserva os dados passados por parâmetro na Request.
dispatcher.forward(request, response);
3
Forma de se realizar um Redirect:
response.sendRedirect("http://www.google.com.br");
No Deployment Descriptor:
<servlet>
<servlet-name>GrandePorteServlet</servlet-name>
<servlet-class>
br.com.grandeporte.servlet.GrandePorteServlet2
</servlet-class>
<init-param>
<param-name>email</param-name>
<param-value>[email protected]</param-value>
</init-param>
</servlet>
Os init-params dos Servlets são lidos somente uma única vez durante a
inicialização do Servlet e depois não mais. Ficam disponíveis única e exclusivamente
aos Servlets que os possuem.
<servlet>
<servlet-name>GrandePorteServlet</servlet-name>
<servlet-class>
br.com.grandeporte.servlet.GrandePorteServlet2
</servlet-class>
</servlet>
<context-param>
<param-name>email</param-name>
<param-value>[email protected]</param-value>
</context-param>
No Deployment Descriptor:
Atributos e Listeners
Atributos
Nas Atividades que fizemos até o momento não precisamos passar nenhum
valor entre diferentes componente de nossa aplicação pois utilizamos apenas Servlets
3
simples e, na maior parte das vezes, único.
Atributos Parâmetros
Tipos Application/context Application/contextinit
Request Request
Session Servletinit
Método setter setAttribute(Stringname, Somente via DD!
Objectvalue)
Tipo de Retorno Object String
Método getter getAttribute(Stringname) getInitParameter(Stringname)
Context/
Request Session Application
getAttribute(String)
setAtribute(String, Object)
removeAttribute(String)
getAttributeNames()
Listeners
javax.servlet.ServletContextAttributeListener;
javax.servlet.http.HttpSessionListener;
javax.servlet.ServletRequestListener;
javax.servlet.ServletRequestAttributeListener;
javax.servlet.http.HttpSessionBindingListener;
javax.servlet.http.HttpSessionAttributeListener;
javax.servlet.ServletContextListener;
javax.servlet.http.HttpSessionActivationListener;
1) O Listener:
2) Um Servlet:
3
IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD><TITLE>Testando listeners!</TITLE>" +
"</HEAD>");
out.println("<BODY>");
out.println("<h1>Grande Porte - Java Level 2</h1>");
out.println("<hr><br /><br>");
out.println("<h4>Veja no console do Servidor se o " +
"listenerouviuessa Request</h4>");
out.println("</BODY>");
out.println("</HTML>");
}
}
3. O Deployment Descriptor
<listener>
<listener-class>
br.com.grandeporte.listeners.MeuListener
</listener-class>
</listener>
3
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Minhaprimeira JSP</title>
</head>
<body>
<h1>Primeiroteste com JSPs</h1>
<br/>
<%
out.println("Imprimindo em HTML por meio de comandos" +
" Java!");
%>
</body>
</html>
Observe no exemplo acima que usamos a notação <% ... %> para inserir
código Java na página HTML. Esse trecho de código inserido é chamado de scriptlet e
pode aparecer quantas vezes forem necessárias na página, podendo inclusive ter sua
abertura e fechamento permeada por código HTML.
Código em Scriptlets:
<%
out.println("Imprimindo em HTML por meio de comandos Java!");
%>
Código em Expressions:
<%=newjava.util.Date() %>
<%= O que estiver aqui será argumento de um out.println() e impresso na tela! %>
Practice
3
Atividade Revisão aos pares
Perceba que o Servlet nada mais é do que uma classe Java que tem como
superclasse HttpServlet. Note também que estamos utilizando como pacote o padrão
de domínio invertido, como fizemos nos capítulos anteriores.
Em seguida, clique em Next duas vezes para obter a próxima janela auxiliar de
configuração do Servlet. Essa janela refere-se a itens de configuração presentes no
Deployment Descriptor, o arquivo web.xml presente em seu projeto.
5. Criado seu Servlet, veja o código padrão gerado pelo Eclipse e, neste
momento, apague todos os comentários e javadoc existentes, de forma a
manter-se apenas com o código essencial para o template. Digite o seguinte
código em seu novo Servlet e preste atenção em cada linha e trecho de código.
1 @WebServlet("/servlet")
3
2 public class GrandePorteServlet extends HttpServlet {
5 response.setContentType("text/html");
7 out.println("<HTML>");
9 <"/TITLE></HEAD>");
10 out.println("<BODY>");
12 out.println("<hr><br /><br>");
13 out.println("<h2>Vocêacessou o Servlet+
14 GrandePorteServlet!</h2><br />");
16 out.println("</BODY>");
17 out.println("</HTML>");
18 }
21 }
http://localhost:8080/web/servlet:
3
Atividade
1 @WebServlet("/servlet")
2 public class RequestMethodsServlet extends HttpServlet {
3 protected void doGet(HttpServletRequest request, HttpServletResponse
4 response) throws ServletException, IOException {
5 response.setContentType("text/html");
6 PrintWriter out = response.getWriter();
7 out.println("<HTML>");
9 "</TITLE></HEAD>");
10 out.println("<BODY>");
11 out.println("<h1>Grande Porte - Java Level 2</h1>");
12 out.println("<hr><br />");
14 "</h2><br />");
16 out.println("</BODY>");
17 out.println("</HTML>");
18 }
21 }
Acrescente ao final da nossa URL (logo após o nome do Servlet sem barra final
"/") o trecho:
?id=1&nome=Aluno&sobrenome=GrandePorte
Essa página possui um formulário simples com alguns controles que receberão
dados do usuário e os enviarão ao servidor como parâmetros. Note que na tag<form>
configuramos o método de envio como "post" e o action como "servlet". O atributo
"action" deve receber o ServletPath para chamada. Em nosso caso, esse valor será o
"url-pattern" que configurarmos em nosso arquivo web.xml.
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Página Inicial:
Página Final:
Testando Listeners. 3
Performance
3
<meta http-equiv="Content-Type"content="text/html; charset=UTF-8">
<title>Formulário Inicial</title>
</head>
<body>
<h1>Bemvindo ao Cadastro de Alunos!</h1>
<hr>
<h3>Entre com seus dados abaixo:</h3>
<form action="captura" method="post">
<label for="nomeAluno">Nome: </label>
<input type="text"name="nomeAluno"id="nomeAluno"size="50">
<br/>
<br/>
<label for="seletorCurso">Curso: </label>
<select id="seletorCurso"name="seletor">
<option>...</option>
<option>Lógica de Programação</option>
<option>Java Level 1</option>
<option>Java Level 2</option>
<option>Cobol Level 1</option>
</select>
<br/>
<br/>
<label for="group1">Sexo: </label>
<input type="radio"name="group1"value="masculino">Masculino
<input type="radio"name="group1"value="feminino"checked>Feminino
<br/>
<br/>
<inputtype="submit"value="Cadastrar"/>
<br/>
<hr/>
</form>
</body>
</html>
packagebr.com.grandeporte.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
RequestDispatcher dispatcher =
request.getRequestDispatcher("/exibeDados.jsp");
dispatcher.forward(request, response);
}
}
}
4. Crie duas páginas jsp: uma chamada erro.jsp e outra chamada exibeDados.jsp
erro.jsp:
3
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01
Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type"content="text/html; charset=ISO-
8859-1">
<title>Erro no formulário</title>
</head>
<body>
<h1>Erro nos dados passados!</h1>
<br/>
<p><h3>Descrição: </h3>
Você inseriu dados inválidos para
<%=request.getParameter("erro") %>.
<br/>
<br/>
</body>
</html>
exibe Dados.jsp
<%@pagelanguage="java"contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01
Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type"content="text/html; charset=UTF
-8">
<title>Insert title here</title>
</head>
<body>
<h1>Cadastro efetuado com sucesso!</h1>
Nome: <%=request.getAttribute("nome") %>
<br/>
Idade: <%=request.getAttribute("idade") %>
<br/>
Curso: <%=request.getAttribute("curso") %>
<br/>
Sexo: <%=request.getAttribute("sexo") %>
<br/>
<br/>
</body>
</html>
7. Refatore sua aplicação para que ela trabalhe com um objeto javabean em
vez de usar atributos primitivos. Altere o código onde for necessário.
Estou fera!
Fiz Certo!
Preparation
Presentation
Teoria filtros
Filtros podem ser encadeados, sendo este um recurso muito útil quando
quisermos separar as funções de cada filtro aplicados a uma mesma Request.
4
Validação: existe a possibilidade de validar dados provindos na request, como
parâmetros e encaminhar o usuário para diferentes servlets, dependendo de
suas escolhas;
Conexão: é possível realizar uma conexão com o Banco de Dados assim que
a request chegar e repassar após ao servlet, já com a configuração de acesso
ao Banco de Dados feita. Essa não é uma prática muito recomendada, mas
ainda assim fica a lembrança.
A interface Filter
Métodos Descrição
init(fc:FilterConfig):void throws Método chamado somente uma vez,
ServletException quando da subida do Container.
destroy():void Método executado somente quando o
Container é desativado.
doFilter(request:ServletRequest, Método principal onde reside a lógica do
response:ServletResponse, filtro. Chamado a cada interceptação feita.
chain:FilterChain):void
Assim como os Servlets, os filtros devem ser declarados no web.xml para que
sejam mapeados e controlados pelo Container.
Da mesma forma que os Servlets, os filtros podem ser declarados por meio de
anotações na classe que os implementam desde a versão Java EE 6:
@WebFilter(...parâmetros...)
Tag Descrição
<filter> Tag raiz que abre o bloco de declaração para cada filtro da
aplicação
<filter-name> Nome dado ao filtro que serve somente para referenciá-lo no
próprio web.xml. Esse nome será usado como referência
para o filtro na tag <filter-mapping>
<filter-class> Nome totalmente qualificado da classe que representa o
respectivo filtro. Utiliza a mesma sintaxe que o utilizado para
importar classes em Java.
<filter-mapping> Tag utilizada para mapear um determinado filtro a um padrão
de URL, utilizando para tanto, a tag <filter-name> que
identifica o filtro específico.
<url-pattern> ou Tag usada dentro da anterior para mapear um padrão de
<servlet-name> URL ou um servlet de destino/origem a ser atendido por um
determinado filtro.
<dispatcher> Tag usada para identificar quais origens de solicitações
deverão ser interceptadas. Possibilidades: REQUEST,
FORWARD, INCLUDE e ERROR.
<filter>
<display-name>MeuFiltro</display-name>
<filter-name>MeuFiltro</filter-name>
<filter-class>br.com.grandeporte.filter.MeuFiltro</filter-class>
</filter>
<filter-mapping>
<filter-name>MeuFiltro</filter-name>
4
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
package br.com.grandeporte.filter;
import java.io.IOException;
import java.util.Date;
import javax.servlet.http.*;
import javax.servlet.*;
Cookies nada mais são do que pequenas porções de dados que são
armazenados na máquina do usuário da aplicação, podendo ser manipulados pelo
aplicativo web, caso haja permissão do usuário para tanto.
Esses pequenos conjuntos de dados são muito usados para se obter alguma
informação útil acerca do usuário logado ou acessando a aplicação web como, usuário
e senha, código de identificação da sessão do usuário, algum texto que represente as
preferências daquele usuário acerca de algum assunto ofertado na aplicação web,
entre outras tantas.
na classe HttpServletResponse:
o addCookie(cookie:Cookie):void - Adiciona o cookie passado como
parâmetro na resposta.
A Classe javax.servlet.http.Cookie
Métodos Descrição
getComment():String Métodos de acesso do atributo comment, que
setComment(comment:String):void descreve o Cookie e seu propósito
4
getDomain():String Métodos de acesso que define o domínio onde
setDomain(domain:String):void todos os componentes terão acesso ao cookie
getMaxAge():int Métodos de acesso para o tempo de vida do
setMaxAge(maxAge:int):void Cookie, em segundos. -1 significa que o
cookie deve expirar assim que o browser for
fechado.
getName():String Métodos de acesso ao atributo name do
setName(name:String):void cookie, usado como identificador.
getPath():String Métodos de acesso à URL de onde todos os
setPath(path:String):void componentes poderão acessar o cookie.
getSecure():boolean Define se será utilizado https para acesso ao
setSecure(secure:boolean):void Cookie.
getValue():String Métodos de acesso ao atributo value do
setValue(value:String):void Cookie, efetivamente o dado que esse cookie
carrega consigo.
package br.com.grandeporte.servlet;
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
if (cookies != null) {
for (int i = 0; i < cookies.length; i++){
if (cookies[i].getName().equals("usuario")) {
usuario = cookies[i].getValue();
}
if (cookies[i].getName().equals("senha")){
senha = cookies[i].getValue();
}
}
}
Desde o início do curso vem sendo dito que o protocolo HTTP não mantém
estado assim como as aplicações web. Isto é, não o faz automaticamente, sendo esta
4
tarefa do desenvolvedor.
Para que esse problema seja contornado, torna-se necessário colocar dados
como os do exemplo acima em uma área da aplicação que seja acessível por outros
componentes e que persista entre as requisições dos clientes. Essa área é
denominada de sessão e representa uma área de armazenamento persistente
enquanto durar a estada do usuário na aplicação.
JSESSIONID=AS435H878JG12477
Método Descrição
getSession():HttpSession Retorna a sessão já existente com essa
request ou cria uma nova, caso não
exista nenhuma.
getSession(create:Boolean):HttpSession Retorna a sessão já existente com essa
request, ou cria uma nova se não existir
uma e o argumento create for igual a
true. Caso o argumento seja false e não
exista nenhuma sessão associada,
retorna null.
Criada a sessão, podemos obter a data de criação e o Id dela por meio dos
métodos:
Método Descrição
getId():String Retorna uma String com o identificador único da sessão
criado pelo Container.
getCreationTime():long Retorna a data de criação da sessão em milisegundos que
podem ser convertidos em um objeto Date.
Método Descrição
getAttribute(name:String):Object Retorna o objeto associado ao nome
passado.
getAttributeNames():Enumeration Retorna uma Enumeration com os nomes
dos atributos existentes na sessão.
setAttribute(name:String, Adiciona o objeto na sessão, associado ao
valor:Object) nome passado no parâmetro do método
removeAttribute(name:String):void Remove o objeto especificado.
Invalidando uma sessão
Uma sessão deve ser invalidada quando não estiver mais em uso, de forma a
preservar recursos no servidor. Comumente, ocorre quando o usuário clica no botão
"Sair" da sua aplicação ou quando permanece muito tempo inativo. Podemos nos
utilizar de duas formas para invalidar sessões:
Método
invalidate():void
Descrição
Invalida a sessão e desassocia todos os objetos
que possuía.
4
setMaxInactiveInterval(interval:int): Atribui o valor máximo que a sessão poderá
void ficar inativa antes que seja invalidada. Esse
valor é definido em segundos.
getLastAccessedTime():long Retorna a representação em long da data da
última requisição deste cliente.
<session-config>
<session-timeout>10</session-timeout>
</session-config>
Método Descrição
encodeURL(url:String):String Adiciona o id da sessão se necessário, ou seja, se a
recepção de cookies estiver desabilitada na
máquina do usuário.
encodeRedirectURL(url:String) Equivalente ao método acima para ser usado em
caso de sendRedirect().
Usando comentários
4
sintaxe própria da JSP:
Usando Declarações
Declarações em JSP são blocos de código Java que podem conter declarações
de variáveis e métodos que serão utilizados no escopo da classe.
Exemplo:
Diretivas Page:
O que torna esta diretiva um pouco complicada é que ela possui onze atributos
diferentes. Observe primeiro como é a sua sintaxe:
o Atributo Info
<%@ page info=”Estudo sobre Diretivas JSP, Prof. Cristiano Neves, 2006” %>
o Atributo Language
o Atributo ContentType
Este atributo indica qual o tipo MIME (Multipurpose Internet Mail Extensions) da
resposta está sendo gerada pela JSP.
o Atributo Extends
Serve para indicar a super classe que será usada pelo container no momento
de tradução da página em um Servlet Java.
o Atributo Import
o Atributo Session
4
gerenciamento de sessão.
<%@ page session=”true” %>
o Atributo Buffer
Responsável por controlar a saída bufferizada para uma página JSP. Se for
modificado para “none” o conteúdo de uma JSP é passado instantaneamente à
resposta HTTP. O tamanho do buffer é descrito em kilobytes.
o Atributo AutoFlush
o Atributo isThreadSafe
Quando uma página JSP é compilada em um Servlet, ela deve ser capaz de
atender a múltiplas solicitações. Para isso deve-se utilizar o atributo isThreadSafe,
caso contrário é necessário defini-lo como “false”.
o Atributo errorPage
ErrorPage indica uma página alternativa que será exibida caso aconteça um
erro não previsto durante o processamento de uma página JSP no container.
Responsável por definir uma página JSP que servirá como a página de erro
padrão para um grupo de páginas JSP.
Diretiva Include
Diretiva Taglib
Objetos Implícitos
Practice
Performance
Utilizamos páginas JSP onde poderiam ter sido utilizados Servlets e vice-versa
de forma a mostrar ao aluno que as tecnologias são intercambiáveis tendo, cada qual,
sua especialidade e vantagens de atuação.
4
<title>Validação de Login</title>
</head>
<body>
<%
String usuario = request.getParameter("userName");
String senha = request.getParameter("password");
String msg = "";
String urlDestino = "/index.jsp";
}
request.setAttribute("msg", msg);
RequestDispatcher dispatcher =
request.getRequestDispatcher(urlDestino);
dispatcher.forward(request, response);
%>
</body>
</html>
package beans;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
4
import javax.servlet.http.HttpServletResponse;
import beans.Cliente;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
4
id="WebApp_ID" version="2.5">
<display-name>GrandePorteJSP</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>Aplicacao</display-name>
<servlet-name>Aplicacao</servlet-name>
<servlet-class>Aplicacao</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Aplicacao</servlet-name>
<url-pattern>/aplicacao</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>Logout</display-name>
<servlet-name>Logout</servlet-name>
<servlet-class>Logout</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Logout</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
</web-app>
Estou fera!
Fiz Certo!
Preparation
Presentation
Veja, além do JSF, alguns dos mais conhecidos frameworks web disponíveis
hoje no mundo Java:
O framework JSF faz extenso uso dos padrões MVC e Front Controller em sua
arquitetura e por esse motivo vale a pena um olhar um pouco mais atento sobre esse
assunto de forma que o aluno entenda melhor como trabalhar com JSF 2.1.
MVC ou Model-View-Controller
Nesse padrão, largamente adotado hoje em dia por quase todos os frameworks
web, procura-se separar as três camadas que compõem qualquer aplicação, de forma
a obter-se algumas vantagens como:
Separação de responsabilidades;
Organização de código;
Baixo acoplamento, facilitando a extensão e alteração de componentes;
5
Integração entre diferentes áreas de desenvolvimento, como designers e
desenvolvedores;
Segurança;
Facilidade de manutenção;
Agilidade na customização, entre outros.
Front Controller
5
controlará todas as requisições chegadas do usuário que atenderem ao padrão
necessário para a chamada da aplicação.
Um projeto web JSF nada mais é do que um projeto Java web, que se utiliza de
Servlets, dos recursos Java EE e dos padrões de arquitetura acima descritos,
principalmente. Respeita a API de Servlets e qualquer outro componente já visto
durante a fase do curso relativa à Servlets, também se aplica da mesma forma em
projetos JSF.
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
o Mojarra: http://javaserverfaces.java.net/download.html
5
Repare que esse último arquivo está somente com a tag inicial <faces-config>.
Esse arquivo poderá ser palco de muitas configurações dentro de nossa aplicação. Na
verdade ele será o "Painel de Controle" da aplicação JSF.
package beans;
import java.util.Random;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class Usuario {
5. Lembre-se de que estamos rodando uma aplicação web e, para tanto, você já deve
estar com seu Container Web (estamos usando o Apache Tomcat) funcional. Após
toda a configuração e códigos prontos, devermos ter a seguinte estrutura de arquivos:
Configuração:
/faces/*
*.jsf
*.xhtml
É claro que infinitas combinações de padrão de URL podem ser feitas, portanto
atente para esse item!
Managed Beans:
5
Language para acessar os Beans.
<h:outputText value="#{usuario.nome}"/>
#{nomeDoBean.nomeDoAtributoOuMétodo}
O nome do bean será por default o nome da classe começando com letra
minúscula. O nome do atributo ou método será sempre o nome do método getter ou
setter, sem os prefixos get ou set.
Facelets são páginas XHTML que carregam tags JSF, mas também tags
XHTML padrão, sendo agora preferidas como forma de apresentação às anteriores
JSPs. Uma página Facelet tem tipicamente as tags HTML padrão substituídas por
aquelas específicas da JSF, contidas em seus namespaces padrão e até outras,
contidas em namespaces customizados.
<h:head>
<!-- … Código … -->
</h:head>
<h:body>
<h:form>
<h:outputText value="Nome Gerado: "/>
<!-- Isso é Expression Language! -->
<h:outputText value="#{usuario.nome}"/>
<br />
<h:commandButton value="Enviar" />
</h:form>
</h:body>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
1. Restore View
2. Apply Request Values
3. Process Validations
4. Update Model Values
5. Invoke Application
6. Render Response
2. Apply Request Values: Nessa fase, a implementação JSF itera sobre todos
os componentes inseridos na árvore montada anteriormente. Cada componente
verifica quais dos valores vindos na requisição lhes pertencem e os armazenam,
atualizam-se com as informações recebidas. Esses valores são chamados de valores
locais. Os eventos recebidos também são identificados nessa fase, porém somente
serão tratados em fase posterior;
4. Update Model Values: Assim que o ciclo sai da fase anterior, entende-se
que é seguro atualizar o modelo de dados. Nessa fase, os valores locais são utilizados
para atualizar os beans (propriedades) que estão conectados aos respectivos
componentes.
Managed Beans
De acordo com a definição presente na especificação Javabeans, um Java
bean é um componente de software reutilizável que pode ser manipulado em uma
ferramenta de construção (build). Temos que admitir que essa definição é bem vaga,
mas em geral, é essa natureza que define um bean: sua vasta gama de aplicações.
Veremos que, em nosso caso, um Managed Bean tem propósitos bem definidos.
5
Lê propriedades dos beans quando exibindo em uma página;
Atualiza propriedades dos beans quando um formulário é postado.
<h:outputText value="#{usuario.nome}"/>
@ManagedBean(name="usuario")
@RequestScoped
public class Usuario {
… // Definição da classe
}
Um Managed Bean nada mais é do que uma classe Java com a anotação
@ManagedBean, que rotula nossa classe como um bean que deverá ser gerenciado
pela implementação JSF e pela anotação @RequestScoped, que delimita o escopo de
existência da classe, nesse caso específico, escopo de Requisição.
http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html
<faces-config>
<managed-bean>
<managed-bean-name>usuario</managed-bean-name>
<managed-bean-class>beans.Usuario</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>
@ManagedBean(eager=true)
Um bean, para ser assim considerado, segue uma série de padrões específicos
de programação para expor as propriedades e ações que oferecem. As propriedades
de um bean compõem o mais importante conjunto de funcionalidades disponíveis em
um componente desse tipo e podem ser definidas por meio da implementação dos três
itens abaixo listados:
Um nome;
Um tipo;
Métodos de acesso e modificação (getters e setters).
package beans;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean(name="usuario")
@RequestScoped
public class Usuario {
5
public String getNome() {
return this.nome;
}
package beans;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class MeuBean {
@PostConstruct
public void inicializar(){
//Código a ser excutado na inicialização do bean
}
@PreDestroy
public void destruir(){
//Código a ser executado na destruição do bean
}
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
5
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class MeuBean implements Serializable{
@ManagedProperty(value="#{user}")
private Usuario user;
Ao definir um bean com esse Você poderá injetar como propriedades, beans
escopo...: deste escopo...:
nenhum nenhum
application nenhum, application
session nenhum, application, session
view nenhum, application, session, view
request nenhum, application, session, view, request
Esse arquivo deverá ser composto unicamente por pares de chave=valor, que
serão referenciados no contexto de todas as páginas da aplicação. Deverá ser criado
no mesmo diretório onde são criadas as classes da aplicação, não importando em qual
subdiretório ou pacote, contanto que tenha a extensão .properties.
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<resource-bundle>
<base-name>br.com.grandeporte.messages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
</faces-config>
5
apenas observar o padrão utilizado para que a implementação JSF saiba qual arquivo
aplicar, dada a localidade em que está.
<faces-config>
<application>
<locale-config>
<default-locale>pt_BR</default-locale>
<supported-locale>en_US</supported-locale>
</locale-config>
</application>
</faces-config>
Tag Descrição
head Renderiza o bloco <head> da página
body Renderiza o bloco <body> da página
form Renderiza um <form> HTML
outputStyleSheet Adiciona uma Folha de Estilos à página (Ex: CSS)
outputScript Adiciona um script à página (Ex: Javascript)
inputText Controle de entrada de texto em uma linha simples
inputTextArea Controle de entrada de texto em múltiplas linhas
inputSecret Controle de entrada de senhas / passwords
inputHidden Campo oculto, geralmente em formulários
outputLabel Controle de label para outro componente na página
(Acessibilidade)
outputLink Link para outra localidade na web
outputFormat Como outputText, mas formata as mensagens compostas
outputText Saída de texto em linha simples
<h:inputText> e <h:outputLabel>
o index.xhtml:
o Navegador:
<h:inputTextarea>
o index.xhtml:
o Navegador:
<h:inputSecret>
o index.xhtml:
o Navegador:
<h:inputHidden>
o index.xhtml:
Esses controles são responsáveis por captar a interação do usuário para uma
dentre diversas escolhas, com exceção do Checkbox booleano. Para a exibição de
múltiplos itens disponíveis para escolha, esses componentes fazem uso de listas ou
coleções em geral, que devem ser criadas e controladas nas propriedades
responsáveis nos Managed Beans.
<h:selectBooleanCheckbox>
o index.xhtml:
o Navegador:
o index.xhtml:
o Navegador:
5
<h:selectOneMenu> - Nesse componente estaremos usando uma forma mista de
populá-lo: um item estaticamente, que corresponde ao valor da String "nenhum" e um
componente que referencia uma coleção controlada pelo Managed Bean
o index.xhtml:
o Navegador
o index.xhtml:
5
this.materiasEscolhidas = new ArrayList<String>();
this.materiasEscolhidas.add("Matemática");
this.materiasEscolhidas.add("Português");
this.materiasEscolhidas.add("Biologia");
this.materiasEscolhidas.add("Física");
this.materiasEscolhidas.add("Quimica");
}
return this.materiasEscolhidas;
}
o Navegador:
o index.xhtml:
o Navegador:
o index.xhtml:
<f:selectItems value="#{aluno.materiasEscolhidas}"/>
</h:selectManyMenu>
Google Chrome:
Mozilla Firefox:
o index.xhtml:
5
if (this.materiasEscolhidas == null){
this.materiasEscolhidas = new ArrayList<String>();
this.materiasEscolhidas.add("Matemática");
this.materiasEscolhidas.add("Português");
this.materiasEscolhidas.add("Biologia");
this.materiasEscolhidas.add("Física");
this.materiasEscolhidas.add("Quimica");
}
return this.materiasEscolhidas;
}
o Navegador:
o index.xhml:
o Navegador:
5
</h:button>
o Navegador:
o index.xhtml:
o Managed Bean: sem conexão com o bean. A afirmação feita aos componentes
<h:button> e <h:link> também se aplicam a esse componente nesse item.
o Navegador:
<h:panelGrid> e <h:panelGroup>
<h:panelGroup >
<h:commandButton value="Cadastrar" />
<h:graphicImage library="imagens" name="Check_24x24.png"/>
</h:panelGroup>
</h:panelGrid>
</h:form>
A biblioteca Core contém componentes que são independentes das tags HTML
para renderização da página. A maior parte dessas tags representam objetos que são
adicionados aos componentes, como os seguintes:
Atributos;
Parâmetros;
Facets;
Ouvintes;
Conversores;
Validadores;
5
Itens de Seleção.
Navegação
ou
Perceba ainda que existe diferença onde deverá ser colocado o outcome. No
caso de um <h:button> ou <h:link> deverá estar no atributo outcome e, no caso de um
<h:commandButton> ou <h:commandLink> deverá estar no atributo action. O único
detalhe a ser lembrado é que os dois últimos precisam estar em um <h:form> para
terem o redirecionamento funcionando.
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>sucesso</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>falha</from-outcome>
<to-view-id>/erro.xhtml</to-view-id>
</navigation-case>
Navegação Dinâmica
Temos visto até agora como configurar nossa aplicação para navegar entre
páginas usando outcomes. Outcomes nada mais são do que Strings que, ao serem
interpretadas pela implementação JSF, busca alguma regra de navegação associada
e, caso não encontre, tenta navegar para uma página de mesmo nome, inferindo o
caminho e extensão do arquivo a partir da página de origem da requisição.
5
nossa aplicação, deixando para o tempo de execução a decisão do destino de nossa
navegação.
Um botão ou link, que antes nos direcionava sempre ao mesmo destino, por
click dado, agora direcionará para uma página diferente a cada click, sendo essa
decisão atrelada a um método em um Managed Bean.
index.xhtml:
<h:form>
<h1>Esta é a Página Dados!</h1>
<h:button value="Próxima página" outcome="#{meuBean.navegacao()}" />
</h:form>
dados.xhtml:
<h:form>
<h1>Esta é a Página Dados!</h1>
<h:commandButton value="Retornar..." action="voltar" />
</h:form>
conteudo.xhtml:
<h:form>
<h1>Esta é a Página Conteúdo!</h1>
<h:commandButton value="Voltar" action="voltar" />
</h:form>
@ManagedBean
@SessionScoped
public class MeuBean {
faces-config.xml:
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>prosseguirDados</from-outcome>
<to-view-id>/dados.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>prosseguirConteudo</from-outcome>
<to-view-id>/conteudo.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>voltar</from-outcome>
<to-view-id>/index.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Teoria facelets
Templates
Tags Descrição
ui:include Inclui conteúdo de outro arquivo XML.
ui:composition Quando usado sem um atributo template, uma composition é uma
sequência de elementos que podem ser inseridos em algum outro
lugar. A composição pode ter partes variáveis (especificadas com
tags filhas ui:insert).
Quando usado com o atributo template, o template é carregado. As
tags filhas dessa tag determinam as partes variáveis do template. O
conteúdo do template substitui essa tag.
ui:decorate Quando usado sem um atributo template, ui:decorate especifica uma
página dentro da qual podem ser inseridas outras partes ou trechos.
5
As partes variáveis são especificadas com tags filhas ui:insert.
Quando usada com o atributo template, o template é carregado. As
tags filhas dessa tag determinam as partes variáveis do template.
ui:define Define conteúdo que será inserido em um template com a tag
correspondente ui:insert.
ui:insert Insere conteúdo em um template. O conteúdo é definido dentro da
tag que carrega o componente.
ui:param Especifica um parâmetro que é passado para um arquivo incluído ou
um template.
ui:component Essa tag é idêntica à ui:composition, só que nesse caso ela cria um
componente que é adicionado à árvore de componentes.
ui:fragment Essa tag é idêntica à ui:decorate, só que nesse caso ela cria um
componente que é adicionado à árvore de componentes.
ui:debug A tag ui:debug permite aos usuários mostrar uma janela de debug,
por meio de um atalho de teclado, que mostra a hierarquia de
componentes para a página atual e as variáveis de escopo application.
ui:remove A implementação JSF remove tudo o que estiver dentro de tags
ui:remove.
ui:repeat Itera sobre uma lista, array, result set ou objeto individual.
http://www.primefaces.org/downloads.html
Vejamos um exemplo:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="E-mail: " for="email" />
<h:inputText id="email" />
<h:outputLabel value="Senha: " for="senha" />
<h:inputText id="senha" />
<h:commandButton value="Enviar"/>
</h:panelGrid>
</h:form>
</ui:composition>
Practice
5
Experimentação com componentes
a) Crie um novo projeto no Eclipse e configure-o para trabalhar com JSF 2.1. Dê o
nome de TesteComponentes.
c) Crie uma outra página chamada bemvindo.xhtml e exiba todos os dados do usuário
cadastrado. Essa página deverá ser chamada a partir do botão "Cadastrar" da página
de cadastro
<h1>Navegação JSF!</h1>
<br />
<br />
<h:button value="Ir para página dados" outcome="dados" >
<f:param name="escola" value="GrandePorte"/>
</h:button>
Note que essa é uma página bem simples, com apenas um componente, um
<h: button>. Lembre-se de que esse componente envia uma requisição via GET.
Estamos aproveitando a ocasião e demonstrando também o envio de parâmetros para
essa requisição (que serão anexados à URL já que trata-se de método GET). Esse
botão envia um outcome com o valor de "dados". Essa String será usada pelo JSF
para procurar uma página de nome dados.xhtml (mesma extensão da página emissora
da requisição) na mesma pasta da página atual e enviar a ela o parâmetro de
requisição: escola=GrandePorte.
<h:form>
<h1>Esta é a página de Dados!</h1>
<br />
<br />
5
<!-- <h:button value="Retornar..." outcome="index" /> -->
<h:commandButton value="Retornar..." action="index" />
</h:form>
d) Rode sua aplicação no servidor e teste a navegação implícita criada entre essas
duas páginas.
e)
f) Neste item, você deverá tornar a navegação entre essas páginas, explícita.
Primeiramente, crie as regras de navegação, usando os seguintes comandos, em seu
arquivo faces-config.xml:
<navigation-rule>
5
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>prosseguir</from-outcome>
<to-view-id>/dados.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/dados.xhtml</from-view-id>
<navigation-case>
<from-outcome>voltar</from-outcome>
<to-view-id>/index.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Navegação dinâmica
a) Crie mais uma página em sua aplicação, denominada conteudo.xhtml. Essa página
deverá possuir um botão ou link para retornar à página index.xhtml, nossa página
inicial.
b) Altere nossa página inicial para receber do usuário o outcome desejado. Utilize o
controle que preferir para capturar esse dado. Dê uma dica ao usuário de quais são os
resultados possíveis (algo semelhante à funcionalidade de um menu). Para isso:
b.1) Crie um Managed Bean denominado NavBean com uma propriedade para
armazenar a escolha do usuário;
a) Crie um novo projeto no Eclipse com suporte a JSF 2.x e Primefaces 3.3.1., dando
o nome de TemplatesJSF. Limpe o projeto, em seguida, excluindo o que foi criado por
5
Default pelo Eclipse;
b) Crie uma página chamada principal.xhtml, que será nosso template para as demais
páginas. Essa página será composta pelo seguinte conteúdo:
<p:tieredMenu style="width:180px;">
<p:submenu label="Alunos" icon="ui-icon-refresh">
<p:menuitem value="Cadastrar" icon="ui-icon-disk"/>
<p:menuitem value="Consultar"
icon="ui-icon-arrowrefresh-1-w" />
</p:submenu>
<p:submenu label="Professores" icon="ui-icon-newwin">
<p:menuitem value="Consultar" icon="ui-icon-close" />
</p:submenu>
<p:separator />
<p:submenu label="Navegação" icon="ui-icon-extlink">
<p:submenu label="Links">
<p:menuitem value="Grande Porte"
url="http://www.grandeporte.com.br" />
<p:menuitem value="PrimeFaces"
url="http://www.primefaces.org"/>
</p:submenu>
<p:menuitem value="Google" url="http://www.google.com.br" />
</p:submenu>
</p:tieredMenu>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="south" size="100">
<h1>Rodapé do site</h1>
</p:layoutUnit>
<p:layoutUnit position="center">
<ui:insert name="center" />
</p:layoutUnit>
</p:layout>
</h:body>
</html>
c) Implementaremos agora nossa primeira página cliente desse template. Crie uma
5
página chamada index.xhtml e configure sua aplicação para que ela seja a página
padrão de inicialização. Deverá possuir o seguinte código:
<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:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<ui:composition template="/principal.html">
<ui:define name="title">
Página composta com template!
</ui:define>
<ui:define name="center">
<h2>Conteúdo inserido pela página index!!</h2>
<p:editor />
</ui:define>
</ui:composition>
</html>
d) Execute sua aplicação e verifique o resultado. Você perceberá que seu menu está
escondido por trás do <p:layoutUnit> definido como "center". Esse é um problema de
CSS que resolveremos já.
.ui-layout-west {
z-index:20 !important;
overflow:visible !important;;
}
.ui-layout-west .ui-layout-unit-content {
overflow:visible !important;
}
f) Como próximo passo, acrescente essa folha de estilos ao seu template, de modo
que todas as páginas-filhas possam fruir desse benefício. Lembra-se da tag
<h:outputStylesheet>? Coloque-a no <h:head> do seu template.
g) Rode novamente sua aplicação e veja que agora o problema está resolvido.
Performance
5
Transformando o menu lateral em um componente
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
</ui:composition>
c) Insira a página criada no mesmo local onde estava antes, porém agora usando a
tag <ui:include>.
Estou fera!
Fiz Certo!
Preparation
6
saibam como está seu conhecimento sobre o assunto e se você precisa ou
pode fornecer ajuda aos colegas e instrutor.
Presentation
Eventos de sistema.
EVENTOS DE AÇÃO
Vamos codificar uma simples aplicação onde utilizaremos os eventos de ação:
Crie um arquivo chamado acaoBTO.xhtml conforme código abaixo:
import javax.faces.bean.ManagedBean;
import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;
@ManagedBean
public class CliqueBean {
public CliqueBean() {
}
actionListener ="#{cliqueBean.mudaTexto}"
Mas por que usar o actionListener em vez do atributo action? Esta pergunta é
bastante conveniente, pois existem esses dois atributos do componente
commandButton para acessar métodos dos nossos ManagedBeans, e assim como a
pergunta é boa, a resposta será a altura! Já vimos anteriormente que existe um mapa
de navegação que espera que os métodos dos nossos managed beans retornem uma
string para que a aplicação saiba qual página renderizar para o usuário, então,
seguindo está lógica, podemos então usar o atributo action para acessar métodos que
irão retornar Strings para o mapa de navegação e usaremos o atributo actionListener
para acessar métodos que irão acessar a lógica de negócio de nossa aplicação (ver
M.V.C.), esta escolha de qual atributo irá acessar a lógica e qual irá acessar a
navegação tem um porquê, quando a framework JSF for executar os métodos de
ações ele executará primeiro os métodos actionlisteners para depois executar os
actions de nossas tags .xhtml.
package br.com.grandeporte.acoes;
import javax.faces.bean.ManagedBean;
import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;
@ManagedBean
public class CliqueBean {
public CliqueBean() {
}
action="#{cliqueBean.navega}"/>
</h:form>
</h:body>
6
</html>
Agora eu quem pergunto a você programador java, como foi que a aplicação
desenvolvida por você conseguiu mudar o valor do componente commandButton?
Para responder esta pergunta temos que entender a classe ActionEvent, seus
métodos e construtores, ressalto aqui a importância da documentação desta
framework, mas irei facilitar seus estudo mostrando um pouco desta classe de eventos.
Esta classe tem este construtor public ActionEvent(UIComponent componente) e
quando usamos o atributo actionListener acabamos lançando o componente que está
utilizando este atributo, claro que implicitamente a framework faz isto, por isso
conseguimos capturar o componente commandButton com o método
e.getComponent() que trás uma referência do próprio botão que ativou a ação.
<h:body>
<h:form>
<h:commandLink id="link" value="Enviar" actionListener="#{mudaCorDaFonte.mudaCorLink}"/>
</h:form>
</h:body>
</html>
package br.com.grandeporte.acao;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;
@ManagedBean
@RequestScoped
public class MudaCorDaFonte {
</h:form>
</h:body>
</html>
package br.com.grandeporte.listern;
import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;
@Override
public void processAction(ActionEvent e) {
UICommand c = (UICommand) e.getComponent();
c.getAttributes().put("style", "color:lime;text-align: center; font: 19px Arial,
sans-serif");
}
6
}
}
processAction(ActionEvent):void
este tipo de código é muito parecido com a interface ActionListener usados nas
aplicações JSE vista no curso Java Level 1, mas não se engane, aquela interface faz
parte do pacote java.awt.ActionListener e esta que estamos usando faz parte do
pacote javax.faces.event.ActionListener, as duas interfaces tem métodos para serem
sobrescritos, e que serão executados todas vez que este listener ‘ouvir’ determinada
ação, em JSE o método abstrato era o actionPerformed e em JSF o método se chama
processAction.
<h:selectOneRadio/>
<h:inputText/>
<h:selectOneMenu/>
ManagedBean:
package br.com.grandeporte.mudancavalor;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ValueChangeEvent;
@ManagedBean
@SessionScoped
public class ProdutoBean {
public void mudaPreco(ValueChangeEvent e) {
System.out.println("Preço antigo: " + e.getOldValue());
System.out.println("Preço novo: " + e.getNewValue());
}
}
IM-05 IM-06
IM-07
IM-08 6
Sua aplicação deve exibir no browser do usuário a
imagem(IM-05) para que o usuário possa digitar
algo no componente h:inputText (IM-06 e IM-08),
assim que o esse form for enviado, o método
mudaPreço(VlueChangeEvent) da classe
ProdutoBean.java será executado e exibirá o valor
antigo e o novo valor do componente no console
IM-09 (IM-07 e IM-09).
package br.com.grandeporte.acoes;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ValueChangeListener;
@Override
public void processValueChange(ValueChangeEvent e)
throws AbortProcessingException {
System.out.println(" Preço antigo : " + e.getOldValue());
System.out.println(" Preço novo : " + e.getNewValue());
}
}
Notem que esta classe não tem as notações @ManagedBeans, porém, ela implementa
a interface ValueChangeListener, e por isso temos que sobrescrever o método
processValueChange(ValueChangeEvent):void , este método será executado quando este
listener for ativado.
<h:body>
<h2>Eventos de alteração de valor do componente f:valueChangeListener</h2>
<h:form>
<h:outputLabel value="Preço: " for="preco" />
<h:inputText id="preco">
<f:valueChangeListener type="br.com.grandeporte.listern.RegistraAlteracao" />
</h:inputText>
</h:form>
</h:body>
</html>
IM-10 IM-11
6
IM-14
IM-13
<h2>Preferência musical:</h2>
<h:selectManyCheckbox value="#{produtoBean.arrStr}" onchange="submit()">
<f:selectItem itemLabel="GOSPEL" itemValue="Gospel"></f:selectItem>
<f:selectItem itemLabel="ROCK" itemValue="Rock"></f:selectItem>
<f:selectItem itemLabel="POP" itemValue="Pop"></f:selectItem>
<f:selectItem itemLabel="FORRO" itemValue="Forro"></f:selectItem>
<f:selectItem itemLabel="DANCE" itemValue="Dance"></f:selectItem>
</h:selectManyCheckbox>
</h:form>
</h:body>
</html>
package br.com.grandeporte.listern;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ValueChangeEvent;
@ManagedBean
@SessionScoped
public class ProdutoBean {
private ArrayList<String> arrStr = new ArrayList<String>();
public ProdutoBean(){}
6
public void setArrStr(ArrayList<String> arrStr) {
for(String str : arrStr){
System.out.println("Tipo musical = " + str);
}
this.arrStr = arrStr;
}
IM-18 IM-19
IM-20 IM-21
EVENTOS DE SISTEMA
Os eventos de sistema são úteis para os programadores fazerem verificações,
ou até mesmo tomarem para si, em determinado momento o processo, isso ajuda a
tomar decisões antes que uma página seja renderizada, ou até mesmo quando sua
aplicação for inicializada ou finalizada pelo servidor.
6
PreRenderViewEvent Disparado antes de a raiz da visualização ser renderizado UIComponent
PreRenderComponentEvent Disparado antes de o componente ser renderizado UIComponent
Disparados, respectivamente, depois que o componente UIViewRoot
PostConstructViewMapEvent raiz cria o mapa de escopo da visualização e quando o
PreDestroyViewMapEvent conteúdo deste mapa é removido
ExceptionQueuedEvent Disparados depois que uma exceção foi colocada na fila ExceptionQueuedEvent
-Context
1ª – Com a tag:
package br.com.grandeporte.listern;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ComponentSystemEvent;
@ManagedBean
@RequestScoped
public class MonitoraEventosSistema {
private String nome;
O sistema irá renderizar na tela do usuário a imagem(IM-22), não importa o nome que o usuário
digite(IM-23), após o sistema acessar o getters e setters ele irá executar o método apontado na tag:
Não importa qual nome que o usuário digite, o listener de fase sempre vai
atravessar o processo mudando o resultado antes de renderizar a página novamente
para o usuário!
6
Esta classe de nome MonitoraEventosSistema.java tem o método apontado na
tag:
<f:event listener="#{monitoraEventoSistema.metodo}"
2ª – Com a tag:
@ListenerFor(SystemEventClass = PreRenderViewEvent.Class)
Este listener de sistema será abordado com mais detalhe no capítulo que fala
sobre criação de componentes.
package br.com.grandeporte.listern;
import javax.faces.application.Application;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.PostConstructApplicationEvent;
import javax.faces.event.PreDestroyApplicationEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
Notem que esta classe está comparando a qual fase sua aplicação está no
momento, se foi construída no servidor (PostConstructApplicationEvent) ou se foi
destruída no servidor (PreDestroyApplicationEvent), ela apenas irá imprimir a situação
atual no console, mas poderia, mas você, programador java, poderia desenvolver
lógicas de negócios para sua aplicação, ou até mesmo estar configurando algo usando
este listener de sistema.
<application>
<system-event-listener>
<system-event-listener-class>br.com.grandeporte.listern.OuvinteDeSystema</system-event-listener-class>
<system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
</system-event-listener>
</application>
Executando esta aplicação verificaremos que toda vez que o servidor for subir
nossa aplicação ele irá disparar o evento PostConstructApplicationEvent que nossa
classe OuvinteDeSystema capturará e executará o método específico conforme IM-25.
IM-25
Vamos criar uma aplicação para vermos na prática o uso destes EVENTOS DE
SISTEMA:
package br.com.grandeporte.listern;
import java.util.Date;import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;import javax.faces.event.ComponentSystemEvent;
@ManagedBean
@SessionScoped
6
public class ExtratoBean {
private Date dataInicial;
private Date dataFinal;
public void validaDatas(ComponentSystemEvent event) {
if (dataFinalEscolhida.before(dataInicialEscolhida)) {
FacesMessage message = new FacesMessage("A data final não pode vir antes da
data inicial");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(source.getClientId(), message);
context.renderResponse();
}
}
} Agora vamos codificar o arquivo geraextrato.xhtml
//Getters e setters
}
IM-31 IM-32
Para capturar este evento gerado pelas suas páginas JSF é necessário configurar o
arquivo faces-config conforme mencionado abaixo ou acrescentar nas páginas que se deseja
ouvir os eventos de fase com a tag:
<f:phaseListener type="br.com.grandeporte.listern.MonitoraFaseListern"></f:phaseListener>
tudo dependendo do que você, programador java pretende, com este listener :
<lifecycle>
<phase-listener>br.com.grandeporte.listern.MonitoraFaseListern</phase-listener>
</lifecycle>
package br.com.grandeporte.listern;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
@Override
public void afterPhase(PhaseEvent e) {
System.out.println("MonitoraFaseListern.afterPhase()");
System.out.println(e.getPhaseId());
}
@Override
public void beforePhase(PhaseEvent e) {
System.out.println("MonitoraFaseListern.beforePhase()");
System.out.println(e.getPhaseId());
}
@Override
public PhaseId getPhaseId() {
System.out.println(PhaseId.ANY_PHASE);
return PhaseId.ANY_PHASE ;
}
}
A partir de agora, toda página que for requisitada pelos usuários executarão o
listener de fase que você acabou de criar, claro que se você optou em usar a tag
f:phaseListener, a classe acima só executará quando está página for requisitada.
A aplicação apresentará uma tela com um botão para o usuário clicar conforme
abaixo
E como toda página agora tem um listener ouvindo todas as fases, e como
6
codificamos ele exibirá no console os textos abaixo, notem que ele imprime todas as
fases conforme explicados anteriormente.
O suporte ao ajax está embutido no JSF 2.0, que contam com uma biblioteca
em javaScript. Essa biblioteca pode ser acessível tanto na página quanto através de
código java. Nas páginas JSF, a forma de utilizar AJAX é usando as tags de apoio
f:ajax, os atributos desta tags são:
ATRIBUTOS DESCRIÇÃO
Event O evento dispara a requisição ajax, este evento pode ser tanto do
javaScript sem o prefixo on, exemplo = “blur” = onbluor, mas também
pode ser nomes de eventos de componentes, ex: action, valueChange
ou actionListener que são eventos de botões e links
Execute Este atributo se refere a qual componentes irá sofrer a requisição ajax,
os id deste devem ser separados por vírgula ou pode ser antecedidos
de @ nos casos (@this, @form, @all, @nome).
Onerror Indica uma função que será executada caso ocorra algum erro ao
processar sua página.
Onevent Neste atributo você poderá indicar uma função do javaScript que sua
aplicação executará quando processar a chamada ajax de sua página,
esta chamada ajax produz três(3) fases, BEGIN – início, COMPLETE-
Final, e SUCCESS-momento da renderização da página.
package br.com.grandeporte;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class BeanAjax {
private String nome;
public BeanAjax() {}
6
Cria uma página mxml de nome eco.xhtml
<h:body>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="Texto digitado: "></h:outputLabel>
<h:inputText id="texto1" value="#{beanAjax.nome}">
<f:ajax event="keyup" render="apoio"/>
</h:inputText>
<h:outputLabel value="ECO do texto digitado: "></h:outputLabel>
<h:inputText id="apoio" value="#{beanAjax.nome}"></h:inputText>
</h:panelGrid>
</h:form>
</h:body>
</html>
package br.com.grandeporte;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
@ManagedBean
@SessionScoped
public class BeanAjax {
private String nome;
public BeanAjax() {}
<h:body>
<h1>AJAX. Exemplo 02...</h1>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel value="Entre com seu nome: "></h:outputLabel>
<h:inputText id="txtNome" value="#{beanAjax.nome}" validator="#{beanAjax.validaNome}">
</h:inputText>
<h:message id="msgerronome" for="txtNome" style="color: green"></h:message>
Então, para se fazer uma requisição AJAX usando as tags da framework JSF é
necessário ter em mente 3 conceitos:
- Informar a esta tag ajax quais os componentes que irão ser validado no
servidor;
- Informar a tag ajax qual o(s) componente(s) que irão ser renderizados no
browser do cliente após requisição ajax.
</h:panelGrid>
</h:form>
</h:body>
</html>
O suporte a ajax oferecido pela framework JSF é de baixo nível pois abstrai
toda a complexibilidade do usuário desta framework quando utiliza requisições deste
tipo, vamos nos aprofundar mais sobre requisição ajax, quais situações o programador
pode encontra necessitar fazer uma requisição ajax? Para responder esta pergunta é
só começar a desenvolver uma página onde o há a necessidade de atualizar parte de
sua página e não toda ela, ou melhor ainda, executar validações de campos de
entrada, antes mesmo que o usuário envie o form utilizado. Vamos alterar mais uma
vez o arquivo para lhe mostrar, que o exemplo acima está didaticamente muito bom,
mas podemos reduzir o número de requisições utilizando o método "blur" conforme
abaixo:
Como visto anteriormente a tag <f:ajax tem o atributo onevent="" que pode
executar uma função javaScript indicada dentro das aspas duplas, sabemos que este
método executará 3 (três) vezes conforme tabela passada no início deste capítulo (nó
inicio da requisição AJAX, após a renderização da página .xhtml e após a última etapa
do ciclo de vida da sua página);
Para manipular erros na requisição ajax, caso ele ocorra, você, programador
java pode fazer o uso do método onerror="" apontando para um método javascript
para tratamento deste.
Como visto programador JAVA, existe várias formas de se utilizar este suporte
a AJAX em sua aplicação JSF, se aprofunde mais fazendo os exercícios extras para
realmente entender os conceitos.
Validadores e
Teoria conversores em jsf
Como visto nos exemplos passados até agora, em nenhum momento nos
preocupamos em validar ou converter dados fornecidos pelo usuário em nossas
páginas .xhtml, mas isso porque didaticamente não foi necessário, porém nos seus
projetos, você programador java, irá validar campos de entrada e converter valores de
String(valores doscampos de entrada) para tipos DATE, int, char, etc.
A framework JSF nos facilita no desenvolvimento nos fornece várias tags para
validação e conversão, estas tags são enviadas junto com o formulário ao servidor, e,
dentro dos 6(seis) ciclos que nossa aplicação percorre, exatamente na fase
ATUALIZAÇÃO DO MODELO nossa framework irá checar todas as validações do
campos, caso ocorra algum erro, ela vai pra última fase (renderizar respota) e antes de
exibir a página novamente ao usuário com os dados enviados preenchido nos campos
respectivos, a framework irá setar mensagens para que possa ser exibida para o
usuário(ver capítulo sobre mensagens).
Isto tudo tem um objetivo bem claro, não deixar que dados inconsistentes
cheguem a regra de negócio de nossa aplicação, além desta facilidade de validar
campos usando os validaores padrões, você programador java, não tem o trabalho de
tratar a página para ser enviada pro usuário, pois a framework faz isto para você.
CONVERSORES:
6
IM-2 IM-3
IM-5
IM-6
IM-7
Outra tag muito útil de conversão é a tag <f:convertDateTime /> para converter
o texto digitado em datas, crie o arquivo convetdata.xhtml conforme código abaixo:
<h:commandButton value="Submeter"></h:commandButton>
</h:panelGrid>
</h:form>
</h:body>
</html>
IM-8 IM-9
6
IM-10 IM-11
IM-12
IM-14
locale String ou Localidade para serem usadas para análise sintática ou formatação
java.util.Locale
timeZone Java.util.TimeZone Região de fuso usado para análise sintática ea formatação, default(GMT),
apartir do JSF 2.0 é possível alterar para localidade padrão o default da
máquina do usuário, para isto temos que atribuir o valor TRUE a
javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIM
EZONE, no arquivo web.xml.
Faça os testes com estes atributos para quando for necessário usar, você,
programador java, não fique reescrevendo código, pois a solução já está pronta para
você usar!
Para outras conversão existe a tag <f:converter /> , esta tag tem o atributo
converterId que recebe como parâmetro nomes relativos de classes conversoras, veja
o exemplo a seguir:
<h:commandButton value="Submeter"></h:commandButton>
</h:panelGrid> </h:form> </h:body></html>
IM-15 IM-16
IM-17
visualize as imagens IM-15/16/17.
6
A IM-18 mostram o mesmo senário
para converter entradas erradas, notem que o
resultado na IM-19 e notem que a mensagem
de erro são idênticas.
IM-18
IM-19
Todas essas convertem para essas classes Wrappers e seus tipos primitivos
correspondentes.
<h:commandButton value="Submeter"></h:commandButton>
</h:panelGrid>
</h:form>
</h:body>
</html>
IM-21
6
mais de 8 (oito) letras IM-25, e submeter este
form a framework irá, dentro do ciclo da
aplicação, verificar que o campo digitado não
tem o padrão passado, então ele irá setar
uma mensagem padrão na sessão e retornará
a página com os campos preenchidos com as
informações que o usuário inseriu para que
ele tenha a oportunidade de arrumar o que
IM-25 está fora dos padrões de validação estipulado
por você programador java conforme IM-26.
IM-26
Até agora usamos as tags para fazer nossas validações, mas há momentos
que temos que validarmos campos ou objetos em nossa aplicação e que a framework
não nos dá suporte, um exemplo clássico é a validação de documentos em um
formulário de cadastro, em específico vamos pegar o cpf, sabemos que ele deve
conter 11 dígitos sendo números e que seus dois últimos números são dígitos
conferidor, ou seja, existe uma equação que se faz com os 9(nove) primeiros dígitos o
resultado é os dígitos conferidores. O alvo aqui não é que vocês discutem a lógica por
trás desta equação, mas sim, que vocês compreendam que é possível criar
conversores e validadores personalizados. Vamos primeiramente entender a interface
Converter que é a que devemos implementar para criarmos conversores customizados,
após entendermos como funciona a lógica por trás de conversores, vamos criar
validadores customizados e entender a lógica por trás da interface Validator.
Quando eu falo em entrada de dados pelo usuário, temos que entender que
tudo o que o usuário digita dentro de um form é reconhecido como String quando este
form é enviado ao servidor, aí que entra a conversão de dados, resumidamente a
framework terá que converter estas Strings em tipos de dados específico, por exemplo,
se você, programador java criar um atributo do tipo int, e atribuir a este valor os dados
digitados pelo usuário em um campo
a framework irá acessar o método setIdade passando um valor do tipo int, isso não
acontece por mágica, a framework irá converter a String digitada pelo usuário para o
tipo int antes de passar o parâmetro para o método, mas eu pergunto a vocês, se o
usuário digitar uma letra em vez de números? Ou se o usuário digitar um número
negativo? Ou um número estrambólico do tipo 1235? Você poderá delimitar tudo isto
usando tags da framework em TODAS as páginas que utilizarem este campo de
entrada para popular este atributo idade. É justamente nestas situações que podemos
utilizar conversores personalizados, veja o exemplo a seguir:
#{msgs.cpf}
<h:inputText id="cpf" value="#{usuario.cpf}">
</h:inputText>
<h:message for="cpf" showDetail="true" showSummary="true" styleClass="errorMessage"/>
</h:panelGrid>
6
<h:commandButton value="#{msgs.bto}" action="result"/>
</h:form>
</h:body>
</html>
#{msgs.cpf}
<h:inputText id="cpf" value="#{usuario.cpf}"/>
<h:message for="cpf" showDetail="true" showSummary="true"/>
</h:panelGrid>
<h:commandButton value="#{msgs.bto}" action="result"/>
</h:form> </h:body> </html>
IM-29
<faces-config
IM-31
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
version="2.1">
<application>
<message-bundle>mensagens.mensagens</message-bundle>
<resource-bundle>
<base-name>mensagens.mensagens</base-name>
<var>msgs</var>
</resource-bundle>
</application>
</faces-config>
package br.com.bean;
@Override
public String toString() {
// TODO Auto-generated method stub
return cpf + "";
}
}
@ManagedBean
@RequestScoped
public class Usuario {
public Usuario() {
this.nome = "";
this.cpf = new Cpf("");
}
public String getNome() {return nome;}
public void setNome(String nome) {this.nome = nome;}
public Cpf getCpf() {return cpf;}
public void setCpf(Cpf cpf) {this.cpf = cpf;}
}
package br.com.conversor;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent; IM-34
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter; Anotação
import br.com.bean.Cpf;
@FacesConverter(forClass=br.com.bean.Cpf.class)
@FacesConverter(forClass=br.com.bean.Cpf.class) aponta para a classe a qual irá realizar a conversão,
todo objeto instanciado deste tipo será convertido
public class ConversorCpf implements Converter{ usando este conversor.
private boolean validaOk = true;
private String msgErro="";
Para se criar um conversor temos que implementar a interface Converter,
sendo assim temos que reescrever os métodos getAsObject – Transforma a
String em um Objeto e o método getAsString que transforma Objeto em
String.
public ConversorCpf() {
@Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String valor) throws ConverterException {
// método que transforma a String digitada pelo usuário em um objeto do tipo Cpf
String cpf = new String(valor);
if(cpf.length() >10 && cpf.length() <12){
try {
long cpfInt =Long.parseLong(cpf);
validaOk = true;
} catch (Exception e) {
validaOk = false;
msgErro = "CPF só pode conter números";
}
}else{
validaOk = false;
msgErro = "CPF só pode conter 11 números";
}
if(!validaOk){
FacesMessage message = new FacesMessage(msgErro, "erro2");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ConverterException(message);
}else return new Cpf(cpf.toString());
}
@Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object valor) {
// Método que pega o objeto Cpf e o transforma para String
return valor.toString();
}
}
Se o usuário digitar um cpf que não fuja das regras de conversão que
definimos, ver IM-34, ele irá apresentar a saída igual a da IM-37
Se o usuário digitar um cpf que não tenha 11(onze) números conforme IM-38 e
IM-39, o sistema não conseguirá converter essa entrada para um objeto do tipo
Cpf.java, e ainda irá setar uma mensagem de erro que poderá ser exibida em uma tag
<h:message/> conforme IM-40.
6
IM-41 IM-42
Se o usuário digitar 11(onze) dígitos, porém por descuido digitar alguma letra
no meio da informação IM-41, ao converter o nosso conversor irá notar o erro e irá
setar a mensagem de erro conforme IM-42.
Pelo que vimos no exemplo sobre conversão, o que vocês, que já sabem fazer
conversões usando as tags JSF e através da interface Converter. Analise qual é a
maneira mais adequada para a sua aplicação, como dica eu sugiro que, se o objeto a
ser Convertido, seja utilizado em mais de uma tela do seu sistema, então vale a pena
utilizar a interface, mas se a conversão for apenas em uma tela, então use o conversor
fornecido pela framework JSF através das tags já vistas anteriormente.
http://www.gerardocumentos.com.br/?pg=entenda-a-formula-do-cpf .
Assim como o Conversor, para criar um Validador temos que criar uma classe
que implemente uma interface, no caso a interface Validator, neste caso temos que
reescrever o método validate que será executada toda vez que instanciarem um objeto
do tipo alvo desta validação. Vamos acrescentar ao projeto anterior um arquivo de
nome ValidadorCpf.java dentro do pacote Bbr.com.validadoresconforme IM-43.
package br.com.validadores;
import javax.faces.application.FacesMessage;
IM-43
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
@FacesValidator("br.com.bean.Cpf")
public class ValidadorCpf implements Validator{
private boolean vallidaOk = true;
public ValidadorCpf() {}
@Override
public void validate(FacesContext arg0, UIComponent arg1, Object valor)
throws ValidatorException {
String cpf = valor.toString();
if(cpf.length() >10 && cpf.length() <12){
validaCPF(cpf.substring(0, 9));
if(vallidaOk){
validaDigCpf(cpf.substring(9, 11), cpf.substring(0, 9));
}
}else{
vallidaOk = false;
}
if(!vallidaOk){
//poderia criar mensagem em tempo de execução para serem apresentadas para o usuário
FacesMessage msgErro = new FacesMessage("Msg sumario", "msg detalhe");
msgErro.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msgErro);
}
}
}else{
for (int i = 0; i < 9; i++) {
soma1 += (Long.parseLong(_cpf.trim().substring(i, i + 1)) * (vlr - 1));
soma2 += Long.parseLong(_cpf.trim().substring(i, i + 1)) * vlr;
vlr--;
}
resto = (soma1 % 11);
if (resto > 1) {
digito1 = (11 - resto);
} else {
digito1 = 0;
}
soma2 += (digito1 * 2);
resto = (soma2 % 11);
if (resto > 1) {
digito2 = (11 - resto);
} else {
6
digito2 = 0;
}
digitoCPFGerado = (digito1 * 10) + digito2;
if(digitoCPFGerado == Long.parseLong(_dig_cpf)){
this.vallidaOk = true;
}else{
this.vallidaOk = false;
}
}
}
}
#{msgs.cpf}
<h:inputText id="cpf" value="#{usuario.cpf}">
<f:validator validatorId="br.com.bean.Cpf"/>
</h:inputText>
IM-45 IM-46
IM-47 IM-48
Componentes personalizados
Teoria em jsf
6
1ª – Pode-se criar uma página JSF utilizando as tags <composite:interface/> e
<composite:implementation/> conforme código abaixo:
package br.com.managedbeans;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class Usuario {
private String login;
private String senha;
public Usuario() {}
<composite:interface>
<composite:attribute name="image" required="true" />
<composite:attribute name="nlogin"></composite:attribute>
<composite:attribute name="nsenha"></composite:attribute>
<composite:attribute name="clogin"></composite:attribute>
<composite:attribute name="csenha"></composite:attribute>
<composite:attribute name="txtbto"></composite:attribute>
<composite:attribute name="acao"
method-signature="java.lang.String action()" />
6
</composite:interface>
<composite:implementation>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="#{cc.attrs.nlogin}"></h:outputLabel>
<h:inputText value="#{cc.attrs.clogin}"></h:inputText>
<h:outputLabel value="#{cc.attrs.nsenha}"></h:outputLabel>
<h:inputSecret value="#{cc.attrs.csenha}"></h:inputSecret>
<h:commandButton action="#{cc.attrs.acao}"
value="#{cc.attrs.txtbto}"></h:commandButton>
</h:panelGrid>
</h:form>
</composite:implementation>
</html>
<composite:interface/> e <composite:implementation/>
<html xmlns:composite=”http://java.sun.com/jsf/composite”>
Jpa e eclipselink
Teoria Ou hibernate
Tudo isto foi desenvolvido, para que você, programador JAVA não necessite
mais de todo aquele trabalhão utilizando SQL para montar seus objetos utilizando
JDBC, com JDBC tínhamos que saber os tipo de dados das tabelas para fazer
conversão, criar códigos SQL dinamicamente.
Vamos criar então um banco de dados conforme imagens abaixo para que nós
possamos utilizar este framework corretamente. O banco irá se chamar cadastro.
6
flag TINYINT(1) NULL DEFAULT '1' , PRIMARY KEY (id) ,
INDEX FK_prod_cat1 (idCategoria ASC) , CONSTRAINT FK_prod_cat1
FOREIGN KEY (idCategoria ) REFERENCES bd_gp_jpa.categorias (id )
ON DELETE CASCADE ON UPDATE CASCADE);
Após criarmos estas tabelas no banco, vamos utilizar a IDE Eclipse para criar
nossas classes e nosso arquivo persistence.xml que é um arquivo de configuração
utilizado pelas classes de nossa framework para mapear uma conexão com o banco e
suas tabelas com classes.
Click
em
modify
Baixe esta library, todas estes arquivos ficarão gravados na pasta libraries
dentro da sua pasta workspace.
1 - Selecione o
link Add
connection
2 - Selecione
banco MySQL.
3 - Selecione o 4 - Selecione
ícone. Driver MySQL que irá
utilizar, no nosso caso o
5.1
5-Sele-
cione
a aba
JAR
List
6
7-Selecione o Driver Mysql que irá
utilizar para sua conexão com o BD.
6
Agora vamos criar nossas classes a partir das tabelas do banco de dados cadastro criado no
início deste capítulo.
17 – Altere o atributo Transaction type
para Resource Local
16 – de dois(2)
cliques no arquivo
de configuração
persistence.xml
19 – Selecione a
conexão criada nos
passos 1 a 14, no nosso
caso não demos nome
para ele, então por
default ele se chamará
New MySQL
20 – Selecione a aba
Source
21 – Este é o arquivo
gerado por toda estes
passos, um mapeamento
do banco de dados para
conexão e
relacionamento entre as
tabelas e nossas classes.
Salve seu projeto, agora vamos criar nossas classes a partir de nossas tabelas utilizando a IDE
Eclipse, siga os passos a seguir:
6
23 – Crie dentro do pacote entidades
arquivos do tipo JPA Entities from Tables
conforme figura ao lado
Verifiquem os atributos dos beans que sua IDE criou, em todos atributos foram
colocados anotações, veremos agora o que significam essas anotações, para isto,
deveremos ter em mente os conceitos de banco de dados, pois estas anotações estão
intrinsicamente ligados aos tipos de dados da tabela, se são chave primárias ou até
mesmo se são chave primária com criação de números automáticos:
javax.persistence.Entity
Usado para definir que uma classe é uma Entity, por padrão quando o nome da
Entity é igual ao nome da tabela o mapeamento é feito automaticamente pelo JPA.
Propriedade Descrição
name Informa o nome da Entity, por padrão o nome da entity é nome da
classe. Este nome é utilizado para referenciar a entity na consulta.
Exemplo:
Criar uma Entity que está mapeada para a tabela PRODUTO.
@Entity
public class Produto {
...
}
javax.persistence.Table
Propriedade Descrição
Catalog O catalogo da tabela.
Name O nome da tabela.
schema O esquema da tabela.
uniqueConstraints Regras / Restrições que podem ser adicionadas na tabela.
Exemplo:
Criar uma Entity que está mapeada para a tabela PRJ_PDT que armazena os
dados de um produto. Se criarmos uma classe chamada Prj_Pdt para mapear esta
tabela, não estaremos seguindo as boas praticas de nomeação de classes e por
padrão a anotação @Entity irá fazer o mapeamento através do nome da classe. Para
especificar manualmente qual a tabela deve ser mapeada com a Entity, podemos usar
a anotação @Table e especificar a propriedade name.
@Entity
@Table(name="prod")
public class Produto {
...
}
javax.persistence.Id
Exemplo:
@Entity
public class Produto {
@Id
private int id;
...
}
6
javax.persistence.Column
Propriedade Descrição
columnDefinition Definição do tipo da coluna.
insertable Informa se a tabela deve ser incluída no SQL de insert, por padrão é
true.
length Tamanho da coluna, por padrão é 255.
name Nome da tabela que contém está coluna, se não for informado a
coluna assume o nome da tabela da entity.
nullable Informa se o valor pode ser null.
precision Precisão da coluna decimal.
scale Número de casas decimais, usado somente em coluna com número
decimal.
table Nome da tabela que contém está coluna, se não for informado
assume o nome da tabela da entity.
unique Informa se a coluna é chave única.
updatable Informa se a coluna deve ser incluída no SQL de update, por padrão
é true.
Exemplo:
@Column(name="DATA_VALIDADE")
@Temporal(value=TemporalType.DATE)
private Date dataValidade;
javax.persistence.SequenceGenerator
Propriedade Descrição
name Nome único para o gerador que pode ser referenciado por uma ou
mais classes que pode ser utilizado para gerar valores de chave
primaria.
allocationSize A quantidade que será incrementada na sequence, o padrão é 50.
initialValue Valor inicial da sequence.
sequenceName Nome da sequence do banco de dados.
Exemplo:
Criar uma Entity para representar a tabela PRODUTO e no banco de dados temos
criado uma SEQUENCE chamada SEQ_PRODUTO que deve ser usada para geração
do ID da tabela.
@Entity
@SequenceGenerator(name="SEQ_PROD", sequenceName="SEQ_PRODUTO", initialValue=1,
allocationSize=1)
public class Produto {
...
}
javax.persistence.GeneratedValue
Define a estratégia para criar o ID, pode ser tipo AUTO (incrementa
automaticamente 1, 2, 3 em sequência) ou utilizando uma SEQUENCE.
Propriedade Descrição
generator Nome do gerador da chave primaria que é especificado na anotação
@SequenceGenerator ou @TableGenerator.
Strategy Estratégia de geração de chave primaria que o serviço de persistência
precisa usar para gerar a chave primaria.
Seu valor pode ser obtido através da enum
javax.persistence.GenerationType, os valores podem ser AUTO,
IDENTITY, SEQUENCE ou TABLE.
Exemplo:
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
...
}
@Entity
@SequenceGenerator(name="SEQ_PROD", sequenceName="SEQ_PRODUTO", initialValue=1,
allocationSize=1)
public class Produto {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_PROD")
6
private Long id;
...
}
javax.persistence.Temporal
Propriedade Descrição
Value O tipo usado para mapear java.util.Date e java.util.Calendar.
Seu valor pode ser obtido através da enum
javax.persistence.TemporalType, os valores podem ser DATE, TIME e
TIMESTAMP.
Exemplo:
@Column(name="DATA_VALIDADE")
@Temporal(value=TemporalType.DATE)
private Date dataValidade;
Criar um atributo para representar a coluna ENTRADA da tabela VALET, sendo que o
tipo desta coluna no banco de dados representa uma data e hora.
@Entity
public class Valet {
@Temporal(value=TemporalType.TIMESTAMP)
private Date entrada;
Criar um atributo para representar a idade do cliente e não deve ser persistido no
banco de dados.
@Entity
public class Cliente {
@Transient
private Integer idade;
Agora que vimos as notações utilizadas pelo JPA, vamos a nossa aplicação,
vamos criar telas de cadastro para esses 3 (três) beans que representam tabelas no
BD, necessitaremos de uma quantidade excessiva de programação, o aluno deve se
empenhar para terminar o código a tempo, pois esta será uma aplicação JSF completa
com JPA.
package br.com.grandeporte.entity.model;
import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
/**
* @author Rogério Aparecido dias
* The persistent class for the usuario database table.
*/
@Entity
public class Usuario implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Lob
private String cpf;
@Temporal(TemporalType.DATE)
@Column(name="data_cadastro")
private Date dtCadastro;
public Usuario() {}
Getters e Setters ...
package br.com.grandeporte.entity.model;
import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
/**
* @author Rogério Aparecido dias
* The persistent class for the produto database table.
*/
@Entity
public class Produto implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Temporal(TemporalType.DATE)
@Column(name="data_cadastro")
private Date dtCadastro;
6
private String nome;
package br.com.grandeporte.entity.model;
import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
/**
* @author Rogério Aparecido dias
* The persistent class for the categorias database table. *
*/
@Entity
@Table(name="categorias")
public class Categoria implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Temporal(TemporalType.DATE)
@Column(name="data_cadastro")
private Date dtCadastro;
package br.com.grandeporte.DAO.model;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import entidades.Usuario;
/**
* @author Rogério Aparecido dias
*/
public abstract class UsuarioDAO {
public UsuarioDAO() {}
package br.com.grandeporte.DAO.model;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import entidades.Categoria;
/**
* @author Rogério Aparecido dias
*/
public abstract class CategoriaDAO {
public CategoriaDAO() {}
6
public static void alterCat(Categoria cat) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.merge(cat);
em.getTransaction().commit();
System.out.println("Alterado com sucesso!");
} catch (Exception e) {
System.out.println("Erro ao alterar!/n" + e);
} finally {
em.close();
}
}
package br.com.grandeporte.beans.controller;
import javax.faces.event.*;
import java.sql.Date;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import br.com.grandeporte.DAO.model.UsuarioDAO;
import br.com.grandeporte.entity.model.Usuario;
/**
* @author Rogério Aparecido dias
* ManagedBean que será nossa classe de controle do xhtml com as classes do pacote model.
*/
@ManagedBean
@RequestScoped
public class UsuarioBean {
public UsuarioBean() {
usu = new Usuario();
}
package br.com.grandeporte.beans.controller;
import javax.faces.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import br.com.grandeporte.DAO.model.CategoriaDAO;
import br.com.grandeporte.entity.model.Categoria;
/**
* @author Rogério Aparecido dias
* ManagedBean que será nossa classe de controle do xhtml com as classes do pacote model.
*/
@ManagedBean
@RequestScoped
public class CategoriasBean {
private Categoria cat;
private List<Categoria> arrCat;
6
public CategoriasBean() {
cat = new Categoria();
refresLista();
}
Vamos criar agora nossas páginas xhtml, vamos começar com a de nome
cadusuario.xhtml
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>CRUD_JSF_JPA</title>
</h:head>
<h:body>
<h2>CADASTRAR USUÁRIO!</h2>
<h:form>
<h:panelGrid columns="2">
<h:body>
<h2>CADASTRAR CATEGORIAS DE PRODUTOS!</h2>
<h:form>
<h:panelGrid columns="2">
<h:commandButton value="Gravar"
actionListener="#{categoriasBean.gravarCat}"></h:commandButton>
</h:panelGrid>
</h:form>
<h:dataTable value="#{categoriasBean.arrCat}" var="cat" border="1">
<f:facet name="header">Categorias </f:facet>
<h:column>
<f:facet name="header">ID </f:facet>
#{cat.id}
</h:column>
<h:column>
<f:facet name="header">Descrição </f:facet>
#{cat.descriacao}
</h:column>
<h:column>
<f:facet name="header">Abilitado </f:facet>
#{cat.flag}
</h:column>
<h:column>
<f:facet name="header">DATA CADASTRO </f:facet>
#{cat.dtCadastro}
</h:column>
</h:dataTable>
</h:body>
</html>
O sistema irá
apresentar a
tela da
esquerda,
preencha os
dados confor-
me Imagem da
direita, clique
no botão
6
Gravar
em.getTransaction().commit();
st.executeUpdate(sqlInsert);
em.close();
} close();
...
O diagrama acima mostra muito bem como funciona uma conexão feita pela
classe EntityManagerFactory, reparem que o parâmetro de entrada
obrigatóriamente é o nome inserido no arquivo persistence.xml:
Interface EntityManager
6
transação, pois os métodos persist(), merge() e remove() precisam de um transação
para realizar suas operações no banco de dados.
Utilizamos o método find da EntityManager que pesquisa uma Entity Pessoa pela sua
classe e a chave primaria.
A String que este método recebe como parâmetro é uma QL, parecida com a
linguagem SQL, porém com algumas modificações.
Estou fera!
Fiz Certo!