Aula 11: Introdução ao Jakarta Faces com Quarkus
Objetivos
- Compreender o que é Jakarta Faces e seu papel no ecossistema Jakarta EE
- Dominar os conceitos de componentes, Managed Beans, ciclo de vida e Facelets
- Integrar Jakarta Faces com Quarkus 3.31 para aplicações cloud-native
- Utilizar PrimeFaces para componentes visuais ricos e modernos
- Implementar uma aplicação de saudação completa, do zero ao deploy
Conteúdo
Contexto e Motivação
O desenvolvimento de aplicações web Java passou por diversas transformações ao longo das últimas décadas. Entre os frameworks mais tradicionais, o Jakarta Faces (antigo JSF — JavaServer Faces) se destaca por oferecer uma abordagem baseada em componentes para construção de interfaces ricas e dinâmicas. Com a ascensão do Quarkus, um framework moderno e otimizado para cloud-native, surge a oportunidade de unir o poder do Jakarta Faces à agilidade e leveza do Quarkus.
A escolha por Jakarta Faces não é apenas uma questão de tradição, mas de estratégia. Muitas empresas mantêm sistemas críticos em JSF, e migrar para soluções modernas pode ser caro e arriscado. Integrar JSF ao Quarkus permite modernizar gradualmente, aproveitando o que há de melhor em ambos os mundos: a robustez do JSF e a performance do Quarkus.
Jakarta Faces é amplamente utilizado em sistemas legados e corporativos. Aprender a integrá-lo ao Quarkus é estratégico para profissionais que desejam atuar em projetos de modernização.
Além disso, o mercado exige cada vez mais aplicações escaláveis, rápidas e preparadas para cloud. Quarkus foi criado para atender a essas demandas, e sua integração com Jakarta Faces permite que equipes aproveitem o conhecimento já existente em JSF, sem prescindir das vantagens do desenvolvimento cloud-native.
| Vantagem | Explicação |
|---|---|
| Modernização Gradual | Permite atualizar sistemas sem reescrever tudo do zero |
| Performance | Quarkus reduz tempo de inicialização e uso de memória |
| Cloud-Ready | Facilita o deploy em containers e ambientes cloud |
| Reaproveitamento | Utiliza o conhecimento e código JSF já existente |
Muitos desenvolvedores acreditam que JSF está obsoleto, mas grandes empresas e órgãos públicos ainda dependem fortemente desse framework. Saber integrá-lo ao Quarkus é um diferencial competitivo.
O que é Jakarta Faces?
Jakarta Faces é um framework MVC (Model-View-Controller) para construção de interfaces web em Java. Ele utiliza páginas XHTML como "View", beans gerenciados como "Model" e um ciclo de vida próprio para processar requisições e respostas.
Por que MVC? O padrão MVC separa a lógica de apresentação (View), a lógica de negócio (Model) e o controle do fluxo (Controller), facilitando manutenção, testes e evolução do sistema.
Principais conceitos:
- Componentes: Elementos reutilizáveis (botões, tabelas, formulários) definidos em XHTML. Cada componente JSF encapsula comportamento e aparência, facilitando a criação de interfaces ricas sem depender de JavaScript.
- Managed Beans: Classes Java que representam dados e lógica de negócio, integradas à interface. São gerenciados pelo contêiner, permitindo injeção de dependências e controle de ciclo de vida.
- Ciclo de Vida: Sequência de fases que processa requisições, valida dados, atualiza modelos e renderiza respostas. O ciclo de vida JSF garante que dados sejam validados e processados antes de serem exibidos ou persistidos.
- Facelets: Sistema de templates que facilita a composição de páginas. Permite criar layouts reutilizáveis e organizar o código XHTML de forma modular.
| Termo | Definição |
|---|---|
| Componentes | Elementos visuais reutilizáveis definidos em XHTML |
| Managed Beans | Classes Java que representam dados e lógica |
| Ciclo de Vida | Fases de processamento de requisições JSF |
| Facelets | Sistema de templates para páginas JSF |
O ciclo de vida do JSF é composto por seis fases principais: restauração da árvore de componentes, aplicação de valores de requisição, processamento de eventos, validação, atualização do modelo e renderização da resposta. Cada fase pode ser interceptada para customizar o comportamento da aplicação.
Por que usar com Quarkus?
Quarkus traz diversos benefícios importantes para o desenvolvimento moderno de aplicações Java. Em primeiro lugar, oferece inicialização ultrarrápida que reduz drasticamente o tempo de startup das aplicações. Além disso, apresenta baixo consumo de memória, tornando as aplicações mais eficientes em termos de recursos. O framework também traz suporte nativo a containers e cloud, facilitando o deploy em ambientes modernos. Por fim, possui integração facilitada com CDI, JPA e outros padrões Jakarta EE.
A combinação de Jakarta Faces com Quarkus resulta em diversos benefícios: interfaces ricas e reativas, backend moderno, leve e escalável, e grande facilidade de integração com APIs REST, microserviços e persistência de dados.
A integração entre Jakarta Faces e Quarkus permite que aplicações legadas ganhem performance e estejam prontas para ambientes cloud-native.
| Característica | JSF Tradicional | JSF com Quarkus |
|---|---|---|
| Inicialização | Lenta | Rápida |
| Consumo de Memória | Alto | Baixo |
| Deploy em Cloud | Complexo | Simples (Docker/Kubernetes) |
| Integração com APIs | Limitada | Facilitada |
Quarkus foi projetado para funcionar bem com GraalVM, permitindo compilar aplicações desenvolvidas utilizando Java em binários nativos. Isso reduz drasticamente o tempo de inicialização e o consumo de recursos, tornando JSF viável até para microserviços.
Exercícios (Checkpoints)
Laboratório 6 — Jakarta Faces com Quarkus
Nesta seção, vamos construir uma aplicação de cadastro de usuários utilizando Jakarta Faces com Quarkus, detalhando cada etapa e explicando o propósito de cada decisão técnica.
Passo 1: Configuração do Projeto
A configuração inicial é fundamental para garantir que todos os recursos do Quarkus e do PrimeFaces estejam disponíveis. O PrimeFaces oferece componentes visuais muito mais ricos que o JSF básico, facilitando a criação de interfaces modernas e responsivas.
Para a criação do projeto, utilize o Maven com o plugin do Quarkus indicando a extensão do PrimeFaces:
mvn io.quarkus.platform:quarkus-maven-plugin:3.31.0:create \
-DprojectGroupId=com.exemplo \
-DprojectArtifactId=faces-quarkus \
-Dextensions="quarkus-primefaces"
Vamos utilizar o projeto desenvolvido no laboratório anterior como base, adicionando as dependências e configurações necessárias para o JSF.
No arquivo pom.xml, inclua as dependências do PrimeFaces para Quarkus 3. Isso garante que todos os componentes avançados estejam disponíveis:
<dependency>
<groupId>io.quarkiverse.primefaces</groupId>
<artifactId>quarkus-primefaces</artifactId>
<version>3.15.7</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.primefaces</groupId>
<artifactId>quarkus-primefaces-extensions</artifactId>
<version>3.15.7</version>
</dependency>
O PrimeFaces 3.15.7 é a versão mais atual e compatível com Quarkus 3, oferecendo componentes Ajax, gráficos, calendários e muito mais, prontos para uso.
Passo 2: Estrutura de Diretórios
Organizar os arquivos é essencial para facilitar a manutenção e evolução do projeto. No Quarkus, a estrutura de diretórios segue algumas convenções específicas que diferem ligeiramente do Jakarta EE tradicional.
Por que a estrutura de diretórios é importante? Uma organização adequada dos arquivos facilita a localização de componentes, simplifica a manutenção e permite que novos desenvolvedores compreendam rapidamente o projeto. No Quarkus, algumas convenções específicas garantem que os recursos sejam carregados corretamente.
Estrutura Recomendada para Quarkus + Jakarta Faces
src/
├── main/
│ ├── java/
│ │ └── br/upf/ads175/critiquehub/
│ │ ├── presentation/
│ │ │ ├── Saudacao.java # Bean de modelo
│ │ │ └── SaudacaoManagedBean.java # Bean gerenciado
│ │ └── service/
│ │ └── SaudacaoService.java # Serviços de negócio
│ ├── resources/
│ │ ├── META-INF/
│ │ │ └── resources/ # Recursos web do Quarkus
│ │ │ ├── index.xhtml # Página principal
│ │ │ ├── sobre.xhtml # Página sobre
│ │ │ └── css/
│ │ │ └── app.css # Estilos customizados
│ │ └── application.properties # Configurações da aplicação
│ └── webapp/
│ └── WEB-INF/
│ └── web.xml # Configuração JSF
└── test/
└── java/
└── br/upf/ads175/critiquehub/
└── presentation/
└── SaudacaoManagedBeanTest.java # Testes unitários
Detalhamento dos Diretórios
| Diretório | Propósito | Observações |
|---|---|---|
presentation/ | Beans de modelo e gerenciados (camada de apresentação) | Contém classes que interagem diretamente com a interface JSF |
service/ | Serviços de negócio e lógica de aplicação | Classes com anotações CDI (@ApplicationScoped, @RequestScoped) |
META-INF/resources/ | Páginas XHTML e recursos estáticos (específico do Quarkus) | Crucial: No Quarkus, páginas web devem estar aqui, não em webapp |
webapp/WEB-INF/ | Configurações do Jakarta Faces | Contém web.xml e outras configurações específicas do JSF |
resources/ | Arquivos de configuração da aplicação | application.properties, resources para templates, etc. |
Diferença Importante: No Quarkus, as páginas XHTML devem estar em src/main/resources/META-INF/resources/ e não em src/main/webapp/. Esta é uma convenção específica do Quarkus para servir recursos estáticos.
Convenções de Nomenclatura
Para manter consistência com o projeto CritiqueHub, seguiremos estas convenções:
- Pacotes: Usar o padrão
br.upf.ads175.critiquehub.{camada} - Beans de Modelo: Nomes simples (ex:
Saudacao,Usuario) - Beans Gerenciados: Sufixo
ManagedBean(ex:SaudacaoManagedBean) - Serviços: Sufixo
Service(ex:SaudacaoService) - Páginas XHTML: Nomes descritivos em minúsculas (ex:
index.xhtml,sobre.xhtml)
Dica de Organização: Mantenha a separação clara entre as camadas:
presentation/: Tudo relacionado à interface (beans JSF)service/: Lógica de negócio e serviçosmodel/ouentity/: Entidades de domínio (quando usar JPA)repository/: Acesso a dados (quando usar JPA)
Atenção: Se você colocar as páginas XHTML em src/main/webapp/ (como no Jakarta EE tradicional), elas não serão servidas corretamente pelo Quarkus. Sempre use src/main/resources/META-INF/resources/ para recursos web no Quarkus.
Passo 3: Criando o Bean de Modelo
O bean de modelo Saudacao representa os dados da saudação. Ele possui dois atributos: nome e mensagem, ambos com métodos getter e setter para permitir o binding (vinculação) com os componentes JSF.
O que é binding? É o mecanismo que conecta automaticamente os campos da interface com os atributos dos beans Java, permitindo que mudanças em um sejam refletidas no outro.
// Saudacao.java
package br.upf.ads175.critiquehub.presentation;
/**
* Bean de modelo para armazenar dados da saudação.
* Este é um POJO (Plain Old Java Object) simples que representa
* os dados que serão manipulados na interface.
*/
public class Saudacao {
private String nome; // Nome do usuário
private String mensagem; // Mensagem de saudação
/**
* Construtor padrão necessário para JSF
*/
public Saudacao() {
// Construtor vazio obrigatório
}
// Getter e setter para nome
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
// Getter e setter para mensagem
public String getMensagem() {
return mensagem;
}
public void setMensagem(String mensagem) {
this.mensagem = mensagem;
}
/**
* Método auxiliar para exibição formatada
*/
public String getSaudacaoCompleta() {
if (nome != null && mensagem != null &&
!nome.trim().isEmpty() && !mensagem.trim().isEmpty()) {
return nome + ", " + mensagem;
}
return "";
}
}
Os métodos getter e setter seguem a convenção JavaBeans, que é essencial para que o JSF consiga acessar e modificar os dados automaticamente através do Expression Language (EL).
Passo 4: Bean Gerenciado
O bean gerenciado SaudacaoManagedBean controla o ciclo de vida da saudação e expõe métodos para manipulação dos dados. Este é o Controller no padrão MVC.
// SaudacaoManagedBean.java
package br.upf.ads175.critiquehub.presentation;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;
/**
* Bean gerenciado para interação com a interface JSF.
* A anotação @Named torna este bean acessível via Expression Language (EL).
* A anotação @RequestScoped define que uma nova instância será criada
* a cada requisição HTTP.
*/
@Named
@RequestScoped
public class SaudacaoManagedBean {
private Saudacao saudacao = new Saudacao(); // Instância do modelo
/**
* Getter para o modelo.
* Este método é chamado pelo JSF quando #{saudacaoManagedBean.saudacao}
* é usado na página XHTML.
*/
public Saudacao getSaudacao() {
return saudacao;
}
/**
* Método para limpar os campos do formulário.
* Cria uma nova instância de Saudacao, efetivamente
* limpando todos os campos.
*/
public void limpar() {
saudacao = new Saudacao();
System.out.println("Formulário limpo"); // Log para debug
}
/**
* Método para demonstrar processamento de dados.
* Em uma aplicação real, aqui seria feita a persistência
* ou chamada de serviços de negócio.
*/
public void processar() {
System.out.println("Processando saudação: " + saudacao.getSaudacaoCompleta());
}
}
O escopo @RequestScoped significa que o bean existe apenas durante uma requisição HTTP. Para dados que precisam persistir entre requisições, use @SessionScoped ou @ViewScoped.
Passo 5: Página XHTML
A página index.xhtml define o formulário de saudação, vinculando os campos ao bean gerenciado. O uso de <f:ajax> permite atualização parcial da interface sem recarregar a página inteira.
Por que usar AJAX? O AJAX (Asynchronous JavaScript and XML) permite uma experiência mais fluida, atualizando apenas partes específicas da página em resposta às ações do usuário.
<!-- index.xhtml -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>CritiqueHub - Aplicação de Saudação</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.form-group { margin: 10px 0; }
.form-group label { display: inline-block; width: 100px; }
.form-group input { width: 200px; padding: 5px; }
.buttons { margin: 20px 0; }
.buttons button { margin-right: 10px; padding: 8px 16px; }
.output { margin-top: 20px; padding: 10px; background: #f5f5f5; }
</style>
</h:head>
<h:body>
<h1>Aplicação de Saudação JSF</h1>
<h:form id="saudacaoForm">
<!-- Campo para nome -->
<div class="form-group">
<h:outputLabel value="Nome:" for="nome"/>
<h:inputText id="nome"
value="#{saudacaoManagedBean.saudacao.nome}"
placeholder="Digite seu nome"/>
</div>
<!-- Campo para mensagem -->
<div class="form-group">
<h:outputLabel value="Mensagem:" for="mensagem"/>
<h:inputText id="mensagem"
value="#{saudacaoManagedBean.saudacao.mensagem}"
placeholder="Digite sua mensagem"/>
</div>
<!-- Botões de ação -->
<div class="buttons">
<!-- Botão para atualizar saudação -->
<h:commandButton value="Atualizar" styleClass="btn-primary">
<f:ajax execute="@form" render="saudacaoAtual"/>
</h:commandButton>
<!-- Botão para limpar campos -->
<h:commandButton value="Limpar"
action="#{saudacaoManagedBean.limpar}"
styleClass="btn-secondary">
<f:ajax execute="@form" render="@form"/>
</h:commandButton>
<!-- Botão para processar (demonstração) -->
<h:commandButton value="Processar"
action="#{saudacaoManagedBean.processar}"
styleClass="btn-success">
<f:ajax execute="@form" render="@none"/>
</h:commandButton>
</div>
<!-- Exibição da saudação atual -->
<div class="output">
<h:outputLabel value="Saudação Atual:" />
<h:outputText id="saudacaoAtual"
value="#{saudacaoManagedBean.saudacao.saudacaoCompleta}"
style="font-weight: bold; color: #2c5aa0;"/>
</div>
</h:form>
<!-- Informações de debug (apenas em desenvolvimento) -->
<div style="margin-top: 30px; font-size: 12px; color: #666;">
<h3>Informações de Debug:</h3>
<p>Bean Scope: Request Scoped</p>
<p>Nome atual: #{saudacaoManagedBean.saudacao.nome}</p>
<p>Mensagem atual: #{saudacaoManagedBean.saudacao.mensagem}</p>
</div>
</h:body>
</html>
O atributo execute="@form" faz com que todos os campos do formulário sejam enviados para o servidor, enquanto render="saudacaoAtual" atualiza apenas o elemento especificado.
Passo 6: Configuração Faces
A configuração do Faces Servlet no web.xml é obrigatória para que o JSF funcione corretamente. Ela define o mapeamento das páginas e o modo de operação do framework.
<!-- web.xml -->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
version="4.0">
<!-- Configuração do estágio de projeto (Development/Production) -->
<context-param>
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- Habilita estado de vista no cliente para melhor performance -->
<context-param>
<param-name>jakarta.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<!-- Configuração do Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Mapeamento para processar arquivos .xhtml -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<!-- Define a página inicial -->
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<!-- Configuração de timeout de sessão -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
A configuração PROJECT_STAGE como "Development" habilita mensagens de erro detalhadas e recursos de debug. Em produção, altere para "Production".
Passo 7: Executando a Aplicação
Para executar a aplicação, use o comando do Quarkus:
./mvnw quarkus:dev
A aplicação estará disponível em http://localhost:8080 e você verá:
- Campos de entrada: Nome e Mensagem
- Botão Atualizar: Mostra a saudação sem recarregar a página
- Botão Limpar: Limpa os campos usando AJAX
- Botão Processar: Demonstra ação do servidor
- Saída dinâmica: Mostra a saudação formatada
O Quarkus dev mode permite alterações em tempo real. Modifique o código e veja as mudanças instantaneamente no navegador.
Laboratório 7 — Jakarta Faces com PrimeFaces e Quarkus
Nesta seção, vamos construir uma aplicação simples de saudação utilizando Jakarta Faces com PrimeFaces e Quarkus, demonstrando os componentes básicos mais ricos que o JSF core tradicional.
Passo 1: Configuração do Projeto com PrimeFaces
Para criar o projeto, utilize o Maven com o plugin do Quarkus:
mvn io.quarkus.platform:quarkus-maven-plugin:3.31.0:create \
-DprojectGroupId=br.upf.ads175.critiquehub \
-DprojectArtifactId=faces-primefaces-basic \
-Dextensions="quarkus-primefaces"
A extensão quarkus-primefaces já inclui automaticamente o Jakarta Faces e todas as dependências necessárias.
Caso esteja adicionando ao projeto existente, inclua a dependência no pom.xml:
<dependency>
<groupId>io.quarkiverse.primefaces</groupId>
<artifactId>quarkus-primefaces</artifactId>
<version>3.15.7</version>
</dependency>
Passo 2: Estrutura Simplificada
src/
├── main/
│ ├── java/
│ │ └── br/upf/ads175/critiquehub/
│ │ └── SaudacaoController.java # Bean gerenciado
│ ├── resources/
│ │ ├── META-INF/
│ │ │ └── resources/
│ │ │ └── index.xhtml # Página principal
│ │ └── application.properties
│ └── webapp/
│ └── WEB-INF/
│ └── web.xml # Configuração JSF
Passo 3: Bean Gerenciado
Vamos criar um bean simples para controlar a aplicação de saudação:
// SaudacaoController.java
package br.upf.ads175.critiquehub;
import jakarta.enterprise.context.RequestScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Named;
/**
* Bean gerenciado para aplicação de saudação com PrimeFaces.
*/
@Named
@RequestScoped
public class SaudacaoController {
private String nome;
private String email;
private String mensagem = "";
/**
* Gera uma saudação personalizada.
*/
public void gerarSaudacao() {
if (nome != null && !nome.trim().isEmpty()) {
mensagem = "Olá, " + nome + "! Bem-vindo ao sistema CritiqueHub!";
if (email != null && !email.trim().isEmpty()) {
mensagem += " Seu email " + email + " foi registrado.";
}
// Adiciona mensagem de sucesso
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Sucesso!",
"Saudação gerada com sucesso!"));
} else {
mensagem = "";
// Adiciona mensagem de erro
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erro!",
"Por favor, digite seu nome!"));
}
}
/**
* Limpa todos os campos.
*/
public void limpar() {
nome = "";
email = "";
mensagem = "";
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Limpo!",
"Campos foram limpos!"));
}
// Getters e Setters
public String getNome() { return nome; }
public void setNome(String nome) { this.nome = nome; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getMensagem() { return mensagem; }
public void setMensagem(String mensagem) { this.mensagem = mensagem; }
public boolean isMensagemVazia() {
return mensagem == null || mensagem.trim().isEmpty();
}
}
Passo 4: Página XHTML com PrimeFaces
Agora vamos criar uma página simples comparando JSF core com PrimeFaces:
<!-- index.xhtml -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>CritiqueHub - Exemplo PrimeFaces</title>
</h:head>
<h:body style="padding: 20px; font-family: Arial;">
<h:form id="form">
<!-- Cabeçalho com PrimeFaces -->
<p:panel header="CritiqueHub - Exemplo Básico PrimeFaces"
style="margin-bottom: 20px;">
<p>Este exemplo demonstra a diferença entre JSF core e PrimeFaces</p>
</p:panel>
<!-- Seção: Comparação JSF Core vs PrimeFaces -->
<p:tabView>
<!-- Aba 1: PrimeFaces -->
<p:tab title="Com PrimeFaces">
<h:panelGrid columns="2" cellpadding="10">
<!-- Campo nome com PrimeFaces -->
<p:outputLabel for="nomePrime" value="Nome:*"
style="font-weight: bold;"/>
<p:inputText id="nomePrime"
value="#{saudacaoController.nome}"
placeholder="Digite seu nome"
required="true"
requiredMessage="Nome é obrigatório"
style="width: 300px;"/>
<!-- Campo email com validação -->
<p:outputLabel for="emailPrime" value="Email:"
style="font-weight: bold;"/>
<p:inputText id="emailPrime"
value="#{saudacaoController.email}"
placeholder="seu@email.com"
style="width: 300px;">
<f:validateRegex
pattern="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
validatorMessage="Email inválido"/>
</p:inputText>
<!-- Botões com ícones -->
<h:outputText value="" />
<h:panelGroup>
<p:commandButton value="Gerar Saudação"
action="#{saudacaoController.gerarSaudacao}"
update="form"
icon="pi pi-check"
styleClass="ui-button-success"
style="margin-right: 10px;"/>
<p:commandButton value="Limpar"
action="#{saudacaoController.limpar}"
update="form"
icon="pi pi-refresh"
styleClass="ui-button-secondary"/>
</h:panelGroup>
</h:panelGrid>
<!-- Resultado com PrimeFaces -->
<p:panel header="Resultado"
rendered="#{!saudacaoController.mensagemVazia}"
style="margin-top: 20px; background-color: #f0f8ff;">
<h:outputText value="#{saudacaoController.mensagem}"
style="font-size: 16px; color: #2e8b57;"/>
</p:panel>
</p:tab>
<!-- Aba 2: JSF Core (para comparação) -->
<p:tab title="JSF Core Tradicional">
<p style="color: #666; font-style: italic; margin-bottom: 20px;">
Para comparação, veja como seria com JSF core:
</p>
<pre style="background: #f5f5f5; padding: 15px; border-radius: 5px;">
<h:panelGrid columns="2">
<h:outputLabel value="Nome:" />
<h:inputText value="#{bean.nome}" />
<h:outputLabel value="Email:" />
<h:inputText value="#{bean.email}" />
<h:commandButton value="Gerar" action="#{bean.gerar}" />
<h:commandButton value="Limpar" action="#{bean.limpar}" />
</h:panelGrid>
<h:outputText value="#{bean.mensagem}"
rendered="#{!bean.mensagemVazia}" />
</pre>
<p:panel header="Limitações do JSF Core">
<ul>
<li>Sem validação visual automática</li>
<li>Campos simples sem placeholder</li>
<li>Botões sem ícones</li>
<li>Sem estilos modernos</li>
<li>Não responsivo</li>
<li>Sem componentes ricos (calendário, máscaras, etc.)</li>
</ul>
</p:panel>
</p:tab>
</p:tabView>
<!-- Demonstração de Componentes PrimeFaces -->
<p:panel header="Exemplos de Componentes PrimeFaces"
style="margin-top: 20px;">
<h:panelGrid columns="2" cellpadding="10">
<!-- Rating (Avaliação) -->
<p:outputLabel value="Avalie o exemplo:" style="font-weight: bold;"/>
<p:rating stars="5" cancel="false"/>
<!-- ProgressBar -->
<p:outputLabel value="Progresso:" style="font-weight: bold;"/>
<p:progressBar value="75"
labelTemplate="{value}% completo"
style="width: 300px;"/>
<!-- Switch/Toggle -->
<p:outputLabel value="Modo escuro:" style="font-weight: bold;"/>
<p:toggleSwitch value="false"/>
<!-- Chips (Tags) -->
<p:outputLabel value="Tecnologias:" style="font-weight: bold;"/>
<p:chips value="#{null}"
placeholder="Digite e pressione Enter"
style="width: 300px;"/>
</h:panelGrid>
</p:panel>
<!-- Mensagens do sistema -->
<p:messages autoUpdate="true" closable="true"
style="margin-top: 20px;"/>
</h:form>
</h:body>
</html>
Componentes PrimeFaces demonstrados:
- p:panel: Painéis com cabeçalho estilizado
- p:tabView: Abas para organizar conteúdo
- p:inputText: Campos com placeholder e validação visual
- p:commandButton: Botões com ícones e estilos
- p:messages: Sistema de mensagens elegante
- p:rating: Componente de avaliação por estrelas
- p:progressBar: Barra de progresso animada
- p:toggleSwitch: Switch moderno
- p:chips: Tags editáveis
Passo 5: Configuração Web.xml
<!-- web.xml -->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="4.0">
<!-- Modo desenvolvimento -->
<context-param>
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- Tema PrimeFaces -->
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>nova-light</param-value>
</context-param>
<!-- Configuração Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
Passo 6: Executando a Aplicação
Execute o comando:
./mvnw quarkus:dev
Acesse http://localhost:8080 e você verá:
- Interface com Abas: Compare PrimeFaces vs JSF core
- Campos Melhorados: Com placeholder e validação visual
- Botões Estilizados: Com ícones e cores
- Componentes Ricos: Rating, progressBar, toggleSwitch
- Mensagens Elegantes: Feedback visual das ações
- Layout Responsivo: Painéis organizados
Vantagens do PrimeFaces demonstradas:
- Produtividade: Componentes prontos para uso
- Experiência do Usuário: Interface moderna e responsiva
- Validação: Feedback visual automático
- Manutenibilidade: Código mais limpo e organizado
- Flexibilidade: Fácil personalização de temas
Este laboratório mostra de forma prática como o PrimeFaces eleva significativamente a qualidade das interfaces JSF, oferecendo componentes modernos sem complexidade adicional no desenvolvimento.
Relacionamento do Jakarta Faces com Demais Tecnologias
O Jakarta Faces conecta-se com as demais tecnologias vistas anteriormente, servindo como ponte entre as demais camadas da aplicação. No ecossistema Quarkus + Jakarta EE, a camada de apresentação (Faces) consome serviços CDI, que por sua vez utilizam JPA/Panache para persistência, criando uma arquitetura coesa e bem definida.