Uso de DWR para Ajax

Pessoal,

Estou querendo usar Ajax em um projeto. E escolhi o framework DWR.
Só que nos tutoriais de configuração que eu encontrei, eles me deixaram um pouco confusa em relação à configuração da versão 1.X com os da versão 2.X. Eu cheguei a configurar, mas acredito que algo ainda tenha que ser mudado.

Em vários tutoriais dizem pra inserir estas linhas na página, mas em minha página dá erro de link corrompido:

<script src='dwr/interface/SefFacade.js'></script>
<script src='dwr/engine.js'></script>
<script src='dwr/util.js'></script>

Enfim, o projeto que estou desenvolvendo é EJB e está dividido nas camadas: dao, vo, rn, facade e servlet. Gostaria de saber como seria a implementação dessa tecnologia numa estrutura de camadas como essa.
E gostaria de saber, também, se vocês sabem de algum tutorial ou algo desse tipo que oriente o programador desde a configuração (web.xml, dwr.xml, …) até desenvolvimento desta tecnologia. Se tiver exemplos melhor ainda.

Até onde você colocou de informação, vc precisa ter no dwr.xml o mapeamento para a classe SefFacade.java

Ex:

[code]<allow>
	<create creator="new" javascript="SefFacade">
		<param name="class"
			value="com.xxx.SefFacade" />			
	</create>
	
</allow>[/code]

Você tem que também criar as funções js.

Passe mais detalhes pra poder te ajudar.

Esse link ajuda bastante:
http://today.java.net/pub/a/today/2005/08/25/dwr.html

Verifique a configuração no seu web.xml, para que seus .js sejam criados pelo Servlet do DWR. Note que passei as classes que serão utilizadas. As do pacote br.com.netra.jad são meus DTO, e as do pacote br.com.netra.jad.dwr são os meus Remote Proxy (classes que invocamos os métodos via ajax).

    <servlet>
        <servlet-name>dwr-invoker</servlet-name>
        <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>classes</param-name>
            <param-value>
                br.com.netra.jad.dwr.ArquivoDWR,
                br.com.netra.jad.Arquivo,
                br.com.netra.jad.Resultado,
                br.com.netra.jad.Status,
                br.com.netra.jad.Opcoes
            </param-value>
        </init-param>        
    </servlet>
    <servlet-mapping>
        <servlet-name>dwr-invoker</servlet-name>
        <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>    
    <session-config>

Lembre de anotar a sua classe Remote Proxy, e não esqueça de anotar os métodos que você quer permitir a chamada Ajax. Só um informativo: esta aplicação é um decompilador Java, utilizando JAD.

package br.com.netra.jad.dwr;

import br.com.netra.jad.Arquivo;
import br.com.netra.jad.Opcoes;
import br.com.netra.jad.Resultado;
import br.com.netra.jad.negocio.BOFactory;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;


/**
 * Classe responsável por apresentar a camada de negócio utilizando a tecnologia
 * AJAX via DWR. Esta classe deve preparar os dados para serem enviados para
 * o browser do cliente.
 * @author Cleverson Sacramento (zyc@ig.com.br)
 * @see <a href="http://getahead.org/dwr/">Direct Web Remoting</a>
 */
@RemoteProxy
public class ArquivoDWR {

    /**
     * Carrega as informações de um arquivo com base na sua identificação.
     * @param id Identificação do arquivo.
     * @return Arquivo carregado.
     * @throws Exception
     */
    @RemoteMethod
    public Arquivo carrega(Long id) throws Exception {
        Arquivo dto = BOFactory.getInstance().createArquivo().carregar(id);
        return dto;
    }

    /**
     * Analisa um determinado aquivo para decompilação com base na sua identificação.
     * @param id Identificação do arquivo.
     * @return Resultado da análise.
     * @throws Exception
     */
    @RemoteMethod
    public Resultado analisa(Long id) throws Exception {
        Arquivo dto = BOFactory.getInstance().createArquivo().carregar(id);

        Resultado resultado = 
            BOFactory.getInstance().createDecompilacao().analisar(dto);
        resultado.getArquivo().setConteudo(null);

        return resultado;
    }

    /**
     * Obtém todos os arquivos baseados na sessão do usuário.
     * @return Lista de resultado com o arquivo preenchido, para manter a 
     * compatibilidade na apresentação das informações.
     * @throws Exception
     */
    @RemoteMethod
    public List<Resultado> obterTodos() throws Exception {
        List<Resultado> list = new ArrayList<Resultado>();

        List<Arquivo> listAux = 
            BOFactory.getInstance().createArquivo().obterTodos();

        String sid = this.getHttpServletRequest().getSession().getId();

        for (Arquivo dto: listAux) {
            if (dto.getCaminho().indexOf(sid) != -1) {
                Resultado resultado = 
                    BOFactory.getInstance().createDecompilacao().analisar(dto);
                resultado.getArquivo().setConteudo(null);

                list.add(resultado);
            }
        }

        return list;
    }

