No TDC2011 (SP) além de me divertir e aprender bastante também apresentei, na trilha Java EE, a palestra: "RichFaces 4: Desenvolvimento Web com JSF2 mais rico". Iniciei a palestra comentando sobre as vantagens em adotar uma suíte de componentes UI (User Interface) terceira no desenvolvimento de aplicativos web com JavaServer Faces versão 2.
Mas o foco da palestra foi explorar os novos recursos do RichFaces 4, uma das mais famosas suítes para desenvolvimento JSF, a nova versão recentemente lançada completamente compatível com JSF 2.
Nesse post vou explorar um pouco mais algumas uma funcionalidades citadas na palestra: RichFaces Client Side Validation (CSV), a validação de campos do RichFaces 4 com Bean Validation. Mais uma vez utilizei nossa cobaia para experiências com JSF, o ScrumToys.
Bean Validation no lado cliente
O novo componente rich:validator, do RichFaces 4, pode ser vinculado a componentes inputs em uma tela para aplicar validações de acordo com as restrições definidas através das anotação do Bean Validation.
O Bean Validation é uma especificação Java EE 6 (JSR 303) que padroniza um mecanismo de validação, aplicado a objetos que seguem o modelo JavaBean, configurados a partir de anotações. Os containers que implementam o Java EE 6 utilizam um provider do Bean Validation, como o Hibernate Validator por exemplo. Mas nesse caso as validações são processadas pelo container, no lado servidor.
Com o rich:validator as validações do Bean Validation ocorrem no browser, no lado cliente. O código a seguir demonstra trechos da entidade Story, com as anotações demarcando validações que deverão ser aplicadas no cadastro da entidade. Nesse caso o nome não pode ser nulo, deve conter no mínimo 3 e no máximo 5 caracteres, enquanto a prioridade dever estar entre 1 e 5. Veja:
(Story.java)
//... import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.validation.constraints.Min; import javax.validation.constraints.Max; @Entity //... definicao de tables e namedqueries da entidade public class Story extends AbstractEntity implements Serializable { @NotNull @Size(min=3, max=60) @Column private String name; @Min(value=1) @Max(value=5) private int priority; //... outros atributos e os metodos da entidade }
No próximo trecho de código o uso do rich:validator dentro os inputs das propriedades name e priority da entidade Story. Um detalhe importante para a validação funcionar corretamente é utilizar em conjunto o componente rich:message ou rich:messages, responsáveis por exibir na tela as mensagens caso a validação reclame:
(\story\create.xhtml)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"> <ui:composition template="/template.xhtml"> ... <ui:define name="content"> <h:form styleClass="scrumForm" id="createStoryForm"> <h:panelGrid columns="3"> <h:outputLabel value="Name:" for="itName"/> <h:inputText id="itName" value="#{storyManager.currentStory.name}"> <rich:validator /> </h:inputText> <rich:message for="itName" styleClass="errorMessage"/> <h:outputLabel value="Priority:" for="itPriority" /> <h:inputText id="itPriority" value="#{storyManager.currentStory.priority}"> <rich:validator /> </h:inputText> <rich:message for="itPriority" styleClass="errorMessage"/> ... </h:panelGrid> </h:form> </ui:define> </ui:composition> </html>
Ao renderizar a página no browser, o código javascript gerado para a validação na camada cliente será parecido com o demonstrado a seguir (apliquei uma formatação básica pra melhorar a visualização):
(javascript gerado na tela de cadastro de uma nova Story)
function createStoryForm_3AitName_3Av(event,id,e,da){ var p={da:da, v:[{f:RichFaces.csv.validateSize, p:{"min":3,"max":60}, m:{"detail":"size must be between 3 and 60", "severity":0, "summary":"size must be between 3 and 60"}}, {f:RichFaces.csv.validateRequired, p:{}, m:{"detail":"may not be null", "severity":0, "summary":"may not be null"}}]}; RichFaces.csv.validate(event,id,e,p); } function createStoryForm_3AitPriority_3Av(event,id,e,da){ var p={da:da, c:{f:RichFaces.csv.convertInteger,p:{}, m:{"detail":"{2}: ''{0}'' must be a number between \u002D2147483648 and 2147483647 Example: {1}", "severity":0, "summary":"{2}: ''{0}'' must be a number consisting of one or more digits."} }, v:[{f:RichFaces.csv.validateMin, p:{"value":1}, m:{"detail":"must be greater than or equal to 1", "severity":0, "summary":"must be greater than or equal to 1"}}, {f:RichFaces.csv.validateMax,p:{"value":5}, m:{"detail":"must be less than or equal to 5", "severity":0, "summary":"must be less than or equal to 5"}}]}; RichFaces.csv.validate(event,id,e,p); } $(document).ready(function() { new RichFaces.ui.Message("createStoryForm:j_idt68", {"forComponentId":"createStoryForm:itName", "showSummary":false, "showDetail":true} ) new RichFaces.ui.Message("createStoryForm:j_idt74", {"forComponentId":"createStoryForm:itPriority", "showSummary":false, "showDetail":true}) });
Analisando o restante do html é possível identificar que as 2 funções javascript são associadas ao evento onchange dos 2 inputs. Esse é o comportamento padrão do rich:validator, mas é possível customizar outro evento através da propriedade event, por exemplo:
(\story\create.xhtml)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"> ... <h:outputLabel value="#{i18n['story.form.label.name']}:" for="itName"/> <h:inputText id="itName" value="#{storyManager.currentStory.name}"> <rich:validator event="keyup" /> </h:inputText> <rich:message for="itName" styleClass="errorMessage"/> ... </html>
Os validadores JSF, como por exemplo o f:validateRange, funcionam mesmo quando misturados ao mesmo input que usa o rich:validator, mas isso não é recomendado. Adotando Bean Validation a configuração para validar os dados de uma entidade pode ser reaproveitada em várias camadas do aplicação.
Caso não exista código lado cliente (javascript) registrado para uma determinada validação, o rich:validator executa a validação no lado servidor via Ajax (Ajax fall-backs). Outro exemplo do uso e mais detalhes sobre o rich:validator estam disponíveis na documentação do RichFaces 4.
Links complementares:
[]s
Eder Magalhães
www.yaw.com.br
twitter.com/youandwe
twitter.com/edermag
Comentários