corner imagecorner image
IDEPlatformPluginsDocs & SupportCommunityPartners

Introdução ao Ajax para aplicações Web Java

Este documento oferece uma introdução ao Ajax e demonstra alguns dos recursos do NetBeans IDE que lhe permitem programar de forma mais rápida e eficaz ao trabalhar com tecnologias relacionadas ao Ajax. Enquanto aprende sobre a funcionalidade de baixo nível do Ajax, você constrói um aplicativo simples que utiliza o autocompletar em um campo de texto. O conteúdo aqui foi adaptado do artigo e do aplicativo de amostra de Greg Murray Using Ajax with Java Technology.

Ajax significa Asynchronous JavaScript and XML. Na essência, o Ajax é uma forma eficiente de um aplicativo da Web manipular as interações de usuário com uma página da Web: uma forma que reduz a necessidade de fazer uma atualização da página ou uma recarga completa da página para cada interação de usuário. Isso permite um comportamento detalhado (similar ao de um aplicativo de área de trabalho ou aplicativo Web com base em plug-in) na utilização de um navegador. As interações do Ajax são manipuladas assincronamente em segundo plano. Quando isso acontece, um usuário pode continuar trabalhando com a página. As interações do Ajax são iniciadas pelo código JavaScript. Quando a interação do Ajax é concluída, o JavaScript atualiza o código-fonte HTML da página. As alterações são feitas imediatamente sem requerer uma atualização da página. As interações do Ajax podem ser utilizadas para fazer coisas como validar entradas do formulário (enquanto o usuário as está fazendo) utilizando lógica do lado do servidor, recuperar dados detalhados do servidor, atualizar dinamicamente os dados em uma página e submete formulários parciais a partir da página.

Conteúdo

O conteúdo desta página se aplica ao IDE NetBeans 6.7, 6.8 e 6.9

Para concluir este tutorial, você precisa dos seguintes recursos e softwares.

Software ou recurso Versão requerida
NetBeans IDE, pacote Java 6.7, 6.8 ou 6.9.9
Java Development Kit (JDK) 6
Servidor GlassFish
ou
Servidor Tomcat
3
 
versão 6.x

Notas:

  • A instalação Web e Java EE permite que você instale opcionalmente o servidor GlassFish 3.0.1 e o contêiner do servlet Apache Tomcat 6.0.x.
  • Este tutorial presume que você tenha conhecimento das várias tecnologias que ele utiliza (ou seja, HTML, CSS, JavaScript, Java e JSP). Ele tenta fornecer uma visão geral da funcionalidade fornecida pelo código, mas não explica como o código funciona linha por linha.
  • Se você precisar comparar seu projeto com uma solução que funciona, baixe o aplicativo de amostra.

Visão geral do aplicativo

Imagine uma página da Web em que um usuário pode procurar informações sobre compositores de música. A página inclui um campo onde o usuário pode indicar o nome do compositor. No aplicativo de exemplo, o campo de entrada possui um recurso autocompletar. Em outras palavras, o usuário pode digitar parte do nome do compositor e o aplicativo da Web tenta completar o nome, listando todos os compositores cujo nome ou sobrenome começa com os caracteres indicados. O recurso auto-completar poupa o usuário de ter que lembrar o nome completo do compositor e pode fornecer um caminho mais intuitivo e direto para a informação procurada.

Aplicação de amostra exibida no navegador

Implementar o autocompletar em um campo de pesquisa é algo que pode ser feito por meio do Ajax. O Ajax funciona através da utilização de um objeto XMLHttpRequest para passar requisições e respostas assincronamente entre o cliente e o servidor. O diagrama seguinte ilustra o fluxo do processo da comunicação que acontece entre o cliente e o servidor.

Diagrama de fluxo do processo Ajax

O fluxo do processo do diagrama pode ser descrito pelas seguintes etapas:

  1. O usuário aciona um evento, por exemplo, liberando uma tecla ao digitar um nome. Isso resulta em uma chamada do JavaScript a uma função que inicializa um objeto XMLHttpRequest.
  2. O objeto XMLHttpRequest é configurado com um parâmetro de requisição que inclui o ID do componente que acionou o evento e qualquer valor que o usuário indicou. O objeto XMLHttpRequest faz uma solicitação assíncrona ao servidor Web.
  3. No servidor da Web, um objeto como um servlet ou um listener manipula a requisição. Os dados são recuperados do armazenamento de dados, e é preparada uma resposta contendo os dados do formulário em um documento XML.
  4. Finalmente, o objeto XMLHttpRequest recebe os dados XML utilizando uma função de retorno de chamada, processa-o e atualiza o HTML DOM (Document Object Model) para exibir a página que contém os novos dados.

Este tutorial demonstra como construir o cenário de autocompletar, seguindo o fluxo do processo indicado no diagrama acima. Primeiro você cria os arquivos do lado do cliente para a apresentação e a funcionalidade necessária para gerar o objeto XMLHttpRequest. Em seguida, você configura o lado do servidor, criando o armazenamento de dados e a lógica corporativa utilizando tecnologia com base em Java. Finalmente, você retorna ao lado do cliente e implementa callback(), e outra funcionalidade JavaScript para atualizar o HTML DOM.


Programando o lado do cliente: Parte 1

Comece criando um novo projeto de aplicativo da Web no IDE. O IDE contém modelos internos para vários tipos de projeto.

  1. Escolha Arquivo > Novo projeto. Em Categorias, selecione Web. Em Projetos, selecione Aplicação Web e clique em Próximo.
  2. No painel Nome e localização, insira MyAjaxApp como o Nome do projeto. O campo Localização do projeto permite que você especifique a localização do projeto em seu computador. Deixe as outras opções como padrão e clique em Próximo.
    Assistente Novo aplicativo da Web: painel Nome e localização
  3. No painel Servidor e configurações, selecione o servidor em que deseja implantar o aplicativo. Somente os servidores registrados com o IDE estão listados.
    Assistente Novo projeto de aplicativo: painel Configurações do servidor
  4. Aceite as outras configurações padrão e clique em Terminar. O projeto é gerado no sistema de arquivos e aberto no IDE.

Quando os projetos baseados em Java são criados, é gerado automaticamente um script de construção Ant que lhe permite compilar o projeto de forma que ele possa ser implantado imediatamente e executado em um servidor que tenha sido registrado no IDE.

Uma página de entrada padrão index.jsp é gerada e aberta no editor de código-fonte do IDE. Além disso, seu projeto aparece na janela Projetos.

Janela Projetos contendo o projeto recém-criado

Antes de começar a codificar, tente rapidamente executar o aplicativo para garantir que a configuração entre o IDE, seu servidor e o navegador esteja configurada corretamente.

  1. Na janela Projetos, clique com o botão direito do mouse no nó do projeto e escolha Executar.

    O aplicativo é compilado, o servidor do aplicativo é iniciado e o aplicativo é implantado nele e executado. O IDE abre seu navegador padrão e exibe a mensagem "Hello World" que é incluída em index.jsp.

Utilizando o editor HTML

Paleta exibindo elementos HTML

Agora que você tem certeza de que seu ambiente está configurado corretamente, comece transformando sua página de índice na interface de auto-completar que será vista pelos usuários.

Uma das vantagens da utilização de um IDE é que o editor em que você trabalha normalmente fornece autocompletar de código, que, se você aprender a aplicar, pode aumentar rapidamente a sua produtividade. O editor de código-fonte do IDE geralmente se adapta à tecnologia que está sendo utilizada, portanto, se você estiver trabalhando em uma página HTML, pressionar a combinação de teclas de autocompletar (Ctrl-Espaço) produzirá sugestões para marcações HTML e atributos. Como será mostrado mais tarde, o mesmo se aplica a outras tecnologias, tais como CSS e JavaScript.

Um segundo recurso que pode ser utilizado é a Paleta do IDE. A Paleta fornece modelos fáceis de utilizar para elementos que são aplicados comumente na tecnologia em que você está codificando. Você simplesmente clica em um item e arrasta-o para um local no arquivo aberto no editor de código-fonte.

É possível visualizar ícones grandes (como exibido aqui) clicando com o botão direito do mouse na Paleta e escolhendo Mostrar ícones grandes.


  1. Substitua o conteúdo das marcações <title> para ler: Autocompletar utilizando AJAX. Além disso, substitua as marcações <h2> pelas marcações <h1> e digite o mesmo texto das marcações <title>. A página de índice não necessita codificação de script do lado do servidor, portanto, você pode excluir com segurança quaisquer remanescentes criados por padrão. A página de índice agora deve aparecer como mostrado abaixo.
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       "http://www.w3.org/TR/html4/loose.dtd">
    
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>Auto-Completion using AJAX</title>
        </head>
        <body>
            <h1>Auto-Completion using AJAX</h1>
        </body>
    </html>
    
  2. Adicione algum texto explicativo para descrever a finalidade do campo de texto. É possível copiar e colar no texto a seguir, no ponto logo abaixo das marcações <h1>:
    <p>Esse exemplo mostra como criar autocompletar em tempo real utilizando interações Ajax (Asynchronous JavaScript and XML).</p>
    
    <p>No formulário abaixo, insira um nome. Os nomes possíveis que serão completados são exibidos abaixo do formulário. Por exemplo, tente digitar "Bach,&quot "Mozart" ou "Stravinsky,"
        em seguida, clique em uma das seleções para ver os detalhes do compositor.</p>
    
  3. Adicione um formulário HTML à página. Faça isso utilizando os elementos listados na Paleta do IDE. Se a Paleta não estiver aberta, escolha Janela > Paleta no menu principal. Em seguida, em Formulários HTML, clique e arraste um elemento Formulário para a página, um ponto abaixo das marcações <p> que você acabou de adicionar. A caixa de diálogo Inserir formulário é aberta. Especifique o seguinte:

    • Ação: preenchimento automático
    • Método: GET
    • Nome: autofillform
    Caixa de diálogo Inserir formulário

    Clique em OK. As marcações HTML <form> são inseridas na página que contém os atributos especificados. (GET é aplicado por padrão e, portanto, não é declarado explicitamente.)

  4. Adicione uma tabela HTML à página. Sob a categoria HTML na Paleta, clique em um elemento Tabela e arraste-o para um ponto entre as marcações <form>. A caixa de diálogo Inserir tabela é aberta. Especifique o seguinte:

    • Linhas: 2
    • Colunas: 2
    • Tamanho da borda: 0
    • Preenchimento de células: 5
    Caixa de diálogo Inserir tabela
  5. Clique com o botão direito do mouse no Editor de código-fonte e escolha Formatar. Isso limpa o código. Seu formulário agora deve ser semelhante ao abaixo:
    <form name="autofillform" action="autocomplete">
      <table border="0" cellpadding="5">
        <thead>
          <tr>
            <th></th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td></td>
            <td></td>
          </tr>
          <tr>
            <td></td>
            <td></td>
          </tr>
        </tbody>
      </table>
    </form>
    
  6. Na primeira linha da tabela, digite o seguinte texto na primeira coluna (alterações em negrito):
    <td><strong>Nome do compositor:</strong></td>
  7. Na segunda coluna da primeira linha, em vez de arrastar um campo Entrada de texto da Paleta, digite o código abaixo manualmente (alterações em negrito):
    <td>
        <input type="text"
            size="40"
            id="complete-field"
            onkeyup="doCompletion();">
    </td>
    
    Enquanto digita, tente utilizar o suporte autocompletar de código embutido do IDE. Por exemplo, digite <i e, em seguida, pressione Ctrl-Espaço. Uma lista de opções sugeridas é exibida abaixo do seu cursor e uma descrição do elemento selecionado aparece em uma caixa acima. De fato, você pode pressionar Ctrl-Espaço a qualquer momento em que estiver codificando no editor de código-fonte para ter acesso às opções possíveis. Além disso, caso só haja uma opção possível, pressionar Ctrl-Espaço completará automaticamente o nome do elemento.
    Autocompletar de código exibido no Editor de código fonte