    /**
     * Remove um arquivo.
     * @param dto Arquivo a ser removido.
     * @return Arquivo removido para apresentar o resultado da remoção em tela.
     * @throws Exception
     */
    @RemoteMethod
    public Arquivo excluir(Arquivo dto) throws Exception {
        BOFactory.getInstance().createArquivo().excluir(dto);
        return dto;
    }

    /**
     * Decompila um determinado arquivo.
     * @param arquivo Arquivo a ser decompilado.
     * @param opcoes Opções de decompilação.
     * @return Código-fonte do arquivo decompilado.
     * @throws Exception
     */
    @RemoteMethod
    public Arquivo decompilar(Arquivo arquivo, 
                              Opcoes opcoes) throws Exception {
        arquivo = 
                BOFactory.getInstance().createArquivo().carregar(arquivo.getId());

        Arquivo fonte = 
            BOFactory.getInstance().createDecompilacao().decompilar(arquivo, 
                                                                    opcoes);
        arquivo.setFonte(fonte);

        arquivo.setConteudo(null);
        arquivo.getFonte().setConteudo(null);

        return arquivo;
    }

    /**
     * Artifício do DWR para obter o request do contexto.
     * @return Escopo de request do usuário.
     */
    private HttpServletRequest getHttpServletRequest() {
        WebContext ctx = WebContextFactory.get();
        return ctx.getHttpServletRequest();
    }
}

Anote os seus DTO, caso você esteja trabalhando com tipos complexos:

package br.com.netra.jad;

import java.io.Serializable;

import org.directwebremoting.annotations.DataTransferObject;
import org.directwebremoting.annotations.RemoteProperty;


/**
 * Objeto de transferência de dados que representa um arquivo a ser decompilado.
 * Um arquivo pode representar uma referência local ou remota.
 * @author Cleverson Sacramento (cleverson@netra.com.br)
 * @version 13/04/2007 (dd/mm/yyyy)
 */
@DataTransferObject
public class Arquivo implements Serializable {

    /**
     * Identificação única do arquivo.
     */
    @RemoteProperty
    private Long id;

    /**
     * Nome completo do arquivo, composto pelo nome e extensão. 
     * Não deve conter o caminho para o arquivo.
     */
    @RemoteProperty
    private String nome;

    /**
     * Caminho completo ou relativo para o arquivo. Não deve conter o nome do
     * arquivo.
     */
    @RemoteProperty
    private String caminho;

    /**
     * Conteúdo do arquivo para os casos de arquivo remoto. Deve ser utilizado
     * apenas quando o arquivo do cliente precise ser replicado no servidor.
     */
    private byte[] conteudo;

    /**
     * Tamanho do arquivo em byte.
     */
    @RemoteProperty
    private Long tamanho;

    /**
     * Tipo MIME do arquivo. Não representa a extensão do arquivo, que pode
     * ser encontrada no nome do arquivo.
     */
    @RemoteProperty
    private String tipo;

    /**
     * Arquivo-fonte associado ao arquivo após o processo de decompilação.
     */
    @RemoteProperty
    private Arquivo fonte;

    /**
     * Define o nome completo do arquivo, composto pelo nome e extensão. 
     * Não deve conter o caminho para o arquivo.
     * @param nome Nome do arquivo.
     */
    public void setNome(String nome) {
        this.nome = nome;
    }

    /**
     * Obtém o nome completo do arquivo, composto pelo nome e extensão. 
     * Não deve conter o caminho para o arquivo.
     * @return Nome do arquivo.
     */
    public String getNome() {
        return nome;
    }

    /**
     * Define o caminho completo ou relativo para o arquivo. Não deve conter o nome do
     * arquivo.
     * @param caminho Caminho do arquivo.
     */
    public void setCaminho(String caminho) {
        this.caminho = caminho;
    }

    /**
     * Obtém o caminho completo ou relativo para o arquivo. Não deve conter o nome do
     * arquivo.
     * @return Caminho do arquivo.
     */
    public String getCaminho() {
        return caminho;
    }

    /**
     * Define o conteúdo do arquivo para os casos de arquivo remoto. Deve ser utilizado
     * apenas quando o arquivo do cliente precise ser replicado no servidor.
     * @param conteudo Conteúdo do arquivo.
     */
    public void setConteudo(byte[] conteudo) {
        this.conteudo = conteudo;
    }

    /**
     * Obtém o conteúdo do arquivo para os casos de arquivo remoto. Deve ser utilizado
     * apenas quando o arquivo do cliente precise ser replicado no servidor.
     * @return Conteúdo do arquivo.
     */
    public byte[] getConteudo() {
        return conteudo;
    }

    /**
     * Define o tamanho do arquivo em byte.
     * @param tamanho Tamanho do arquivo em byte
     */
    public void setTamanho(Long tamanho) {
        this.tamanho = tamanho;
    }

    /**
     * Obtém o tamanho do arquivo em byte.
     * @return Tamanho do arquivo em byte
     */
    public Long getTamanho() {
        return tamanho;
    }

    /**
     * Define a identificação única do arquivo.
     * @param id Identificação única do arquivo.
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Obtém a identificação única do arquivo.
     * @return Identificação única do arquivo
     */
    public Long getId() {
        return id;
    }

    /**
     * Define o tipo MIME do arquivo. Não representa a extensão do arquivo, que pode
     * ser encontrada no nome do arquivo.
     * @see br.com.netra.jad.util.ConstanteJad#MIME_CLASS
     * @see br.com.netra.jad.util.ConstanteJad#MIME_ZIP
     * @see br.com.netra.jad.util.ConstanteJad#MIME_JAVA
     * @param tipo Tipo MIME do arquivo.
     */
    public void setTipo(String tipo) {
        this.tipo = tipo;
    }

    /**
     * Obtém o tipo MIME do arquivo. Não representa a extensão do arquivo, que pode
     * ser encontrada no nome do arquivo.
     * @see br.com.netra.jad.util.ConstanteJad#MIME_CLASS
     * @see br.com.netra.jad.util.ConstanteJad#MIME_ZIP
     * @see br.com.netra.jad.util.ConstanteJad#MIME_JAVA
     * @return Tipo MIME do arquivo.
     */
    public String getTipo() {
        return tipo;
    }

    /**
     * Define o arquivo-fonte associado ao arquivo após o processo de decompilação.
     * @param fonte Arquivo-fonte associado ao arquivo.
     */
    public void setFonte(Arquivo fonte) {
        this.fonte = fonte;
    }

    /**
     * Define o arquivo-fonte associado ao arquivo após o processo de decompilação.
     * @return Arquivo-fonte associado ao arquivo.
     */
    public Arquivo getFonte() {
        return fonte;
    }
}

No jsp basta importar os seguintes .js, gerados pelo Servlet do DWR que você configurou no seu web.xml.

        <script type='text/javascript' src='dwr/interface/ArquivoDWR.js'></script>
        <script type='text/javascript' src='dwr/engine.js'></script>
        <script type='text/javascript' src='dwr/util.js'></script>

No javascript basta fazer a chamada ao seu Proxy, passando os parâmetros. Ao final da chamada coloque o nome do handle que processará o retorno assincrono do Ajax:

function excluir(){
    var dtos = obterMarcados();

    for(i = 0; i < dtos.length; i++){
        [b]ArquivoDWR.excluir(dtos[i].arquivo, retornoExcluiArquivo);[/b]
    }
}

[b]function retornoExcluiArquivo(dto){[/b]
    var row = getRowByArquivoID(dto.id);
    grid.deleteRow(row);

    info("<u>" + dto.nome + "</u> excluído com sucesso.")
}

Esta implementação utilizando Anotações simplifica bastante a utilização do DWR. Logo, não será mais necessário o arquivo dwr.xml.

Espero que estes exemplos sejam úteis para você!

Poxa… ficou legal essa estrutura que vc fez. Muito obrigada pela ajuda.

O meu projeto é EJB e eu to usando classes dao pra acessar o banco de dados.
Eu preciso colocar o @DataTransferOBject nos daos tb?
E eu uso Facade pra camada servlet acessar os rns, que acessam os vos e daos.
Eu tinha implementado o dwr antes no facade, mas ai dava o problema de que o objeto não foi encontrado.
Modifiquei e coloquei como vc fez aí. Criei uma pasta só pra DWR e coloquei @DataTransfer nos vos, daos e rns. E no DWR eu coloquei @RemotProxy
So que agora ficou confuso, pq eu apenas quero consultar uma coleção de objetos a partir de um código passado como parâmetro e eu to com dúvida de como se implementa em javascript na pág jsp.

Poxa… ficou legal essa estrutura que vc fez. Muito obrigada pela ajuda.

O meu projeto é EJB e eu to usando classes dao pra acessar o banco de dados.
Eu preciso colocar o @DataTransferOBject nos daos tb?
E eu uso Facade pra camada servlet acessar os rns, que acessam os vos e daos.
Eu tinha implementado o dwr antes no facade, mas ai dava o problema de que o objeto não foi encontrado.
Modifiquei e coloquei como vc fez aí. Criei uma pasta só pra DWR e coloquei @DataTransfer nos vos, daos e rns. E no DWR eu coloquei @RemotProxy
So que agora ficou confuso, pq eu apenas quero consultar uma coleção de objetos a partir de um código passado como parâmetro e eu to com dúvida de como se implementa em javascript na pág jsp. :?

Fico agradecida por estarem me ajudando!!! :smiley: