O PrettyFaces possui um mecanismos que facilita a chamada de métodos através da URL no JSF,pois já possui um filtro implementado escutando a configuração feita no pretty-config.xml.
No exemplo a baixo será uma simulação de uma loja virtual, que ao clicar no produto abre a página do produto com a URL formatada em : produto/Categoria/ID/Descrição e o parâmetro de ação será o ID do produto ou seja qualquer alteração nos outros parâmetro não será chamado o Controller/ManagedBean.
Dependências
pom.xml
<dependency> <groupid>org.ocpsoft.rewrite</groupid> <artifactid>rewrite-servlet</artifactid> <version>2.0.4.Final</version> </dependency> <dependency> <groupid>org.ocpsoft.rewrite</groupid> <artifactid>rewrite-config-prettyfaces</artifactid> <version>2.0.4.Final</version> </dependency> <dependency> <groupid>org.ocpsoft.rewrite</groupid> <artifactid>rewrite-integration-cdi</artifactid> <version>2.0.4.Final</version> </dependency>
Configuração
Criar o arquivo pretty-config.xml dentro de webapp/WEB-INF.
O filtro do prettyFaces apenas serão executados nos xhtml que estiverem referenciados dentro do pretty-config, caso não esteja dentro do arquivo terão o comportamento normal de xhtml dentro do JSF.
pretty-config.xml
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd"> <url-mapping id="viewListaProduto"> <pattern value="/pages/listaProdutos" /> <view-id value="/pages/listaProdutos.xhtml" /> </url-mapping> <url-mapping id="viewProduto"> <pattern value="/pages/produto/#{categoria}/#{idProduto : produtoController.idUrlParametro}/#{descricao}" /> <view-id value="/pages/produto.xhtml" /> <action>#{produtoController.abrirProduto}</action> </url-mapping> </pretty-config>
- pattern : URL a ser apresentanda
- view-id : Arquivo xhtml que deverá ser escutado pelo filtro.
- action : Método do controller/ManagedBean a ser chamado ao renderizar página.
Existem 2 formas de passar parâmetros no pattern :
- Parâmetro da request: É apenas adicionado uma variável após o separador “/”, que esperará o valor de parâmetro vindo da request, ex : #{categoria}
- Referenciar um atributo do Controller/ManagedBean: A variável da URL receberá o valor que estiver no campo referenciado do Controller/ManagedBean, ex : #{idProduto : produtoController.idUrlParametro}
- No atributo pattern podem sem adicionado quantos parâmetros forem preciso separados por “/”;
- A quantidade de parâmetros esperados no patterns deve ser a mesma quantidade passada na chamada da página, caso não for será lançada uma a exception e a tela não será renderizada;
Implementação
Criar um Controller/ManagedBean para gerenciar criar uma lista de produtos, armazenar o id do produto selecionado para enviar por parametro e consultar id vindo por parametro.
ProdutoController.java
import java.io.Serializable; import java.util.List; import javax.annotation.PostConstruct; import javax.ejb.EJB; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import javax.faces.validator.ValidatorException; import org.business.teste.product.Product; import org.business.teste.service.product.IProductService; @ManagedBean(name = "produtoController") @SessionScoped public class ProdutoController implements Serializable { private static final long serialVersionUID = 1L; private List<Produto> produtos; private Produto produtoSelecionado; private String idProdutoUrl; @EJB private IProductService productService; @PostConstruct public void listarTodosProdutos() { this.produtos = this.productService.findAll(); } public void abrirProduto() { try { this.produtoSelecionado = this.productService.findById(Long.valueOf(this.idProdutoUrl)); } catch(NumberFormatException ne) { throw new ValidatorException(new FacesMessage("Parametro Inválido")); } }
- Criar uma lista de produtos e carrega – lá para utilizar na listagem de produtos;
- Criar um atributo idProdutoUrl para armazenar o valor do id do produto a ser pesquisado;
- Criar um método que consulte o produto pelo id vindo do parâmetro idProdutoUrl;
Criar uma página para a listagem de todos os produtos.
produtos.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui" xmlns:pretty="http://ocpsoft.com/prettyfaces"> <body> <h:form> <h2>Lista de Produtos</h2> <p:dataTable value="#{produtoController.produtos}" var="product" rows="5" style="width: 40%" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" rowsPerPageTemplate="5,10,15"> <p:column headerText="ID" sortBy="#{produto.id}" > <h:outputText value="#{produto.id}" /> </p:column> <p:column headerText="Categoria" sortBy="#{produto.categoria}"> <h:outputText value="#{produto.categoria}" /> </p:column> <p:column headerText="Decrição" sortBy="#{produto.descricao}"> <h:outputText value="#{produto.descricao}" /> </p:column> <p:column headerText="Opções" > <pretty:link mappingId="viewProduto" title="Open"> <h:outputLabel value="Open " /> <f:param value="#{produto.categoria}" /> <f:param value="#{produto.id}" /> <f:param value="#{produto.descricao}" /> </pretty:link> </p:column> </p:dataTable> </h:form> </body> </html>
Feito a lista de produtos é preciso um link para seleção do produto selecionado para enviar os parâmetros necessários para construir a URL e realizar a consulta para carregar o produtoSelecionado.
- pretty:link : Componente do prettyFaces que tem um comportamento similar do h:link ou seja é processado no lado do cliente;
- mappingId : É o atributo que define qual configuração do pretty-config.xml utilizar quando clicar no link;
- f:param : É os valores dos parâmetro esperado na configuração do viewProduto no pretty-config.xml, ou seja, foram configurado 3 parâmetros então é necessário enviar 3 parâmetros;
Utilizando o componente pretty:link facilita o envio de parâmetros, usando a tag f:param para definir os parâmetros e apenas se preocupando com o tipo(apenas tipos primitivos) e a ordem deles.
Criar uma página para abrir o produto.
produto.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui" xmlns:pretty="http://ocpsoft.com/prettyfaces"> <body> <h1>Produto</h1> <h:form> <h:panelGrid columns="2"> <h:outputLabel value="ID: " /> <h:outputLabel value="#{produtoController.produtoSelecionado.id}" /> <h:outputLabel value="Categoria: " /> <h:outputLabel value="#{produtoController.produtoSelecionado.categoria}" /> <h:outputLabel value="Descrição: " /> <h:outputLabel value="#{produtoController.produtoSelecionado.descricao}" /> </h:panelGrid> <br /> <pretty:link mappingId="viewListaProduto"> <h:outputLabel value="Voltar" /> </pretty:link> </h:form> </body> </html>
Ao clicar no link do produto na página produtos.xml, segundo a configuração do pretty-config, será chamada a action : produtoController.abrir() que pegará o valor do idProdutoUrl e fará uma consulta no banco de dados para carregar o produtoSeleciado em seguida, seguindo a configuração, será redirecionado para página de produto.xhtml.
O único parâmetro que afeita na ação é o segundo (id), então qualquer alteração nos outros parâmetros não será executado nada.
Resultado : http://localhost:8080/projeto/produto/CALCA/1/CALCA-JEANS