Integração entre o Mentawai e o DWR

Por Cássio Marques (cassiommc@gmail.com)

O objetivo aqui é demonstrar uma simples integração entre o Mentawai e o DWR.
O DWR é um framework AJAX escrito em Java bastante simples de utilizar. Sua função é mapear classes escritas em Java (no servidor) e criar seus equivalentes em javascript. O DWR cuida também de todas as chamadas remotas realizadas pelo browser. Para acionar estas chamadas é necessário escrever um pouco de javascript, mas nada que assuste.
Maiores informações sobre o DWR podem ser obtidas no site oficial do projeto

Não irei explicar aqui os detalhes da utilização do DWR, pois isso fugiria do escopo deste tutorial. Estou assumindo que você já conhece o básico deste framework, bem como um pouco de javascript também.
Este tutorial também supõe que:

Os arquivos fonte deste tutorial podem ser baixados aqui.

Neste exemplo temos uma página simples, que exibe em uma tabela os alunos matriculados em um determinado curso. Temos um elemento <select> e um <div> inicialmente vazio. Quando a seleção deste <select> é alterada uma função javascript é acionada, a qual realiza uma chamada remota para uma inner action do Mentawai, passando o valor atual do <select>. Essa inner action é responsável por recuperar a lista de alunos matriculados no curso pesquisado, colocá-la no output e fazer um forward para um jsp que contém a estrutura da tabela, utilizando as tags do Mentawai.
A mágica aqui é que com um pouco de javascript e o auxílio do DWR, pegamos todo o html deste jsp e renderizamos o mesmo dentro do nosso <div>. Cada vez que escolhemos um novo curso, a tabela é alterada, sem a necessidade de recarregar a página atual.

Abaixo temos o html da nossa página inicial:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<head>
<title>Exemplo MentaDWR</title>
<script type='text/javascript' src='/MentawaiDWR/dwr/engine.js'></script>
<script type='text/javascript' src='/MentawaiDWR/dwr/util.js'></script>
<script type='text/javascript' src='/MentawaiDWR/dwr/interface/AlunoAction'></script>
<script type="text/javascript">
   <!--
   function exibeAlunos(){
      var c = document.getElementById('curso').selectedIndex;      
       if(c != 0)
          AlunoAction.forwardParaTabelaPorCurso(c, function(conteudo){
             document.getElementById('tabela').innerHTML = 
                conteudo.replace(/\\n/g,""); //retirando as quebras de linha
          });
    }
    -->
</script>
</head>
<body>
<h2>Exemplo simples de integração entre o Mentawai e o DWR</h2>
Selecione um curso para exibir os alunos matriculados no mesmo<br/><br/>
Curso: <mtw:select name="curso" id="curso" list="cursosList" extra="onchange=exibeAlunos()"/><br/><br/>
<div id="tabela"></div>
</body>
</html>

A função javascript exibeAlunos() realiza a chamada à action do Mentawai do lado servidor, recebe como retorno o conteúdo do jsp e utiliza uma função de callback para inserir este html no <div>.

Aqui temos o html do jsp com a tabela

<%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %>

<mtw:list value="alunos">
   <mtw:isEmpty>
      <b>Nao há alunos cadastrados no curso pesquisado.</b>
   </mtw:isEmpty>
   <mtw:isEmpty negate="true">        
      <table>
      <tr>
         <th align="left">ID</th>
         <th align="left">NOME</th>
         <th align="left">EMAIL</th>                        
      </tr>
      <mtw:loop var="a">
      <tr>
         <td width="40px">${a.id}</td>
         <td width="80px">${a.nome}</td>
         <td width="120px">${a.email}</td>
      </tr>                        
      </mtw:loop>                  
      </table>
   </mtw:isEmpty>
</mtw:list>

Criamos um POJO bem simples para representar um aluno:

package org.mentadwr.bean;

public class Aluno {
      
      private int id;
      private String nome;
      private String email;
      private int curso;
      
      //getter e setters omitidos
}

Nossa action fica assim:

                  
public class AlunoAction extends BaseAction implements ModelDriven {

      private List<Aluno> alunos = null;
      private AlunoManager model = new AlunoManager();	
      
      public Object getModel() {
               return model;
      }
      
      public String execute() throws Exception {
               //nada aqui...
               return SUCCESS;
      }
      
      /*
       * Metodo chamado remotamente pelo DWR, faz forward para inner action "exibeTabela", a qual
       * por sua vez faz forward para o jsp que contem a tabela.
       */
      public String forwardParaTabelaPorCurso(String curso) throws Exception{
               return WebContextFactory.get().forwardToString("/AlunoAction.exibeTabela.mtw?curso="+curso);		
      }
      
      /*
         * Inner action que recebe o curso pesquisado como parametro, realiza a busca atraves de
         * uma classe de negocio (a qual acessa um DAO) e coloca a lista recuperada no output.
         */
      public String exibeTabela() throws Exception{
               int curso = input.getIntValue("curso");
               if(curso <= 0){
                        output.setValue("erro", "Informe um curso para pesquisar!");
                        return ERROR;
               }
               alunos = model.selectPorCurso(curso);
               output.setValue("alunos", alunos);
               return SUCCESS;			 
      }
}

Nossa action possui o método forwardParaTabelaPorCurso(), o qual é acessado pelo DWR, e a inner action exibeTabela(), mapeada no ApplicationManager, que realiza o forward para o jsp da tabela. O método forwardParaTabelaPorCurso() recebe o curso pesquisado, constrói a string de pesquisa e utiliza a classe WebContextFactory do DWR para fazer um forward para a inner action exibeTabela().

Mapeando nossa action no dwr.xml

<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://www.getahead.ltd.uk/dwr//dwr20.dtd">

<dwr>
   <allow>   
   <create creator="new" javascript="AlunoAction">
      <param name="class" value="org.mentadwr.action.AlunoAction"/>
   </create>      
   </allow>
</dwr>

O ApplicationManager fica mais ou menos assim:
public void loadLists(){
      //lista com a descricao dos cursos
      SimpleListData cursosList = new SimpleListData("cursosList");
      cursosList.add(0, "");
      cursosList.add(1, "Matematica");
      cursosList.add(2, "Computacao");
      cursosList.add(3, "Fisica");		
      ListManager.addList(cursosList);
}
                  
public void loadActions() {

     filter(new IoCFilter());
     filter(new ConnectionFilter("connection", connHandler));        
     filter(new DIFilter("connection", java.sql.Connection.class));
     filter(new InjectionFilter());
                                 
     ActionConfig ac = new ActionConfig("AlunoAction", org.mentadwr.action.AlunoAction.class);		
     ac.addConsequence(AlunoAction.SUCCESS, "exibeTabela", new Forward("/tabelaAlunos.jsp"));
     ac.addConsequence(AlunoAction.ERROR, "exibeTabela", new Forward(""));
     addActionConfig(ac);
}                  

A partir deste exemplo fica fácil utilizar o Mentawai e o DWR para inserir conteúdo html de maneira dinâmica em suas páginas.