O atributo onkeyup que você digitou acima aponta para uma função JavaScript nomeada doCompletion(). Essa função é chamada toda vez que uma tecla é pressionada no campo de texto do formulário, e mapeia para a chamada JavaScript representada no fluxograma do Ajax acima.

Utilizando o editor JavaScript

O novo editor JavaScript do IDE fornece muitas possibilidades de edição avançada, tais como autocompletar de código inteligente, realce de semântica, renomeação instantânea e capacidades de refatoração, assim como muitos outros recursos. Consulte o Editando JavaScript para uma introdução e http://wiki.netbeans.org/JavaScript para especificações detalhadas.

O autocompletar de código JavaScript é automaticamente fornecido quando você codifica em arquivos .js, assim como em marcações <script> quando trabalha com outras tecnologias (ou seja, HTML, RHTML, JSP, PHP). Quando você utiliza o editor JavaScript, o IDE fornece informações sobre compatibilidade do navegador, dependendo dos tipos de navegador e as versões especificadas no painel Opções de JavaScript. Abra o painel Opções de JavaScript, escolhendo Ferramentas > Opções (NetBeans > Preferências no Mac) e, em seguida, Miscelâneos > JavaScript.

Painel Opções de JavaScript

O IDE fornece suporte imediato para Firefox, Internet Explorer, Safari e Opera. No painel Opções de JavaScript, você também pode especificar a versão do mecanismo JavaScript a qual auto-completar de código se aplica.

Adicione um arquivo JavaScript ao aplicativo e comece a implementar doCompletion().

  1. Na janela Projetos, clique com o botão direito do mouse no nó do projeto e escolha Novo > arquivo JavaScript. (Se o arquivo JavaScript não estiver listado, escolha Outro. Em seguida, escolha o arquivo JavaScript na categoria Web no assistente para Novo arquivo.)
  2. Chame o arquivo de javascript, e digite web no campo de texto Pasta para colocá-lo na subpasta da Web.
  3. Clique em Terminar e observe que o novo arquivo JavaScript aparece na janela Projetos na pasta Páginas da Web.

    Nota: se você está pensando no porquê a pasta web não é exibida, clique na janela Arquivos (Janela > Arquivos). A janela Projetos fornece uma visualização lógica do conteúdo importante do projeto, enquanto a janela Arquivos oferece uma representação do conteúdo do projeto inteiro em uma visualização baseada em diretório.

  4. Digite o código abaixo em javascript.js.
    var req;
    var isIE;
    
    function init() {
        completeField = document.getElementById("complete-field");
    }
    
    function doCompletion() {
            var url = "autocomplete?action=complete&id=" + escape(completeField.value);
            req = initRequest();
            req.open("GET", url, true);
            req.onreadystatechange = callback;
            req.send(null);
    }
    
    function initRequest() {
        if (window.XMLHttpRequest) {
            if (navigator.userAgent.indexOf('MSIE') != -1) {
                isIE = true;
            }
            return new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            isIE = true;
            return new ActiveXObject("Microsoft.XMLHTTP");
        }
    }

    O código acima executa um verificação simples de compatibilidade do navegador para o Firefox 3 e para o Internet Explorer versões 6 e 7). Se desejar incorporar um código mais robusto para questões de compatibilidade, considere utilizar este script de detecção de navegador disponível em http://www.quirksmode.org.

  5. Volte para index.jsp e adicione uma referência ao arquivo JavaScript entre as marcas <head>.
    <script type="text/javascript" src="javascript.js"></script>

    É possível alternar rapidamente entre as páginas abertas no editor de código-fonte, pressionando Ctrl-Tab.

  6. Insira uma chamada a init() na marca de abertura <body>.
    <body onload="init()">
    Isso garante que init() é chamada toda vez que a página é carregada.

A função de doCompletion() é:

  • crie uma URL que contenha dados que possam ser reutilizados pelo lado do servidor,
  • inicialize um objeto XMLHttpRequest, e
  • solicite que o objeto XMLHttpRequest envie uma solicitação assíncrona para o servidor.

O objeto XMLHttpRequest é o coração do Ajax e se tornou o padrão de fato para permitir que dados XML sejam passados assincronamente por meio de HTTP. A interação Asynchronous implica que o navegador pode continuar a processar eventos na página depois que a requisição é enviada. Os dados são passados em segundo plano, e podem ser carregados automaticamente na página exigindo uma atualização da página.

Observe que o objeto XMLHttpRequest é realmente criado por initRequest(), que é chamada por doCompletion(). A função verifica se XMLHttpRequest pode ser entendido pelo navegador e, se for o caso, cria um objeto XMLHttpRequest. Caso contrário, ela verifica ActiveXObject (o XMLHttpRequest equivalente do Internet Explorer 6) e cria um ActiveXObject, se identificado.

Três parâmetros são especificados quando você cria um objeto XMLHttpRequest: um URL, o método HTTP (GET ou POST), e se a interação é assíncrona ou não. No exemplo acima, os parâmetros são:

  • A URL autocomplete, e o texto indicado no complete-field pelo usuário:
    var url = "autocomplete?action=complete&id=" + escape(completeField.value);
  • GET, significando que as interações HTTP utilizam o método GET, e
  • true, significando que a interação é assíncrona:
    req.open("GET", url, true);

Se a interação for definida como assíncrona, uma função de chamada de retorno deve ser especificada. A função callback dessa interação é definida com a instrução:

req.onreadystatechange = callback;

