JSF - Java Server Faces Liane Marques Santos Universidade Tiradentes Pós-graduação em Análise de Sistemas com ênfase em WEB Rua A,111/1202.Jardins 49.025-100. Aju-Se-Brasil 55-79-217-3635 [email protected] Resumo este artigo. Finalmente a última seção conclui com alguns comentários pertinentes ao trabalho realizado. A implementação convencional de aplicações para Web em Java, request-response, trazia uma série de dificuldades para o seu desenvolvimento. Com o intuito de tornar esse trabalho mais simples, modularizada e semelhante ao modelo de componentes do AWT/Swing surge o Java Server Faces. O JSF como é também conhecido é um framework de desenvolvimento Web Java. Neste artigo foram abordadas várias características e facilidades; além da implementação de um pequeno exemplo mostrando algumas de suas funcionalidades. 2. MVC Modelo 2 no JSF O JSF utiliza a arquitetura MVC Modelo-2 para construção de formulários HTML, validando seus valores, invocando lógica de negocio e exibindo os resultados. Sua arquitetura pode ser visualizada pela representação abaixo (figura 1): Termos gerais [JSF]: Java Server Faces. Palavras chaves JSF, MVC modelo 2, Conversor, Events. Faces Servlet, Action, Validator, 1. INTRODUÇÃO O Java Server Faces (JSF) é um framework de desenvolvimento Java em que a principal característica é trazer para a web o modelo de componentes e eventos, semelhante ao AWT/Swing, ao contrário do modelo request/response que comumente é utilizado no desenvolvimento de aplicações para web. O objetivo é tornar mais simples a tarefa de construir aplicações web. É disponibilizado pelo framework um conjunto de componentes reusáveis e a separação da construção da interface de usuário a partir da qual é delegado o processamento do negócio em outra camada. A organização do artigo apresenta-se da seguinte forma: é dada uma visão geral de como o JSF utiliza o MVC modelo 2 (seção 2). Em seguida como são construídas as páginas utilizando as tags predefinidas e como é a relação destas com os componentes JSF (seção 3). A seção 4 trata de como as facilidades de Validações, Conversões, Eventos e Ações são abordados pelo framework. A seção seguinte mostra o objetivo e características das diversas fases do ciclo de vida de uma requisição no JSF. A sexta seção demonstra algumas configurações pertinentes e citadas durante (Figura 1)[1] A aplicação flui sob a mediação do Controller que é o responsável por despachar requisições e controlar seus fluxos, que no JSF é delegado ao servlet central chamado FacesServlet. O servlet controlador realiza os passos para preparar e disparar a resposta. Ele é responsável por receber requisições de clientes web, decidir qual função da lógica de negócio será executada e 1 depois delegar a responsabilidade de produzir a próxima fase da interface usuária para o componente View apropriado. O Model representa ou encapsula o estado interno ou ações que modificam o estado de uma aplicação. Em muitas aplicações, assim como no JSF, o estado interno da aplicação é representado por um conjunto de javabeans. Estes podem armazenar informações entre as camadas View e Model de uma aplicação web. Na figura 1 observamos que o objeto não é parte do modelo de objetos de negócio. A ligação entre esse objeto (javabean) e o objeto de negócio é feita no JSF primeiramente definindo-os como managed bean no arquivo de configuração. Desta forma esses managed beans poderão ser referenciados pelos componentes ui (componentes para interface de usuário), como veremos na seção seguinte. Depois de passar pela lógica de negócio o controle é normalmente mandado de volta do Controller para a View apropriada. Esse redirecionamento é usado pelos arquivos de configurações o que permite um baixo acoplamento entre o View e o Model, o que leva a uma maior facilidade na manutenção destas aplicações. No JSF a porção View é construída baseada em JSP’s com conteúdo estático HTML e tags próprias do framework JSF, cujo uso veremos na seção seguinte. <f:view> <!DOCTYPE …> <HTML> <HEAD>Login</HEAD> <BODY> <h:form id=”formLogin”> usuário: <h:inputText id=”usuario”/><BR> senha: <h:inputSecret id=”senha”/><BR> <h:commandButton value="Submeter" action="login"/> </h:form> </BODY></HTML> </f:view> Neste exemplo temos um formulário com dois campos de edição, (sendo o segundo para senha) e um botão de ação. Seria semelhante em HTML a: <form method="POST" action="login.jsp"> <p><input type="text" name="usuario"> <p><input type=" password" name="senha"> <p><input type="submit" value="login" name="B1"></p> </form> Numa representação simples da árvore de componentes no JSF teríamos: 3. Utilizando o JSF O JSF prove um conjunto de controles GUI (Graphical User Interface) pré-construídos orientados a HTML; um conjunto de API e tags customizadas associados a estes para construção de formulários com interface complexa. É fornecido pelo framework um número de componentes básicos, havendo a possibilidade de customizá-los. E a partir destes é possível compor componentes mais complexos. No JSF quando uma página é submetida, é construída em memória uma árvore com uma instância de UIComponent para cada tag de componente contidas na página. O JSF possui as tags libraries para componentes que estamos acostumados a utilizar em html, como veremos a seguir. Os componentes JSF representam controladores web como campos de texto, formulários, botões, tabelas, checkboxes, dentre outros. Num exemplo simples de um formulário contendo num segundo nível da hierarquia botões, caixa de texto, labels etc. Quando a página for submetida é construída uma árvore com esses componentes (correspondente as tags contidas na página). A tag de formulário tem seu componente correspondente UIForm, assim como a caixa de texto tem o UIInput e o botão o componente UICommand. A árvore irá seguir a hierarquia contida entre as tags e a relação com os componentes JSF. Os componentes se ajustam na hierarquia e podem ser compostos ou compor outros mais complexos <%@ taglib prefix="f" <%@ taglib prefix="h" uri="http://java.sun.com/jsf/core" %> uri="http://java.sun.com/jsf/html" %> Para que a árvore de componentes seja corretamente criada as tags JSF devem estar contidas entre <f:view> e </f:view>. O FacesServlet é o ponto de entrada do framework JSF. Ele lida com o processamento do ciclo de vida de uma requisição e age como um controlador frontal. Todas as requisições passam por ele. O JSF também apresenta a noção de binding tanto de valor quanto de métodos, o que significa que facilmente é feita a ligação entre as tags da página e os beans gerenciáveis da aplicação. Estes são configurados no arquivo faces-config e seu uso pode ser observado no código seguinte: <h:inputText value=”#{beanx.propriedade}”/> Quando o formulário é submetido o valor do campo de texto é salvo na propriedade do bean. O campo do formulário é linkado a propriedade do bean da aplicação. A vantagem é que o bean é uma classe comum, sem a necessidade de herdar de uma classe específica do framework. Sua codificação poderia ser exemplificada por: public class BeanX { public String metodo() { ExternalContext context = 2 FacesContext.getCurrentInstance() .getExternalContext(); HttpServletRequest request = (HttpServletRequest)context.getRequest(); String usuario = request.getParameter("formLogin:usuario"); String senha = request.getParameter("formLogin:senha"); if ((usuario == null)||(senha == null)) return("preencher-param"); else return("success"); } } Basicamente para uma aplicação JSF necessitamos de um bean que represente os dados contidos no formulário para ser passado adiante; um controlador de ação que leia o conteúdo do formulário, invoque a lógica de negócio, retorne os resultados e condições; o arquivo de configuração faces-config.xml que declare o bean, o controller e as regras de navegação. Para cada condição de retorno teremos um jsp associado. No caso de uma ação disparada por uma submissão de um formulário retornar nulo ou um valor não encontrado no arquivo de configuração como mapeado para alguma página, a página atual será reexibida. Vale ressaltar que o estado dos componentes é mantido, ou seja, os valores preenchidos não são perdidos. O JSF define pontos bem definidos desde a ação do usuário até a chegada na lógica de negócio, possibilitando ao usuário plugar seu código nesse fluxo. Algumas dessas formas serão vistas na próxima seção. 4. Ações, Eventos, Validações, Conversões O JSF provê muitas facilidades para formatação, conversões e validações. Tem capacidade de checagem se os valores do formulário estão faltando, se estão no formato requerido e nestes casos o formulário é reexibido com mensagens de erro e os valores anteriormente informados são mantidos. Iremos observar como cada um desses componentes são disponibilizados pelo framework e como podem ser implementados. 4.1 ACTION Uma ação pode estar diretamente ligada a um método de um bean. Por exemplo, num botão pertencente a uma página pesquisa.jsp podemos fazer a associação de um clique no botão com uma ação a partir do código a seguir: <h:commandButton id=”ok” value=”pesquisar” action=”#(elemento.metodo)”/> Num link essa associação seria feita da seguinte maneira: <h:commandLink id=”link” action=”#(elemento.metodo)”> <f:verbatim> Pesquisar </f:verbatim> </h:commandLink> O método referenciado poderia retornar o id_pag_saida que seria o identificador da página seguinte da navegação. Esse id estaria definido no arquivo de configuração da aplicação: <navigation-rule> <from-view-id> /pesquisa.jsp <from-view-id> <navigation-case> <from-outcome>id_pag_saida</from-outcome> <to-view-id>/pgSaida.jsp <to-view-id> </navigation-case> </navigation-rule> Retirando a tag <from-view-id>, que especifica de onde parte a navegação, estaríamos criando uma definição global, pois poderia ter origem de qualquer página da aplicação. A ação também pode indicar diretamente um JSP e não uma expressão para binding, como observamos no exemplo anterior em que o método retornava o identificador da página de saída, o que permite a variação desta página a depender de alguma situação observada pelo método. A ligação direta com a página de saída fixa seria feita da seguinte forma: <h:commandLink id=”link” action=” id_pag_saida”> <f:verbatim> Home </f:verbatim> </h:commandLink> A identificação estaria ainda no arquivo de configuração apontando para a página desejada como mostrado no exemplo anterior. A ação pode ainda ser adicionada no próprio formulário, uma vez que o mesmo pode receber os seguintes atributos: - action. Método acionado quando um formulário é submetido. É executado após todos os escutadores terem completado sua execução. – actionListener. Método escutador acionado quando um formulário é submetido. Ele é executado depois do método action. 4.2 EVENTOS O JSF provê dois tipos de eventos: Value Change (javax.faces.event.ValueChangeEvent) e Action (javax.faces.event.ActionEvent). O primeiro é utilizado para verificar mudanças nas propriedades de um componente ui, como mudança no valor de um edit, por exemplo. O segundo se refere a ações em botões e hyperlink basicamente. Cada um deles tem um tipo de escutador correspondente ValueChangeListener e ActionListener respectivamente. ActionEvents são empilhados por componentes que implementem a interface ActionSource (ex: UICommand) quando ativado por uma ação do usuário, como um clique num botão. E o ValueChangeEvents por componentes que implementem EditableValueSource (ex:UIInput) quando seus valores são modificados através de uma entrada do usuário. Lembrando que isso só é verificado após o formulário ser submetido. Quando um evento é empilhado é irradiado para que todos os escutadores registrados para essa ação sejam avisados/disparados. Da mesma forma que ocorre com os Validators, é possível referenciar um método de um managed bean A assinatura dos métodos deve seguir a seguinte assinatura: void x(ActionEvent event){..} void y (ValueChangeEvent event){..} E são inseridos na página da seguinte forma: 3 <h:inputText id=”campo” valueChangeListener=”#(bean.y)”/> <h:commandButton id=”campo” actionListener=”#(bean.x)”/> Outra forma é a de implementar as duas interfaces de escutadores e sobrescrever seus métodos: De ActionListener a assinatura do método é: public void processAction(ActionEvent event) throws AbortProcessingException{...} De ValueChangeListener a assinatura é: public void processValueChange(ValueChangeEvent event) throws AbortProcessingException{...} Para registrar esses escutadores nos componentes da página segue o código: <h:commandButton id=”ok” ...> <f:actionListener type=”classe”/> </h:commandButton> e para um campo de edição em que um evento valueChange será registrado segue o código: <h:inputText id=”identificador” ...> <f:valueChangeListener type=”classe”> </h:inputText> Ao modificar a caixa de texto relativa ao identificador, o método processValueChanged da classe pacote.classe que implementa a interface ValueChangeListener será executado. Assim como o método processAction é chamado para a ação no botão “ok”. </h:inputText> No arquivo de configuração da aplicação teremos a definição de idvalidator: <validator> <validator-id>idvalidator</validator-id> <validator-class>classe</validator-class> <description>xxxxx</description> </validator> Existem os Validators básicos disponíveis no JSF, como exemplo podemos citar o LengthValidator que é referenciado pela tag validateLength e que valida um campo de texto constatando se o texto inserido pode ser convertido num long e se está entre os valores mínimo e máximo O DoubleRangeValidator por sua vez é referenciado pela tag validateDoubleRange e valida o campo para verificar se ele pode ser convertido num double e se obedece a faixa entre o mínimo e o máximo; etc. Verificamos um exemplo de seu uso a seguir: <h:inputText id=”campo” …”> <f:validateDoubleRange minimum=”-100.0” maximum=”100.0”/> Existe também a possibilidade de atributos serem passados para os validadores não padrões, como podemos observar: <h:inputText id=”campo”> <f:validator type=”pacote.FormatadorValidator”/> <f:attribute name=”padrao” values=”99-99-9999”/> </h:inputText> 4.4 CONVERSOR 4.3 VALIDATOR A checagem de corretude de um dado submetido pelo usuário é parte integrante do framework JSF. Ela pode ser feita por binding do método validate() com métodos de qualquer managed bean no escopo. Para tal a assinatura dos métodos precisam seguir a seguinte assinatura: public void método(FacesContext context, UIComponent component, Object value) throws ValidatorException Na tag o atributo validator irá referenciar este método da seguinte forma: <h:inputText id=”campo” validator=”#(idclasse.metodo)”> Quando uma exceção ValidatorException é lançada, o JSF marca o componente como inválido e após a verificação das outras invalidações a requisição é abortada e as mensagens de erros apropriadas são exibidas. A validação pode também ser feita pela criação de um Validator, implementando a interface javax.faces.validator.Validator e sobrescrevendo o método validate() que possui assinatura semelhante ao método citado acima. A inclusão na página pode ser observada a seguir: <h:inputText id=”campo”> <f:validator validatorId=”idvalidator”/> Os conversores têm o papel primário de converter os managed bean que, representam informações da aplicação, numa String e vice-versa. No ciclo de vida de uma requisição os conversores vêm antes dos validadores, pois muitas vezes os validators precisam de conversões. Conversores podem ser usados para garantir que um dado é válido em seu tipo (emitindo uma exceção ConverionException). Já um Validator garante que ele é válido em seu valor. <h:inputText id=”campo” converter=”#(Double)” .../> Neste exemplo a caixa de edição é associada a um DoubleConverter, um dos conversores padrões suportados pelo framework JSF. O JSF disponibiliza diversos conversores. Dentre eles destacamos as classes NumberConverter e DateTimeConverter que podem receber atributo, o que refina seu comportamento. <h:inputText id=”campo”> <f:converterNumber type=”currency”> </h:inputText> <h:inputText id=”campo”> <f:convertDateTime pattern=”M/d/yyyy”/> </h:inputText> 4 Para criar um conversor é necessário implementar javax.faces.convert.Converter e sobrescrever os métodos public Object getAsObject(FacesContext, UIComponent, String) throws ConverterException public Object getAsObject(FacesContext, UIComponent, Object) throws ConverterException E a sua configuração no arquivo da aplicação é da seguinte maneira: <faces-config> ... <converter> <description> xxxxx </description> <converter-id>conversorx</converter-id> <converter-class>classe</converter-class> </converter> </faces-config> Na página teremos: <h:inputText id=”campo”> <f:converter converterId=”conversorx”> </h:inputText> 5. Ciclo de Vida de uma requisição Quando um cliente faz uma requisição o servidor responde com um HTML, é assim em JSP ou em JSF. Entretanto, como o JSF provê características adicionais no processamento da página, o ciclo de vida provê outros serviços para esse processamento. O ciclo de vida do JSF é composto de 6 fases. Numa requisição podemos passar por todas essas fases ou por nenhuma, a depender do tipo de requisição, de erros que ocorram de validações e conversões e do tipo de resposta. Uma requisição e uma resposta são consideradas faces request/response se contiverem tags JSF, assim como as que não as contém são chamadas de non-faces request/response. Uma nonfaces request pode ser advinda de um clique em link, por exemplo. Como já visto anteriormente toda requisição é recebida pelo FacesServlet e prossegue a passagem pelas fases até uma resposta ser retornada ao cliente. O FacesServlet recupera uma instancia de FacesContext do FacesContextFactory, fornecendo uma implementação de LifeCycle. O processamento do ciclo de vida é então delegado a interface LifeCycle, a partir da chamado ao método execute. A implementação de LifeCycle inicia as fases do ciclo de vida. Inicialmente é criada uma árvore, com os componentes do formulário do qual se originou a requisição. Esta também é conhecida como view. Se existir algum validator associado a algum campo do formulário este é inicializado nessa primeira fase. A árvore é armazenada pelo contexto e será utilizada nas fases seguintes. Também o estado do formulário é salvo automaticamente. No caso de uma non-faces request não existirá campos no formulário para montagem da árvore e no momento da geração da resposta uma nova árvore deverá ser criada e armazenada no contexto; a referência para o objeto do modelo requerido pela árvore deverá ser obtida; e a chamada ao método renderResponse do FacesContext será invocado, o que fará com que o ciclo seja direcionado para a fase 6. Na segunda fase os valores dos componentes que compõem a árvore são extraídos da requisição através do método decode. Se algum erro ocorrer durante o processo é empilhado no contexto para ser exibido ao cliente. Também nessa fase os eventos que são criados por ações do usuário são empilhados para serem propagados para os listeners registrados. Durante a terceira fase temos a execução dos validadores que foram inicializados na fase anterior. Isso é feito pela execução do método validate em cada validator registrado. Se qualquer validação falhar o ciclo de vida pula para a fase 6. Assim como na fase anterior, os eventos resultantes dessa fase são empilhados para propagação aos escutadores registrados. Na quarta fase do ciclo de vida, após todos os validators terem sido processados com sucesso, o JSF atualiza os valores dos objetos do modelo pela chamada ao método updateModel de cada componente. Os valores provenientes dos campos do formulário são setados nos valores de atributos dos objetos do modelo, normalmente um java bean ou managed bean. Se algum erro decorrer dessa atualização o ciclo é avançado para a fase 6. O método processAction é invocado na quinta fase e neste momento será executada o processamento da lógica. Na última fase do ciclo de vida a próxima página a ser exibida é verificada no arquivo faces-config como já visto anteriormente. No caso de algum erro ocorrer a mesma página que originou a requisição será exibida com os erros pertinentes. Com relação ao resultado apresentado ao usuário, as tags JSF herdam de UIComponentTag que implementa os métodos doStartTag e doEndTag (de Tag) e possuem os métodos abstratos getComponentType e getRenderedType. A implementação desses dois métodos nas classes das tags JSF permite especificar o tipo do componente e do renderer. Quando um formulário é renderizado os seguintes passos são executados: - O servlet container invoca o método doStartTag do FormTag. - O FormTag recupera seu UIComponent pelo método getComponetType. Essa busca é feita pela recuperação do nome da classe para este componente no facesconfig e precedida pela criação de uma instância do UIComponent. - O FormTag recupera de Renderer através do método getRenderedType. Da mesma forma que na busca anterior, é feita através do faces-config. - Com o FormComponent e FormRenderer criados o método encodeBegin de FormComponent é invocado e com ele o FormRenderer inicia a montagem da página, para tanto, na ordem de assentamento de cada tag, os métodos encodeBegin e encodeEnd vão ser acionados. - Por fim o servlet container invoca na ordem contrária de assentamento o método doEndTag de cada tag. No final de tudo o formulário e seus componentes são renderizados como HTML. No caso em que uma requisição JSF gera uma resposta non-faces o desenvolvedor deve forçar a ida a fase 6 através da chamada ao método responseComplete de FacesContext. Essa chamada pode ocorrer em qualquer fase do ciclo. 5 O fluxo entre os passos do ciclo de vida JSF pode ser visto na figura 2. 7. Exemplo Demonstraremos um exemplo simples de uma página de inclusão de contatos e o seu resultado: Página para informação dos dados: Nesta página é exibida ao cliente uma tela com os campos a serem cadastrados. O campo “nick” que representa o identificador do contato é obrigatório, com tamanho entre 5 e 10 caracteres. (Figura 2) 6. Configurações Observemos que os arquivos de configurações, apesar de indicar para arquivos .jsp, há como configurar para que não seja possível acessar esses jsp’s diretamente, sendo necessário trocar a extensão para .faces. Isso protege o acesso direto aos jsp’s. Para tal utilizamos a seguinte configuração: <web-app> … <security-constraint> <display-name> Prevent access to raw JSP pages that are for JSF pages. </display-name> <web-resource-collection> <web-resource-name>Raw-JSF-JSP-Pages</webresource-name> <!- - Adicionar uma tag url-pattern para cada página jsp --> <url-pattern>/home.jsp</url-pattern> <url-pattern>/munu1.jsp</url-pattern> … </web-resource-collection> <auth-constraint> <description>No roles, so no direct access</description> </auth-constraint> </security-constraint> </web-app> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <html><head><title>Cadastro de Contato </title></head><body> <f:view> <h:form> Informe os Dados <br> Identificador:<h:inputText id="nick" value="#{ContatoBean.nickName}" required="true"> <f:validateLength minimum="5" maximum="10"/> </h:inputText><br> nome: <h:inputText value="#{ContatoBean.nome}"/><BR> email: <h:inputSecret value="#{ContatoBean.email}"/><BR> fone: <h:inputSecret value="#{ContatoBean.telefone}"/><BR> <h:commandButton value="Submeter" action="#{ContatoBean.cadastrar}"/> <br><br> <h:outputLink value="menu.jsf"> <f:verbatim>Menu</f:verbatim> </h:outputLink><br> <h:outputLink value="logouf.jsf"> <f:verbatim>Logout</f:verbatim> </h:outputLink><br> </h:form> </f:view> </body></html> A tela resultante desta codificação é a seguinte: No faces-config para especificar que a partir de uma requisição de login.jsp, se o valor retornado for “login”, a página menu.jsp será exibida, temos: <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE faces-config PUBLIC …> <faces-config> <navigation-rule> <from-view-id>/login.jsp</from-view-id> <navigation-case> <from-outcome>login</from-outcome> <to-view-id>/menu.jsp</to-view-id> </navigation-case> </navigation-rule> </faces-config> . 6 { this.msg = msg; } Página com o resultado do cadastro: <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <html><head><title>Cadastro de Contato </title></head><body> <f:view> <h:form> Resultado <br> Identificador:<h:outpuText value="#{ContatoBean.nickName}"/><br> Nome:<h:outpuText value="#{ContatoBean.nome}"/><br> Email:<h:outpuText value="#{ContatoBean.email}"/><br> Telefone:<h:outpuText value="#{ContatoBean.telefone}"/> <br><br> Mensagem: <h:outpuText value="#{ContatoBean.texto}"/> </h:form> </f:view> </body></html> Podemos visualizar a tela resultante a seguir: public String getTelefone() { return telefone; } public String setTelefone(String telefone) { this.telefone = telefone; } public String getNickname() { return msg; } public String setNickname(String nickname) { this.nickname = nickname; } public String getEmail() { return email; } public String setEmailo(String email) { this.email = email; } public String getNome() { return nome; } public String setNome(String nome) { this.nome = nome; } } 8. Conclusão O Java Server Faces veio acrescentar muitos avanços que os desenvolvedores Java para Web sentiam a necessidade, especialmente na facilidade no desenvolvimento. Com o framework JSF os desenvolvedores passam a ter a facilidade de trabalhar com a modularização que o MVC modelo 2 proporciona. Os componentes são bem definidos e a divisão de tarefas consequentemente. O webdesigner monta sua página (interface) e em cima desta são incluídos os respectivos validadores, conversores ou qualquer outra facilidade já disponibilizada pelo framework ou que este dá a possibilidade de o desenvolvedor criar a partir de sua infraestrutura. A adição destes na interface é feita de forma simples e clara. A Delegação que é feita a partir das ações na interface é remetida a uma outra camada e os componentes contidos nesta podem ser reutilizados por interfaces diversas. Há, muito mais do que antes a nítida divisão dos papéis do webdesigner e do desenvolvedor e a reusabilidade dos componentes de lógica. Além disso, os elementos de interface possuem uma ligação direta com classes do framework em que podemos descrever comportamentos peculiares e até ações associadas ao seu uso. A customização de componentes, desde os disponibilizados pelo JSF, como pelos que podem ser criados pelos desenvolvedores e que são incluídos numa página JSP através de simples tags. Assim como é feito pelo AWT e Swing A classe do bean utilizada no exemplo pode ser representada pela seguinte codificação: import br.com.escolaquasar.acessodados.AcdContato; public class ContatoBean{ private String nickname; private String nome; private String email; private String telefone; private String msg; public void cadastrar (){ msg = AcdContato.cadastrar(this); } public String getTexto() { return msg; } public String setTexto(String texto) O prosseguimento do fluxo da aplicação no JSF é descrito num arquivo de configuração, que facilita em muito as alterações futuras. Aliás, muitos dos dados utilizados pelo JSF estão em arquivos XML ou de propriedade, o que possibilita que várias mudanças sejam feitas modificando um único arquivo. De modo geral, todas essas facilidades trazidas pelo framework de desenvolvimento JSF fazem com que o desenvolvedor mantenha seu foco nas tarefas do negócio e não se veja perdido em meio a configurações, a detalhes do ambiente, de interface, ou seja se preocupando com todo o layout do sistema, ou ate mesmo implementando facilidades que o próprio framework deveria fornecer, e agora o faz em muitos pontos vistos nesse artigo. 7 9. REFERÊNCIAS [1] Dudney Bill, Lehr Jonathan, Willis Bill, Mattingly LeRoy Mastering Java Server Faces – Wiley Publishing Inc. – Indianapolis-Indiana2004 [2] http://java.sun.com/j2ee/javaserverfaces/jsfintro.html capturada em 27/07/2004 [3] http://www.coreservlets.com/JSF-Tutorial/ capturada em 27/08/2004 [4] http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html capturada em 27/10/2004 [5] www-106.ibm.com/developerworks/ java/library/j-integrate/ capturada em 03/08/2004 [6] www.exadel.com/tutorial/jsf/jsftutorial-kickstart.html capturada em 27/10/2004 [7] java.sun.com/j2ee/1.4/docs/tutorial/doc/JSFIntro10.html capturada em 12/10/2004 [8] http://java.sun.com/j2ee/javaserverfaces/ capturada em 27/10/2004 [9] http://192.18.97.239/ECom/EComTicketServlet/BEGINjsecom16 k.sun.com-cfb%3A409feef6%3A749cc712ba44fc3f/2147483648/376655475/1/449522/449474/376655475/2ts+/westC oastFSEND/j2eesdk-1.4-oth-JPR/j2eesdk-1.4-oth-JPR:1/j2eesdk1_4-windows.exe capturada em 27/10/2004 [10] http://developers.sun.com/prodtech/javatools/jscreator/index.jsp capturada em 07/10/2004 8