quinta-feira, 11 de junho de 2009

Iniciando com JSF (Tutorial com exemplo prático)

Nesta postagem será mostrado um exemplo prático (CRUD de pessoas) para aqueles que desejam iniciar o uso da tecnologia JSF. Para isso, será utilizado o servidor de aplicação Apache Tomcat 6.0 e a IDE Eclipse Ganymede.

Para começar, é preciso criar um novo projeto. No Eclipse, basta abrir o menu file conforme mostrado na figura 1. Em seguida, será aberta uma tela para escolher o tipo de aplicação que será desenvolvida. No caso do exemplo, selecione Dynamic Web Project (figura 2) e clique no botão Next.
Na seqüência, dê um nome para o projeto (no exemplo será jsfdemo) e selecione a combo Target RunTime para Apache Tomcat v6.0 (figura 3). Depois, clique no botão Finish que o projeto estará criado.

Um vez criado o projeto, é necessário configurar o ambiente para que a aplicação funcione. Para isso, faça o download da ultima versão do JSF e extraia os jars para a pasta WEB-INF/lib do projeto. Por fim, é necessário configurar o web.xml do projeto, cuja configuração é mostrada na listagem 1.


Figura 1:Novo projeto


Figura 2: Dynamic Web Project


Figura 3: Configuração inicial do projeto


<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
</web-app>
Listagem 1: web.xml

A partir deste ponto já podemos começar a efetivamente desenvolver a aplicação de exemplo.

Construindo a aplicação

Para iniciar, vamos criar os seguintes pacotes na projeto:
  • com.sample.controller;
  • com.sample.dao;
  • com.sample.model.
A figura 4 ilustra a organização dos pacotes no eclipse.

Figura 4: Pacotes

Dentro do pacote model vamos criar a classe pessoa cujo código é listado na listagem 2.

package com.sample.model;

public class Pessoa {
private Integer id;
private String nome;
private String nacionalidade;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getNome() {
return nome;
}

public void setNome(String nome) {
this.nome = nome;
}

public String getNacionalidade() {
return nacionalidade;
}

public void setNacionalidade(String nacionalidade) {
this.nacionalidade = nacionalidade;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pessoa other = (Pessoa) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
Listagem 2: Pessoa.java

Dentro do pacote dao vamos definir a interface PessoaDao cujo código é mostrado na listagem 3.
package com.sample.dao;

import java.util.List;

import com.sample.model.Pessoa;

public interface PessoaDao {
void save(Pessoa pessoa);
void delete(Integer id);
Pessoa getById(Integer id);
List<Pessoa> findAll();
}
Listagem 3: PessoaDao.java

Dentro do pacote dao é necessário criar também a implementação da interface PessoaDao. No caso do exemplo será definido a classe PessoaDaoImpl (listagem 4).
package com.sample.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sample.model.Pessoa;

public class PessoaDaoImpl implements PessoaDao {
private static PessoaDaoImpl INSTANCE = new PessoaDaoImpl();
private static Map<Integer, Pessoa> database
= new HashMap<Integer, Pessoa>();
private static Integer nextId = 0;

private PessoaDaoImpl() {
}

public static PessoaDaoImpl getInstance() {
return INSTANCE;
}

@Override
public void save(Pessoa pessoa) {
if (pessoa != null) {
if (pessoa.getId() == null) {
nextId++;
pessoa.setId(nextId);
}
database.put(pessoa.getId(), pessoa);
}
}

@Override
public void delete(Integer id) {
if (id != null)
database.remove(id);
}

@Override
public Pessoa getById(Integer id) {
return database.get(id);
}

@Override
public List<Pessoa> findAll() {
return new ArrayList<Pessoa>(database.values());
}
}
Listagem 4: PessoaDaoImpl.java

Dentro do pacote controller vamos definir a classe PessoaController que será o nosso managed bean (listagem 5).
package com.sample.controller;

import java.util.List;

import javax.faces.context.FacesContext;

import com.sample.dao.PessoaDao;
import com.sample.dao.PessoaDaoImpl;
import com.sample.model.Pessoa;

public class PessoaController {
private PessoaDao pessoaDao = PessoaDaoImpl.getInstance();
private Pessoa pessoa;

public PessoaController() {
pessoa = new Pessoa();
}

public void save() {
pessoaDao.save(pessoa);
pessoa = new Pessoa();
}

public void edit() {
// pega o parametro passado no link
Integer id = Integer.parseInt((String)
FacesContext.getCurrentInstance().getExternalContext()
.getRequestParameterMap().get("id"));
pessoa = pessoaDao.getById(id);
}

public void delete(){
// pega o parametro passado no link
Integer id = Integer.parseInt((String)
FacesContext.getCurrentInstance().getExternalContext()
.getRequestParameterMap().get("id"));
pessoaDao.delete(id);
}

// getters e setters
public Pessoa getPessoa() {
return pessoa;
}

public void setPessoa(Pessoa pessoa) {
this.pessoa = pessoa;
}

public List<Pessoa> getPessoas() {
return pessoaDao.findAll();
}
}
Listagem 5: PessoaController.java

Vamos agora configurar o faces-config.xml (localizado dentro da pasta WEB-INF) cuja configuração é mostrada na listagem 6.


<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
<navigation-rule>
<from-view-id>pessoa.jsp</from-view-id>
<navigation-case>
<from-outcome>*</from-outcome>
<to-view-id>pessoa.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<managed-bean>
<managed-bean-name>pessoaController</managed-bean-name>
<managed-bean-class>
com.sample.controller.PessoaController
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>
Listagem 6: faces-config.xml

Por fim, vamos criar nossa página pessoa.jsp (listagem 7).


<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<html>
<f:view>
<head>
<title><h:outputText value="Desvendando JSF" /></title>
</head>
<body>
<h:form>
<table>
<tr>
<td><h:outputText value="Nome" />:</td>
<td><h:inputText value="#{pessoaController.pessoa.nome}" /></td>
</tr>
<tr>
<td><h:outputText value="Nacionalidade" />:</td>
<td><h:inputText value="#{pessoaController.pessoa.nacionalidade}" /></td>
</tr>
<tr>
<td><h:commandButton value="salvar" action="#{pessoaController.save}" /></td>
</tr>
</table>
<h:dataTable value="#{pessoaController.pessoas}"
var="p" rendered="#{not empty pessoaController.pessoas}" border="1">
<h:column>
<f:facet name="header">
<h:outputText value="Nome" />
</f:facet>
<h:commandLink value="#{p.nome}" action="#{pessoaController.edit}">
<f:param name="id" value="#{p.id}" />
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Nacionalidade" />
</f:facet>
<h:commandLink value="#{p.nacionalidade}" action="#{pessoaController.edit}">
<f:param name="id" value="#{p.id}" />
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Excluir" />
</f:facet>
<h:commandLink value="excluir" action="#{pessoaController.delete}">
<f:param name="id" value="#{p.id}" />
</h:commandLink>
</h:column>
</h:dataTable>
</h:form>
</body>
</f:view>
</html>
Listagem 7: pessoa.jsp

A partir deste ponto, com as definições acima, podemos vizualizar a aplicação através da URL http://localhost:8080/jsfdemo/pessoa.faces .

Veja uma prévia do funcionamento dela (figura 5). Trata-se de um CRUD básico de pessoa.

Figura 5: Aplicação JSF


Um excelente referencia para quem deseja aprender conceitos relacionados ao JSF é o livro Core JavaServer Faces.

Os fontes do exemplo (incluindo Jars) estão disponíveis aqui.

Até!

Veja também: