WEBCODELOG

free codes, enjoy

Tag: ‘ajax’

JSF, RichFaces, AJAX e combobox alinhados

with 17 comments

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.

Written by Luciano

agosto 11th, 2008 at 7:23 pm

Posted in Programação

Tagged with , ,

AJAX II: Java Server Faces com Jboss RichFaces

with one comment

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.

Written by Luciano

julho 6th, 2008 at 8:19 pm

Posted in Programação

Tagged with , , ,

AJAX: Nada novo, mas que muda tudo!

with 2 comments

Resolvi escrever sobre AJAX porque vejo muita confusão ainda sobre o assunto, tem uma galera que não sabe exatamente o que é e, como se aplica e o que se ganha utilizando a técnica. Vou apenas demonstrar o mecanismo básico para funcionamento, não é um segredo, esse mesmo tutorial pode ser encontrado em milhares de sites na internet.

AJAX (Asynchronous JavaScript and XML) é uma técnica simples aplicada em ambiente de internet que utiliza apenas JavaScript e XML, possibilitando ao desenvolvedor criar funcionalidades mais ricas, daí o famoso RIA (Rich Internet Application). É possível usar AJAX em qualquer linguagem dinâmica de internet que suporte XML, como PHP, ASP, J2EE, .NET, etc.  A diferença realmente está nos navegadores de internet, que utilizam o componente chave XMLHttpRequest cada um a sua maneira.

O processo é feito de maneira simples, o XMLHttpRequest  faz uma chamada assíncrona por XML a uma outra página oculta aos olhos do usuário. Esta página oculta por sua vez devolve as informações processadas ao XMLHttpRequest, também via XML, e utilizando JavaScript é feito o parse do XML e exibido o resultado na página principal, que originou a chamada.

Para obter o XMLHttpRequest, eh comum a utilização deste bloco JavaScript

if( window.XMLHttpRequest ){ // Firefox, Safári, etc.
xmlReq= new XMLHttpRequest();
}else  if( window.ActiveXObject ){ // Se for IE – ActiveX version
xmlReq = new ActiveXObject(“Microsoft.XMLHTTP”);
}

Existem outras maneiras para obter o componente, cada programador decide pelo mais conveniente, veja este outro exemplo:

try{
xmlReq = new ActiveXObject(“Microsoft.XMLHTTP”); // IE
}catch(e){   // Falhou, para os normais
xmlReq = new XMLHttpRequest();
}

Após obter o XMLHttpRequest, vamos fazer a comunicação com um XML e exibir seu conteúdo, e tudo isso usando apenas JavaScript.


// faz a chamada no servidor da página dinâmica, responsavel por devolver o XML response
// o primeiro parametro indica se a chamada será via GET ou POST
// o segundo informa qual é a página, e por último se será uma chamada assíncrona

xmlReq.open(“GET”, “http://localhost/ajax/response.php”, true);


xmlReq.onreadystatechange=function(){
if( xmlReq.readyState < 4 ){
// Enquanto é aguardado o retorno, pode-se exibir uma mensagem
}else{
if( xmlReq.readyState == 4 ){
// Aqui é colocado o processo de parser do XMLResponse.
}
}
}// end OnReadyStateChange
xmlReq.send(null); // transporte

Vejam que a primeira ação é chamar a página “oculta”, responsável por retornar o XML com os dados necessário.

O readyState indica qual o nível do processamento, esses são os estados: 1 – Sendo enviado; 2 – Processando; 3 – Armazenando e 4 – Pronto. É possível utilizar a propriedade status do XMLHttpResponse, esta por sua vez indica o status da página que foi chamada, ou seja, se ocorreu algum erro ou não.

That`s all! Simples não? É assim que funciona o famoso AJAX, nada mais além disso, os recursos de JavaScript são utilizados ao extremo. Atualmente existem recursos extremamente avançados e mais seguros que este exemplo, mesmo assim é válido o entendimento do mecanismo utilizado nesses frameworks e esclarecer o funcionamento do AJAX.

Você pode fazer aqui o download de um exemplo simples, porém muito útil em formulários de cadastro, onde três dropdowns (País, Estado e Cidade) interdependentes, que ao fazer o reload da página para carregá-los é muito cansativo. Vale ressaltar que utilizei PHP para a construção deste pequeno tutorial, acabando como mito de que AJAX está vinculado a Java/.Net.

Ambiente

PHP 5 e MySQL 5, rodando em Windows XP, IE 6 e 7 e Firefox 2.

Desafio

Talvez você tenha idéia melhores para aplicar o AJAX depois de entendê-lo e, eu não me surpreenderia com isto, então faço aqui um desafio para estimular o aprendizado: crie um Auto-Completar! Você é capaz?!

Written by Luciano

junho 13th, 2008 at 10:51 pm

Posted in Programação

Tagged with , , ,