e uma função callback() deve ser definida mais tarde. A interação HTTP começa quando XMLHttpRequest.send() é chamada. Essa ação mapeia para a solicitação HTTP que é enviada para o servidor Web no fluxograma acima.


Programando o lado do servidor

O IDE oferece suporte abrangente para programação Web do lado do servidor. Embora isso inclua o suporte a editor básico para muitas linguagens de programação e de script populares, também inclui serviços Web, tais como SOAP, REST, SaaS e estruturas orientados a MVC, tais como JSF, Spring, Struts, Ruby on Rails e Grails. O suporte a Ajax é incluído em componentes Woodstock para projetos JSF Visual Web e Dynamic Faces, uma extensão JSF que oferece a funcionalidade do Ajax. Também existem inúmeros plug-ins para frameworks orientados a Ajax, tais como GWT, Struts2 e jMaki.

A lógica corporativa do aplicativo processa as requisições, recuperando dados do armazenamento de dados e, em seguida, preparando e enviando a resposta. Isso é implementado aqui por meio de um servlet. Antes de começar a codificar o servlet, configure o armazenamento de dados e a funcionalidade requerida pelo servlet para acessar os dados.

Criando o armazenamento de dados

Para esse aplicativo simples, você cria uma classe nomeada ComposerData que mantém os dados do compositor utilizando um HashMap. Um HashMap permite armazenar pares de itens vinculados em pares de valores-chave. Você também pode criar uma classe Composer que permita ao servlet recuperar dados de entradas no HashMap.

  1. Clique com o botão direito do mouse no nó do projeto na janela Projetos e escolha Novo > Classe Java.
  2. Nomeie a classe ComposerData e insira com.ajax no campo Pacote. Isso cria um novo pacote que contém a classe, assim como outras classes que serão criadas mais tarde.
  3. Clique em Terminar. A classe é criada e aberta no editor de código-fonte.
  4. No editor de código-fonte, cole o seguinte código:
    package com.ajax;
    
    import java.util.HashMap;
    
    /**
     *
     * @author nbuser
     */
    public class ComposerData {
    
        private HashMap composers = new HashMap();
    
        public HashMap getComposers() {
            return composers;
        }
    
        public ComposerData() {
    
            composers.put("1", new Composer("1", "Johann Sebastian", "Bach", "Baroque"));
            composers.put("2", new Composer("2", "Arcangelo", "Corelli", "Baroque"));
            composers.put("3", new Composer("3", "George Frideric", "Handel", "Baroque"));
            composers.put("4", new Composer("4", "Henry", "Purcell", "Baroque"));
            composers.put("5", new Composer("5", "Jean-Philippe", "Rameau", "Baroque"));
            composers.put("6", new Composer("6", "Domenico", "Scarlatti", "Baroque"));
            composers.put("7", new Composer("7", "Antonio", "Vivaldi", "Baroque"));
    
            composers.put("8", new Composer("8", "Ludwig van", "Beethoven", "Classical"));
            composers.put("9", new Composer("9", "Johannes", "Brahms", "Classical"));
            composers.put("10", new Composer("10", "Francesco", "Cavalli", "Classical"));
            composers.put("11", new Composer("11", "Fryderyk Franciszek", "Chopin", "Classical"));
            composers.put("12", new Composer("12", "Antonin", "Dvorak", "Classical"));
            composers.put("13", new Composer("13", "Franz Joseph", "Haydn", "Classical"));
            composers.put("14", new Composer("14", "Gustav", "Mahler", "Classical"));
            composers.put("15", new Composer("15", "Wolfgang Amadeus", "Mozart", "Classical"));
            composers.put("16", new Composer("16", "Johann", "Pachelbel", "Classical"));
            composers.put("17", new Composer("17", "Gioachino", "Rossini", "Classical"));
            composers.put("18", new Composer("18", "Dmitry", "Shostakovich", "Classical"));
            composers.put("19", new Composer("19", "Richard", "Wagner", "Classical"));
    
            composers.put("20", new Composer("20", "Louis-Hector", "Berlioz", "Romantic"));
            composers.put("21", new Composer("21", "Georges", "Bizet", "Romantic"));
            composers.put("22", new Composer("22", "Cesar", "Cui", "Romantic"));
            composers.put("23", new Composer("23", "Claude", "Debussy", "Romantic"));
            composers.put("24", new Composer("24", "Edward", "Elgar", "Romantic"));
            composers.put("25", new Composer("25", "Gabriel", "Faure", "Romantic"));
            composers.put("26", new Composer("26", "Cesar", "Franck", "Romantic"));
            composers.put("27", new Composer("27", "Edvard", "Grieg", "Romantic"));
            composers.put("28", new Composer("28", "Nikolay", "Rimsky-Korsakov", "Romantic"));
            composers.put("29", new Composer("29", "Franz Joseph", "Liszt", "Romantic"));
    
            composers.put("30", new Composer("30", "Felix", "Mendelssohn", "Romantic"));
            composers.put("31", new Composer("31", "Giacomo", "Puccini", "Romantic"));
            composers.put("32", new Composer("32", "Sergei", "Rachmaninoff", "Romantic"));
            composers.put("33", new Composer("33", "Camille", "Saint-Saens", "Romantic"));
            composers.put("34", new Composer("34", "Franz", "Schubert", "Romantic"));
            composers.put("35", new Composer("35", "Robert", "Schumann", "Romantic"));
            composers.put("36", new Composer("36", "Jean", "Sibelius", "Romantic"));
            composers.put("37", new Composer("37", "Bedrich", "Smetana", "Romantic"));
            composers.put("38", new Composer("38", "Richard", "Strauss", "Romantic"));
            composers.put("39", new Composer("39", "Pyotr Il'yich", "Tchaikovsky", "Romantic"));
            composers.put("40", new Composer("40", "Guiseppe", "Verdi", "Romantic"));
    
            composers.put("41", new Composer("41", "Bela", "Bartok", "Post-Romantic"));
            composers.put("42", new Composer("42", "Leonard", "Bernstein", "Post-Romantic"));
            composers.put("43", new Composer("43", "Benjamin", "Britten", "Post-Romantic"));
            composers.put("44", new Composer("44", "John", "Cage", "Post-Romantic"));
            composers.put("45", new Composer("45", "Aaron", "Copland", "Post-Romantic"));
            composers.put("46", new Composer("46", "George", "Gershwin", "Post-Romantic"));
            composers.put("47", new Composer("47", "Sergey", "Prokofiev", "Post-Romantic"));
            composers.put("48", new Composer("48", "Maurice", "Ravel", "Post-Romantic"));
            composers.put("49", new Composer("49", "Igor", "Stravinsky", "Post-Romantic"));
            composers.put("50", new Composer("50", "Carl", "Orff", "Post-Romantic"));
    
        }
    }

Crie a classe Composer:

  1. Clique com o botão direito do mouse no nó do projeto na janela Projetos e escolha Novo > Classe Java.
  2. Nomeie a classe Composer e escolha com.ajax na lista suspensa no campo Pacote. Clique em Próximo.
  3. Clique em Terminar. A classe é criada e aberta no editor de código-fonte.
  4. No editor de código-fonte, cole o seguinte código:
    package com.ajax;
    
    public class Composer {
    
        private String id;
        private String firstName;
        private String lastName;
        private String category;
    
        public Composer (String id, String firstName, String lastName, String category) {
            this.id = id;
            this.firstName = firstName;
            this.last Name = lastName;
            this.category = category;
        }
    
        public String getCategory() {
            return category;
        }
    
        public String getId() {
            return id;
        }
    
        public String getFirstName() {
            return firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    }

Criando um servlet

Crie um servlet para manipular a URL autocomplete que é recebida pela solicitação de entrada.

  1. Clique com o botão direito do mouse no nó do projeto na janela Projetos e escolha Novo > Servlet. (Se Servlet não estiver exibido, escolha Outro, em seguida, selecione Servlet na categoria Web).
  2. Nomeie o servlet AutoCompleteServlet e escolha com.ajax na lista suspensa no campo Pacote. Clique em Próximo.
  3. No painel Configurar deployment do servlet, note que o nome do servlet é AutoCompleteServlet e o caminho totalmente qualificado para a classe é com.ajax.AutoCompleteServlet. Altere o padrão de URL para /autocomplete de forma que ele corresponda à URL que foi definida anteriormente no objeto XMLHttpRequest. Esse painel poupa a etapa de adicionar manualmente esses detalhes no descritor de deployment.
  4. Clique em Terminar. O servlet é criado e aberto no Editor de código-fonte. O descritor de deployment web.xml também é atualizado para indicar que o servlet está registrado no aplicativo.

Os únicos métodos que você precisa substituir são doGet(), para definir como o servlet manipula a solicitação autocomplete GET, e init(), que precisa iniciar um ServletContext de forma que o servlet possa acessar outras classes no aplicativo quando ele é posto em serviço.

É possível substituir métodos de superclasses utilizando o menu pop-up Inserir código do IDE. Implemente init() fazendo isso.

  1. Coloque o seu cursor abaixo da declaração da classe AutoCompleteServlet no Editor de código-fonte. Pressione Alt-Insert (Ctrl-I no Mac) para abrir o menu popup Gerar código.
    Menu popup Inserir código exibido no editor de código-fonte
  2. Escolha Sobrescrever método. Na caixa de diálogo que é exibida, todas as classes que AutoCompleteServlet herda são exibidas. Expanda o nó GenericServlet e selecione init(Servlet Config arg0).
    Caixa de diálogo Sobrescrever listando as classes herdadas
  3. Clique em OK. O método init() é adicionado no editor de código-fonte.
  4. Adicione uma variável para um objeto ServletContext e modifique init() (alterações em negrito):
    private ServletContext context;
    
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.context = config.getServletContext();
    }
  5. Adicione uma instrução de importação para ServletContext. É possível fazer isso clicando no ícone da lâmpada exibido na margem esquerda do Editor de código fonte
    Dica de importação exibida na margem esquerda do editor de código-fonte

O método doGet() precisa analisar a URL da requisição, recuperar dados do armazenamento de dados e preparar uma resposta em formato XML. Note que a declaração do método foi gerada quando você criou a classe. Para visualizá-la, você talvez precise expandir os métodos HttpServlet, clicando no ícone de expansão (ícone de expansão) na margem esquerda.

  1. Adicione as declarações de variável seguintes abaixo da declaração da classe AutocompleteServlet.
    private ComposerData compData = new ComposerData();
    private HashMap composers = compData.getComposers();
    Isso cria um HashMap de todos os dados do compositor, que é, em seguida, utilizado por doGet().
  2. Role para baixo para doGet() e implemente o método da seguinte forma:
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
    
        String action = request.getParameter("action");
        String targetId = request.getParameter("id");
        StringBuffer sb = new StringBuffer();
    
        if (targetId != null) {
            targetId = targetId.trim().toLowerCase();
        } else {
            context.getRequestDispatcher("/error.jsp").forward(request, response);
        }
    
        boolean namesAdded = false;
        if (action.equals("complete")) {
    
            // check if user sent empty string
            if (!targetId.equals("")) {
    
                Iterator it = composers.keySet().iterator();
    
                while (it.hasNext()) {
                    String id = (String) it.next();
                    Composer composer = (Composer) composers.get(id);
    
                    if ( // targetId matches first name
                         composer.getFirstName().toLowerCase().startsWith(targetId) ||
                         // targetId matches last name
                         composer.getLastName().toLowerCase().startsWith(targetId) ||
                         // targetId matches full name
                         composer.getFirstName().toLowerCase().concat(" ")
                            .concat(composer.getLastName().toLowerCase()).startsWith(targetId)) {
    
                        sb.append("<composer>");
                        sb.append("<id>" + composer.getId() + "</id>");
                        sb.append("<firstName>" + composer.getFirstName() + "</firstName>");
                        sb.append("<lastName>" + composer.getLastName() + "</lastName>");
                        sb.append("</composer>");
                        namesAdded = true;
                    }
                }
            }
    
            if (namesAdded) {
                response.setContentType("text/xml");
                response.setHeader("Cache-Control", "no-cache");
                response.getWriter().write("<composers>" + sb.toString() + "</composers>");
            } else {
                //nothing to show
                response.setStatus(HttpServletResponse.SC_NO_CONTENT);
            }
        }
    }

Como pode ver neste servlet, não há nada exatamente novo que você precise aprender para escrever código do lado do servidor para processamento Ajax. O tipo de conteúdo da resposta precisa ser definido como text/xml para casos em que você deseje trocar documentos XML. Com o Ajax também é possível trocar texto sem formatação ou até mesmo trechos de código de JavaScript, que podem ser avaliados ou executados pela função chamada de retorno no cliente. Observe também que alguns navegadores podem armazenar em cache os resultados, portanto, talvez seja necessário definir o cabeçalho Cache-Control HTTP como no-cache.

Nesse exemplo, o servlet gera um documento XML que contém todos os compositores com nome ou sobrenome começando com os caracteres digitados pelo usuário. Esse documento mapeia para os dados XML ilustrados no diagrama de fluxo acima. Aqui está um exemplo de um documento XML que é retornado para o objeto XMLHttpRequest:

<composers>
    <composer>
        <id>12</id>
        <firstName>Antonin</firstName>
        <lastName>Dvorak</lastName>
    </composer>
    <composer>
        <id>45</id>
        <firstName>Aaron</firstName>
        <lastName>Copland</lastName>
    </composer>
    <composer>
        <id>7</id>
        <firstName>Antonio</firstName>
        <lastName>Vivaldi</lastName>
    </composer>
    <composer>
        <id>2</id>
        <firstName>Arcangelo</firstName>
        <lastName>Corelli</lastName>
    </composer>
</composers>

É possível utilizar o Monitor HTTP do IDE para visualizar os dados XML retornados ao concluir o aplicativo.


Programando o lado do cliente: Parte 2

Você deve definir a função chamada de retorno para manipular a resposta do servidor, e adicionar qualquer funcionalidade necessária para refletir alterações na página visualizadas pelo usuário. Isso requer a modificação do HTML DOM. Finalmente, você pode trabalhar no editor CSS do IDE para adicionar uma folha de estilo simples na apresentação.

Adicionando a funcionalidade Retorno de chamada

A função chamada de retorno é chamada assincronamente em pontos específicos durante a interação HTTP quando a propriedade objeto readyState do XMLHttpRequest é alterada. No aplicativo que está sendo construído, a função chamada de retorno é callback(). Você lembra que em doCompletion(), chamada de retorno foi definida como a propriedade XMLHttpRequest.onreadystatechange para uma função. Agora, implemente a função callback da seguinte forma.

  1. Abra javascript.js no editor de código-fonte e digite o código abaixo.
    function callback() {
        if (req.readyState == 4) {
            if (req.status == 200) {
                parseMessages(req.responseXML);
            }
        }
    }

Um readyState de "4" significa a conclusão da interação HTTP. A API de XMLHttpRequest.readState indica que há 5 valores possíveis que podem ser definidos. Dentre eles estão:

Valor readyState Definição do status do objeto
0 não inicializado
1 carregando
2 carregado
3 interativo
4 completo

Observe que a função parseMessages() somente é chamada quando o XMLHttpRequest.readyState é "4" e o status (a definição do código de status HTTP da solicitação) é "200", significando êxito. Você definirá parseMessages() em seguida em Atualizando o HTML DOM.

Atualizando o HTML DOM

A função parseMessages() manipula os dados XML de entrada. Fazendo isso, ele conta com várias funções auxiliares, tais como appendComposer(), getElementY() e clearTable(). Você também deve introduzir novos elementos na página de índice, tal como uma segunda tabela HTML que serve como a caixa autocompletar e os IDs dos elementos de forma que eles possam ser referenciados em javascript.js. Finalmente, você cria novas variáveis correspondendo aos IDs dos elementos em index.jsp, as inicializa na função init() que implementou anteriormente e adiciona alguma funcionalidade que seja necessária toda vez que index.jsp é carregado.

Nota: as funções e elementos que você cria nas etapas seguintes funcionam de forma independente. Recomendamos que você percorra esta seção, em seguida, examine o código quando tudo estiver no lugar.

  1. Abra index.jsp no editor de código-fonte e digite o código abaixo para a segunda linha da tabela HTML que você criou anteriormente.
    <tr>
        <td id="auto-row" colspan="2">
            <table id="complete-table" />
        <td/>
    </tr>
    A segunda linha da tabela contém outra tabela HTML. Essa tabela representa a caixa autocompletar que será utilizada para preencher os nomes de compositor.
  2. Abra javascript.js no editor de código-fonte e as três variáveis seguintes no início do arquivo.
    var completeField;
    var completeTable;
    var autoRow;
  3. Adicione as seguintes linhas (em negrito) na função init().
    function init() {
        completeField = document.getElementById("complete-field");
        completeTable = document.getElementById("complete-table");
        autoRow = document.getElementById("auto-row");
        completeTable.style.top = getElementY(autoRow) + "px";
    }
    Uma finalidade de init() é tornar os elementos dentro de index.jsp acessíveis para outras funções que modificarão o DOM da página de índice.
  4. Adicione appendComposer() a javascript.js.
    function appendComposer(firstName,lastName,composerId) {
    
        var row;
        var cell;
        var linkElement;
    
        if (isIE) {
            completeTable.style.display = 'block';
            row = completeTable.insertRow(completeTable.rows.length);
            cell = row.insertCell(0);
        } else {
            completeTable.style.display = 'table';
            row = document.createElement("tr");
            cell = document.createElement("td");
            row.appendChild(cell);
            completeTable.appendChild(row);
        }
    
        cell.className = "popupCell";
    
        linkElement = document.createElement("a");
        linkElement.className = "popupItem";
        linkElement.setAttribute("href", "autocomplete?action=lookup&id=" + composerId);
        linkElement.appendChild(document.createTextNode(firstName + " " + lastName));
        cell.appendChild(linkElement);
    }
    Essa função cria uma nova linha da tabela, insere um link em um compositor utilizando os dados passados para a função através de seus três parâmetros e insere a linha no elemento complete-table da página de índice.
  5. Adicione getElementY() a javascript.js.
    function getElementY(element){
    
        var targetTop = 0;
    
        if (element.offsetParent) {
            while (element.offsetParent) {
                targetTop += element.offsetTop;
                element = element.offsetParent;
            }
        } else if (element.y) {
            targetTop += element.y;
        }
        return targetTop;
    }
    Essa função é aplicada para localizar a posição vertical do elemento pai. Isso é necessário porque a posição atual do elemento, quando ele é exibido, frequentemente depende do tipo e da versão do navegador. Note que o elemento complete-table, quando é exibido contendo nomes de compositor, é deslocado para o lado inferior direito da tabela em que ele está. O posicionamento correta da altura é determinado por getElementY().

    Nota: Consulte esta explicação de deslocamento em http://www.quirksmode.org/.

  6. Adicione clearTable() a javascript.js.
    function clearTable() {
        if (completeTable.getElementsByTagName("tr").length > 0) {
            completeTable.style.display = 'none';
            for (loop = completeTable.childNodes.length -1; loop >= 0 ; loop--) {
                completeTable.removeChild(completeTable.childNodes[loop]);
            }
        }
    }
    Essa função define a exibição do elemento complete-table como 'none' (ou seja, o torna invisível) e remove quaisquer entradas de nome de compositor existentes que tenham sido criadas.
  7. Modifique a função callback() para que chame clearTable() cada vez que novos dados forem recebidos do servidor. Quaisquer entradas do compositor que já existem na caixa auto-completar são, portanto, removidas antes que esta seja preenchida com novas entradas.
    function callback() {
    
        clearTable();
    
        if (req.readyState == 4) {
            if (req.status == 200) {
                parseMessages(req.responseXML);
            }
        }
    }
  8. Adicione parseMessages() a javascript.js.
    function parseMessages(responseXML) {
    
        // no matches returned
        if (responseXML == null) {
            return false;
        } else {
    
            var composers = responseXML.getElementsByTagName("composers")[0];
    
            if (composers.childNodes.length > 0) {
                completeTable.setAttribute("bordercolor", "black");
                completeTable.setAttribute("border", "1");
    
                for (loop = 0; loop < composers.childNodes.length; loop++) {
                    var composer = composers.childNodes[loop];
                    var firstName = composer.getElementsByTagName("firstName")[0];
                    var lastName = composer.getElementsByTagName("lastName")[0];
                    var composerId = composer.getElementsByTagName("id")[0];
                    appendComposer(firstName.childNodes[0].nodeValue,
                        lastName.childNodes[0].nodeValue,
                        composerId.childNodes[0].nodeValue);
                }
            }
        }
    }

A função parseMessages() recebe como parâmetro uma representação de objeto do documento XML retornado pelo servlet AutoComplete. A função atravessa programaticamente o documento XML, extraindo firstName, lastName e id de cada entrada e, em seguida, passa esses dados para appendComposer(). Isso resulta em uma atualização dinâmica do conteúdo do elemento complete-table. Por exemplo, uma entrada que é gerada e inserida em complete-table deve ter a seguinte aparência:

<tr>
    <td class="popupCell">
        <a class="popupItem" href="autocomplete?action=lookup&id=12">Antonin Dvorak</a>
    </td>
</tr>

A atualização dinâmica do elemento complete-table representa a etapa final do fluxo do processo de comunicação que acontece durante a comunicação por meio do Ajax. Essa atualização mapeia para os dados HTML e CSS que estão sendo passados para a apresentação no fluxograma acima.

Anexando uma folha de estilo

Nesse estágio, você concluiu todo o código necessário para a funcionalidade do aplicativo. Para ver os resultados dos seus esforços, tente executar o aplicativo agora.

  1. Na janela Projetos, clique com o botão direito do mouse no nó do projeto e escolha Executar. O projeto é recompilado e implantado no servidor de destino. Seu navegador se abre e você pode ver a página de índice.
    Aplicativo exibido no navegador sem folha de estilo

Para anexar uma folha de estilo ao seu aplicativo, simplesmente crie um arquivo .css e vincule-o a partir da(s) página(s) da sua apresentação. Quando você trabalha em arquivos .css, o IDE fornece o suporte autocompletar de código, assim como vários outros recursos que podem ajudar na produção de regras de folha de estilo. Entre eles se incluem:

  • Editor de regras de estilo: Uma caixa de diálogo que permite que você crie regras com base em classes, IDs e elementos HTML, e defina sua posição na hierarquia do documento.
  • Janela Visualização de CSS: Uma janela de visualização que, quando você coloca o cursor em uma regra, exibe o texto de amostra renderizado de acordo com o bloco de declaração dessa regra.
  • Construtor de estilo CSS: uma interface projetada para permitir que você crie regras utilizando uma seleção de controles e assistentes.

