Tag: ‘jsf’
JSF, RichFaces, AJAX e combobox alinhados
Em meus estudos sobre JSF e AJAX, gostei muito do pacote disponibilizado pela JBoss, o RichFaces. A intensão é usar o mais puro do JSF porém, aproveitando o que cada componente oferece de melhor.
O RichFaces é interessante e muito completo, oferece diversos recursos para web que até então o HTML estava limitado, como o combobox (leia-se também dropdown) com área aberta para localização de textos – <rich:comboBox/>. Ao contrário deste alguns outros componentes apresentam problemas sérios de incompatibilidade com o Apache MyFaces (Tomahawk), por exemplo, o <rich:fileUpload/>.
Estudando esses componentes observei suas vantagens e falhas, decidi então criar este exemplo de um recurso tão comum em formulários e simples com JSF, que são os combobox dependentes ou alinhados.
Vamos continuar com o esquema de Países e Estados, um combobox para cada, sendo que ao modificar o Pais através do AJAX os estados relacionados serão carregados.
A configuração básica do Faces e RichFaces no web.xml será ocultada, porém você poderá fazer o download do projeto no fim deste post.
O projeto está estruturado da seguinte maneira:
No Manager Bean destacam-se os métodos getPaises() e actionCarregarEstados(), o primeiro retorna um array de itens – SelectItem[] – tipo de dado complexo que será tratado pelo componente JSF, já o actionCarregarEstados() é responsável por carregar os estados relacionados ao pais.
public class UirapuruManagerBean {
private Pessoa pessoa = new Pessoa();
private SelectItem[] estados;
/* getters e setters ocultados */
/* carrega os paises */
public SelectItem[] getPaises(){
List<pais> lp = regiaoDao.getAllPais();
List<selectItem> itens = new ArrayList<selectItem>(lp.size());
for( Pais p : lp ){
itens.add( new SelectItem(p.getId_pais(), p.getNm_pais()) );
}// for end
return itens.toArray( new SelectItem[itens.size()] );
}
/* carrega os estados */
public SelectItem[] getEstadosByPais(int id_pais){
List<estado> estados = regiaoDao.getEstadosDoPais(id_pais);
List<selectItem> itens = new ArrayList<selectItem>(estados.size());
for( Estado e : estados ){
itens.add( new SelectItem(e.getId_estado(), e.getNm_estado()) );
}// for end
return itens.toArray( new SelectItem[itens.size()] );
}
/* */
public String actionCarregarEstados(){
this.estados = getEstadosByPais(getPessoa().getPais().getId_pais());
return "SUCCESS";
}
}
Uma observação importante antes de seguirmos: os beans Pessoa, Pais e Estado são simples e foram criados apenas para uma interpretação melhor, é importante e somente assim este exemplo irá funcionar perfeitamente se no bean Pessoa, os atributos pais e estado sejam inicializados. Já que não estamos trabalhando com Spring o Faces não irá fazer este entendimento e uma exceção NullPointerException será lançada, para evitar tal faça isto:
public class Pessoa implements Serializable {
private int id;
private String nome;
// criando os objetos
private Pais pais = new Pais();
private Estado estado = new Estado();
/* getters e setters ocultados */
}
Okay. Feita a observação vamos para a parte final, a montagem do JSP.
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core"%> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html"%> <%@ taglib prefix="a4j" uri="http://richfaces.org/a4j"%>
Não esqueça que qualquer página JSF deve ser elaborada dentro da tag <f:view/> e, que sem a definição do formulário <h:form/> o AJAX não irá funcionar.
<f:view>
<h:form>
<h:panelGrid border="0" columns="2" width="500" cellpadding="1" cellspacing="2">
<h:outputLabel value="Pais" for="pais"/>
<h:selectOneMenu id="pais"
value="#{umb.pessoa.pais.id_pais}"
rendered="true">
<f:selectItems value="#{umb.paises}"/>
<a4j:support event="onchange"
ajaxSingle="true"
action="#{umb.actionCarregarEstados}"
reRender="pais,estado"/>
</h:selectOneMenu>
<h:outputLabel value="Estado" for="estado"/>
<h:selectOneMenu id="estado"
value="#{umb.pessoa.estado.id_estado}"
rendered="true">
<f:selectItems value="#{umb.estados}"/>
</h:selectOneMenu>
</h:panelGrid>
</h:form>
</f:view>
Na tag <h:selectOneMenu/> deve-se colocar na propriedade VALUE o atributo que irá receber o valor selecionado no combobox, outras propriedades excenciais são o ID que identifica o componente e RENDERED que indica a renderização. A tag <f:selectItems/> invoca o método – umb.getPaises() – que contém os itens do combobox.
Até o momento utilizamos apenas JSF puro, o RichFaces é representado na tag <a4j:support/> responsável por identificar quando um evento do tipo OnChange é feito e fazer a ação definida no método umb.actionCarregarEstados, e por fim na propriedade reRender estão separados por vírgulas os componentes que serão renderizados.
Seguindo esta linha de raciocínio você conseguirá fazer vários níveis de dependência facilmente, o componente <rich:combobox/> também permite este tipo de interação, com alguns recursos a mais.
Faça aqui o download do projeto.
AJAX II: Java Server Faces com Jboss RichFaces
Continuando com a série de posts sobre AJAX, agora vou mostrar como é mais simples desenvolver aplicativos utilizando um framework e o escolhido foi JavaServer Faces.
A utilização de frameworks é uma mão-na-roda, tanto no sentido de diminuir muito a reconstrução de funcionalidades básicas, tão quanto para padronizar componentes. O JavaServer Faces há tempos é uma base de desenvolvimento segura, padronizada e rica em componentes web 2.0, seguindo este padrão o pessoal do JBoss criou o RichFaces, que futuramente foi chamado de Ajax4Jsf, nada mais é que um pacote de componentes pré-definidos para construção de aplicativos utilizando AJAX. No wikipedia você encontra uma descrição mais detalhada sobre JSF e RichFaces.
Em seguida vou demonstrar um desafio feito por mim mesmo, veja aqui, construindo um auto-completar utilizando JSF com Richfaces.
Os conceitos de JSF e RichFaces não serão discutidos, ou seja, apenas vou demonstrar como criar a aplicação sem detalhar a configuração feita no web.xml e no faces-config.xml, futuramente dedicarei um post sobre essas configurações.
Em seguida será demonstrado como construit um auto-completar cujo conteúdo será o nome de países, portanto, a estrutura básica das classes é esta:
O arquivo web.xml está configurado básicamente para trabalhar com os framewroks JSF e RichFaces.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>ClubesRich</display-name> <!-- RichFaces Config --> <context-param> <param-name>org.richfaces.SKIN</param-name> <param-value>blueSky</param-value> </context-param> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <filter> <display-name>RichFaces Filter</display-name> <filter-name>richfaces</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>richfaces</filter-name> <servlet-name>Faces Servlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> <!-- Faces Config --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Faces Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <!-- Database Config --> <resource-ref> <description>DB Connection</description> <res-ref-name>jdbc/Clubes</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> <!-- --> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsf</welcome-file> </welcome-file-list> </web-app>
Já o ManagerBean está assim configurado no faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?> <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <managed-bean> <managed-bean-name>regiaoControl</managed-bean-name> <managed-bean-class>com.clubs.control.RegiaoControl</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <display-name>autocomplete</display-name> <from-view-id>/autocomplete.jsp</from-view-id> </navigation-rule></faces-config>
Veja abaixo o manager bean terá um método chamado autoCompletePais que receberá um parametro do tipo Object e retorna um ArrayList do tipo Pais.
public ArrayList<pais> autoCompletePais(Object o){
return rdao.getAllPais( o.toString() );
}
E por fim, o arquivo autocomplete.jsp, que foi mapeado no faces-config, mostrará como é simples utilizar o recurso SuggestionBox do pacote RichFaces e fazer um auto-completar com diversos recursos, acima de tudo bonito e eficaz no dia-a-dia, veja:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
<f:view>
<h:form>
<rich:panel>
<f:facet name="header"><h:outputText value="Digite o Pais:"/></f:facet>
<h:inputText value="#{regiaoControl.pais.nome}" id="campo" />
<rich:suggestionbox height="150"
width="150"
for="campo"
fetchValue="#{campo.nome}"
suggestionAction="#{regiaoControl.autoCompletePais}"
var="campo">
<h:column>
<h:outputText value="#{campo.id_pais}"/>
</h:column>
<h:column>
<h:outputText value="#{campo.nome}"/>
</h:column>
</rich:suggestionbox>
</rich:panel>
</h:form>
</f:view>
Veja o resultado final, tornando a utilização do software mais agradável.