Para anexar uma folha de estilo ao seu aplicativo, faça o seguinte.

  1. Na janela Projetos, clique com o botão direito do mouse no nó do projeto e escolha Novo > Folha de estilo em cascata (se Folha de estilo em cascata não estiver listado, escolha Outro. Em seguida, escolha Folha de estilo em cascata na categoria Web no assistente para Novo arquivo.)
  2. No campo de texto Nome do arquivo CSS, digite stylesheet.
  3. Clique em Terminar. O novo arquivo é adicionado à janela Projetos, e aberto no editor do IDE.
  4. Em stylesheet.css, digite as regras a seguir. É possível utilizar o suporte autocompletar de código do IDE, pressionando Ctrl-Espaço nos pontos em que desejar acionar sugestões.
    body {
       font-family: Verdana, Arial, sans-serif;
       font-size: smaller;
       padding: 50px;
       color: #555;
       width: 650px;
    }
    
    h1 {
       letter-spacing: 6px;
       font-size: 1.6em;
       color: #be7429;
       font-weight: bold;
    }
    
    h2 {
       text-align: left;
       letter-spacing: 6px;
       font-size: 1.4em;
       color: #be7429;
       font-weight: normal;
       width: 450px;
    }
    
    table {
       width: 550px;
       padding: 10px;
       background-color: #c5e7e0;
    }
    
    td {
       padding: 10px;
    }
    
    a {
      color: #be7429;
      text-decoration: none;
    }
    
    a:hover {
      text-decoration: underline;
    }
    
    .popupBox {
      position: absolute;
      top: 170px;
      left: 140px;
    }
    
    .popupCell {
       background-color: #fffafa;
    }
    
    .popupCell:hover {
      background-color: #f5ebe9;
    }
    
    .popupItem {
      color: #333;
      text-decoration: none;
      font-size: 1.2em;
    }

    Verifique se o seu código CSS é válido, clicando com o botão direito do mouse no Editor CSS e escolhendo Verificar CSS. Quaisquer erros encontrados são exibidos na janela Saída (Janelas > Saída).

  5. Abra a janela Visualização de CSS, escolhendo Janela > Outro > Visualização de Css.
  6. Coloque o seu cursor em uma regra que faça ajustes no texto e na cor (por exemplo, h1). A janela Visualização de CSS gera uma exibição de amostra que mostra como o texto será renderizado em um navegador.
    Janela Visualização de CSS exibindo o texto de amostra da regra h1
  7. Alterne para a página index.jsp no editor de código-fonte, e adicione uma referência à folha de estilo entre as marcas <head>.
    <link rel="stylesheet" type="text/css" href="stylesheet.css">
  8. Adicione a classe popupBox que está definida na folha de estilo para o elemento complete-table (alterações em negrito).
    <tr>
        <td id="auto-row" colspan="2">
            <table id="complete-table" class="popupBox" />
        <td/>
    </tr>
    Como indicado em stylesheet.css, esta regra posiciona o elemento complete-table para que seja exibido um pouco à direita de seu elemento principal.

Executando o projeto

Quando você executar o aplicativo novamente, ele será exibido no navegador utilizando a folha de estilo que acabou de ser criada. Toda vez que você digita um caractere, uma solicitação assíncrona é enviada para o servidor e retornada com dados XML que foram preparados por AutoCompleteServlet. Conforme você indica mais caracteres, o número de nomes de compositor diminui para refletir a nova lista de correspondências.

Utilizando o monitor do servidor HTTP

É possível utilizar o monitor do servidor HTTP do IDE para verificar a comunicação HTTP que acontece quando as requisições e as respostas são passadas entre o cliente e o servidor. O monitor do servidor HTTP exibe informações como cabeçalhos do cliente e do servidor, propriedades da sessão, detalhes do cookie, assim como parâmetros de solicitação.

Antes de começar a utilizar o monitor HTTP, você deve primeiro ativá-lo no servidor que está utilizando.

  1. Abra a janela Servidores, escolhendo Ferramentas > Servidores no menu principal.
  2. No painel esquerdo, selecione o servidor que que está sendo utilizado com o projeto. Em seguida, no painel direito, selecione a opção Ativar monitor HTTP.

    Nota: essa opção é exibida abaixo da aba Comum do servidor GlassFish. Para Tomcat, ela reside na aba Conexão.

  3. Clique em Fechar.

Se o servidor já estiver em execução, você precisará reiniciá-lo para permitir que as alterações tenham efeito. É possível reiniciar o servidor, abrindo a janela Serviços (Janela > Serviços) e, em seguida, clicando com o botão direito do mouse no servidor abaixo do nó Servidores e escolhendo Reiniciar.

Agora, quando você executar o aplicativo novamente, o monitor HTTP será aberto na região inferior do IDE. É possível selecionar um registro no painel esquerdo e, em seguida, clicar nas abas na janela principal para visualizar as informações sobre cada requisição que é feita.

Monitor do servidor HTTP exibido no IDE

É possível verificar os dados XML que são enviados a partir do servidor, como resultado da requisição assíncrona feita quando um usuário indica um caractere no campo autocompletar.

  1. Na visualização em árvore do lado esquerdo do monitor HTTP, clique com o botão direito do mouse no registro de uma solicitação e escolha Reproduzir.

A resposta é gerada em seu navegador. Nesse caso, como a resposta consiste em dados XML, o navegador exibe os dados em seu visualizador XML nativo.

Monitor do servidor HTTP exibido no IDE

Conclusão

Isso conclui a Introdução ao Ajax. Esperamos que agora você saiba que o Ajax é simplesmente trocar informações por meio de HTTP em segundo plano, e atualizar essa página dinamicamente com base nos resultados.

Você pode notar que o aplicativo construído possui vários problemas, por exemplo, nada acontece quando o nome de um compositor é selecionado na caixa de autocompletar! Você é bem-vindo a baixar o projeto de solução para ver como isso pode ser implementado utilizando tecnologia JSP. Além disso, talvez queira investigar a validação do lado do servidor que impede que um usuário solicite um nome que não existe no armazenamento de dados. É possível aprender mais sobre essas técnicas e tecnologias, seguindo outros tutoriais na Trilha de aprendizado do Java Web e do Java EE.


Consulte também

Para obter mais informações sobre a tecnologia Ajax e Java em netbeans.org, consulte os seguintes recursos: