// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= Introdução ao Ajax para Aplicações Java Web
:jbake-type: tutorial
:jbake-tags: tutorials 
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: Introdução ao Ajax para Aplicações Java Web - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, Introdução ao Ajax para Aplicações Java Web

Este documento oferece uma introdução ao Ajax e demonstra algumas das funncionalidades no NetBeans IDE que permitem que você programe 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 uma aplicação simples que utiliza a função autocompletar em um campo de texto. O conteúdo aqui foi adaptado do artigo e da aplicação de amostra de Greg Murray link:http://weblogs.java.net/blog/gmurray71/archive/2005/12/using_ajax_with_1.html[+Using Ajax with Java Technology+].

Ajax significa Asynchronous JavaScript and XML. Na essência, o Ajax é uma forma eficiente de uma aplicação web tratar as interações do usuário com uma página 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 do usuário. Isso permite um comportamento detalhado (semelhante ao de uma aplicação de área de trabalho ou aplicação web com base em plug-in) na utilização de um browser. As interações do Ajax são tratadas assincronamente em segundo plano. Enquanto 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 form (enquanto o usuário as está digitando) utilizando lógica do lado do servidor, recuperar dados detalhados do servidor, atualizar dinamicamente os dados em uma página e submeter forms parciais a partir da página.


image::images/netbeans-stamp-80-74-73.png[title="O conteúdo desta página se aplica ao NetBeans IDE 7.2, 7.3, 7.4 e 8.0"]


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

|===
|Software ou Recurso |Versão Necessária 

|link:https://netbeans.org/downloads/index.html[+NetBeans IDE, pacote Java EE+] |7.3, 7.4, 8.0 

|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+JDK (Java Development Kit)+] |7 ou 8 

|link:https://glassfish.java.net/[+GlassFish Server+] 
_ou_ 
link:http://tomcat.apache.org/index.html[+servidor Tomcat+] |Open Source Edition 3.1.x ou 4.x 
_ _ 
versão 7.x ou 8.x 
|===

*Observações:*

* A instalação do Java EE do IDE permite instalar o servidor GlassFish e o contêiner de servlets do Apache Tomcat.
* 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, link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaScript%252FMyAjaxApp.zip[+faça download da aplicação de amostra+].



[[overview]]
== Visão Geral da Aplicação

Imagine uma página 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 digitar o nome do compositor. Na aplicação de exemplo, o campo de entrada possui uma funcionlidade autocompletar. Em outras palavras, o usuário pode digitar parte do nome do compositor e a aplicação web tentará completar o nome, listando todos os compositores cujo nome ou sobrenome começa com os caracteres digitados. A funcionalidade autocompletar 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.

image::images/sample-app.png[title="Aplicação de amostra exibida no browser"]

Implementar a funcionalidade autocompletar em um campo de pesquisa é algo que pode ser feito por meio do Ajax. O Ajax funciona com o emprego de um objeto `XMLHttpRequest` para passar solicitações e respostas assincronamente entre o cliente e o servidor. O diagrama a seguir ilustra o fluxo do processo da comunicação que acontece entre o cliente e o servidor.

image::images/ajax-process-flow.png[title="Diagrama de fluxo de processo do Ajax"]


O fluxo de 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 para uma função que inicializa um objeto `XMLHttpRequest`.
2. O objeto `XMLHttpRequest` é configurado com um parâmetro de solicitação que inclui o ID do componente que acionou o evento e qualquer valor que o usuário digitou. O objeto `XMLHttpRequest` faz uma solicitação assíncrona ao servidor web.
3. No servidor web, um objeto como um servlet ou um listener trata a solicitação. Os dados são recuperados do armazenamento de dados, e é preparada uma resposta contendo os dados do form em um documento XML.
4. Finalmente, o objeto `XMLHttpRequest` recebe os dados XML utilizando uma função de chamada de retorno, processa-os 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 da funcionalidade 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árias para gerar o objeto `XMLHttpRequest`. Em seguida, você configura o lado do servidor, criando o armazenamento de dados e a lógica de negócio utilizando tecnologia baseada em Java. Finalmente, você retorna ao lado do cliente e implementa `callback()`, e outra funcionalidade JavaScript para atualizar o HTML DOM.



[[client1]]
== Programando o Lado do Cliente: Parte 1

Comece criando um novo projeto de aplicação Web no IDE. O IDE contém modelos incorporados para vários tipos de projeto.

1. Escolha Arquivo > Novo Projeto. Em Categorias, selecione Java Web. Em Projetos, selecione Aplicação Web e clique em Próximo.
2. No painel Nome e Localização, digite `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 default e clique em Próximo. 

image::images/java-name-location.png[title="Especifique o nome e a localização do seu projeto de aplicação"]


. No painel Servidor e Definições, selecione o servidor em que deseja implantar a aplicação. Somente os servidores registrados no IDE estão listados. 

image::images/java-server-settings.png[title="Especifique o servidor no qual sua aplicação será implantada"]


. Aceite as outras definições default e clique em Finalizar. O projeto será 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 link:http://ant.apache.org/[+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 default será gerada e aberta no Editor de Código-fonte do IDE. Dependendo do servidor de destino, a página de entrada será `index.jsp` ou `index.html`.

image::images/java-proj-win.png[title="A janela Projetos exibe o projeto MyAjaxApp"]

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

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

A aplicação é compilada, o servidor de aplicações é iniciado e a aplicação é implantada nele e executada. O IDE abre seu browser default e exibe a página de entrada default.


=== Usando o Editor HTML

image::images/palette.png[title="Paleta que exibe elementos HTML"] 

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

Uma das vantagens do uso de um IDE é que o editor em que você trabalha normalmente fornece a funcionalidade autocompletar código, o que, se você aprender a aplicar quando codifica, 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 código (Ctrl-Espaço) produzirá sugestões para tags e atributos HTML. Como será mostrado mais tarde, o mesmo se aplica a outras tecnologias, como CSS e JavaScript.

Uma segunda funcionalidade que pode ser utilizada é a Paleta do IDE. A Paleta fornece modelos fáceis de utilizar para elementos que são comumente aplicados 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.

Você pode exibir ícones grandes (como exibido aqui) clicando com o botão direito do mouse na Paleta e selecionando Mostrar Ícones Grandes.


1. Substitua o conteúdo das tags `<title>` e `<h1>` para que leia: `Auto-Completion using AJAX`. A página de índice não requer nenhuma codificação de script do lado do servidor, portanto, você pode deletar com segurança quaisquer remanescentes criados por default. A página de índice agora deve ter a seguinte aparência.

[source,xml]
----

<!DOCTYPE html>

<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>

----


. Adicione algum texto explicativo para descrever a finalidade do campo de texto. Você pode copiar e colar no texto a seguir, no ponto logo abaixo das tags `<h1>`:

[source,html]
----

<p>This example shows how you can do real time auto-completion using Asynchronous
    JavaScript and XML (Ajax) interactions.</p>

<p>In the form below enter a name. Possible names that will be completed are displayed
    below the form. For example, try typing in "Bach," "Mozart," or "Stravinsky,"
    then click on one of the selections to see composer details.</p>

----


. Adicione um form HTML à página. Faça isso utilizando os elementos listados na Paleta do IDE. Se a Paleta não estiver aberta, selecione Janela > Paleta no menu principal. Em seguida, em Forms HTML, clique e arraste um elemento Form para a página, um ponto abaixo das tags `<p>` que você acabou de adicionar. A caixa de diálogo Inserir Form será aberta. Especifique o seguinte: 

* Ação: autocompletar código
* Método: GET
* Nome: autofillform

image::images/insert-form.png[title="Caixa de diálogo Inserir form"]

Clique em OK. As tags HTML `<form>` serão inseridas na página que contém os atributos especificados. (GET é aplicado por default e, portanto, não é declarado explicitamente.)



. Adicione uma tabela HTML à página. Na categoria HTML na Paleta, clique em um elemento Tabela e arraste-o para um ponto entre as tags `<form>`. A caixa de diálogo Inserir Tabela será aberta. Especifique o seguinte: 

* Linhas: 2
* Colunas: 2
* Tamanho da Borda: 0
* Preenchimento de Células: 5

image::images/insert-table.png[title="Caixa de diálogo Inserir tabela"]


. Clique com o botão direito do mouse no Editor de Código-Fonte e selecione Formatar. Isso limpa o código. Seu form agora deve ser semelhante ao abaixo:

[source,xml]
----

<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>

----


. Na primeira linha da tabela, digite o seguinte texto na primeira coluna (alterações em *negrito*):

[source,xml]
----

<td>*<strong>Composer Name:</strong>*</td>
----


. 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*):

[source,xml]
----

<td>
    *<input type="text"
        size="40"
        id="complete-field"
        onkeyup="doCompletion();">*
</td>

----
Enquanto digita, tente utilizar o suporte à funcionalidade autocompletar código incorporado do IDE. Por exemplo, digite `<i` e, em seguida, pressione Ctrl-Espaço. Uma lista de opções sugeridas será exibida abaixo do seu cursor e uma descrição do elemento selecionado aparecerá 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. 

image::images/code-completion.png[title="Pressione Ctrl-Espaço no editor para chamar o suporte a autocompletar código e à documentação"]

O atributo `onkeyup` que você digitou acima aponta para uma função JavaScript chamada `doCompletion()`. Essa função é chamada toda vez que uma tecla é pressionada no campo de texto do form, e mapeia para a chamada JavaScript representada no <<flow-diagram,fluxograma>> do Ajax acima.


[[javascript]]
=== Utilizando o Editor JavaScript

O novo Editor JavaScript do IDE fornece muitos recursos de edição avançados, como autocompletar código inteligente, realce de semântica, renomeação instantânea e recursos de refatoração, assim como muitas outras funcionalidades.

A funcionalidade autocompletar código JavaScript é automaticamente fornecida quando você codifica em arquivos `.js`, assim como em tags `<script>` quando trabalha com outras tecnologias (ou seja, HTML, RHTML, JSP, PHP). O IDE por fornecer algumas dicas quando você editar o código JavaScript. É possível especificar as opções de JavaScript escolhendo Ferramentas > Opções (NetBeans > Preferências, no Mac) para abrir a janela Opções e selecionar a linguagem JavaScript na guia Dicas, categoria Editor. Você também pode adicionar seus próprios modelos de código JavaScript na guia Modelos de Código, janela Opções.

image::images/javascript-options.png[title="Opções de Dicas de JavaScript na janela Opções"]

Adicione um arquivo JavaScript à aplicação e comece a implementar `doCompletion()`.

1. Na janela Projetos, clique com o botão direito do mouse no nó Páginas Web e escolha Novo > arquivo JavaScript. (Se o arquivo JavaScript não estiver listado, selecione Outro. Em seguida, escolha o arquivo JavaScript na categoria Web no assistente Novo arquivo.)
2. Nomeie o arquivo como `javascript` e clique em Finalizar. O novo arquivo JavaScript aparecerá na janela Projetos, na pasta Páginas da Web.
3. Digite o código abaixo em `javascript.js`.

[source,java]
----

var req;
var isIE;

function init() {
    completeField = document.getElementById("complete-field");
}

function doCompletion() {
        var url = "autocomplete?action=complete&amp;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 browser para o Firefox 3 e para o Internet Explorer versões 6 e 7). Se desejar incorporar um código mais robusto para problemas de compatibilidade, considere usar este link:http://www.quirksmode.org/js/detect.html[+script de detecção de browser+] disponível em link:http://www.quirksmode.org[+http://www.quirksmode.org+].



. Volte para a página do índice e adicione uma referência ao arquivo JavaScript entre as tags `<head>`.

[source,xml]
----

<script type="text/javascript" src="javascript.js"></script>
----

Você pode alternar rapidamente entre as páginas abertas no Editor de Código-fonte, pressionando Ctrl-Tab.



. Insira uma chamada a `init()` na tag de abertura `<body>`.

[source,java]
----

<body *onload="init()"*>
----
Isso garante que `init()` seja chamada toda vez que a página for carregada.

A atribuição de `doCompletion()` é:

* criar um URL que contenha dados que possam ser utilizados pelo lado do servidor,
* inicializar um objeto `XMLHttpRequest`, e
* solicitar que o objeto `XMLHttpRequest` envie uma solicitação assíncrona para o servidor.

O objeto `XMLHttpRequest` é o núcleo do Ajax e se tornou o padrão de fato para permitir que dados XML sejam passados assincronamente por HTTP. A interação _Assíncrona_ implica que o browser pode continuar a processar eventos na página depois que a requisição tiver sido enviada. Os dados são passados em segundo plano, e podem ser carregados automaticamente na página sem exigir 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 browser e, se for o caso, cria um objeto `XMLHttpRequest`. Caso contrário, ela executa uma verificação em `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:

* O URL `autocomplete`, e o texto digitado no `complete-field` pelo usuário:

[source,java]
----

var url = "autocomplete?action=complete&amp;id=" + escape(completeField.value);
----
* `GET`, significando que as interações HTTP usam o método `GET`, e
* `true`, significando que a interação é assíncrona:

[source,java]
----

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 de chamada de retorno dessa interação é definida com a instrução:


[source,java]
----

req.onreadystatechange = callback;
----

e uma função `callback()` <<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 <<flow-diagram,fluxograma>> acima.



[[serverside]]
== 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 Web services, tais como SOAP, REST, SaaS e frameworks orientados a MVC, como JSF, Spring e Struts. Diversos plug-ins do NetBeans estão disponíveis no link:http://plugins.netbeans.org/[+Portal de Plug-In do NetBeans+] para frameworks orientados para Ajax, como link:https://developers.google.com/web-toolkit/[+GWT+] e link:http://struts.apache.org/2.x/[+Struts2+].

A lógica de negócios da aplicação processa as solicitaçõ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 necessários pelo servlet para acessar os dados.

* <<data,Criando o Armazenamento de Dados>>
* <<servlet,Criando um Servlet>>


=== Criando o Armazenamento de Dados

Para essa aplicação simples, você cria uma classe nomeada `ComposerData` que mantém os dados do composer utilizando um link:http://download.oracle.com/javase/1.5.0/docs/api/java/util/HashMap.html[+`HashMap`+]. Um `HashMap` permite armazenar pares de itens vinculados em pares chave-valor. 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 selecione Novo > Classe Java.
2. Nomeie a classe `ComposerData` e digite `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 Finalizar. A classe será criada e aberta no Editor de Código-fonte.
4. No Editor de Código-fonte, cole o seguinte código:

[source,java]
----

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"));

    }
}
----

Você observará que uma advertência será exibida na margem esquerda do editor porque a classe  ``Composer``  não pode ser encontrada. Execute as etapas a seguir para criar a classe `Composer`.

1. Clique com o botão direito do mouse no nó do projeto na janela Projetos e selecione Novo > Classe Java.
2. Nomeie a classe `Composer` e selecione `com.ajax` na lista drop-down no campo Pacote. Clique em Finalizar.

Quando você clica em Finalizar, o IDE cria a classe e abre o arquivo no Editor de Código-fonte.



. No Editor de Código-fonte, cole o seguinte código:

[source,java]
----

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.lastName = lastName;
        this.category = category;
    }

    public String getCategory() {
        return category;
    }

    public String getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }
}
----

Depois que você cria a classe  ``Composer`` , se você observar a classe  ``ComposerData``  no editor, poderá ver que as anotações de advertência não existem mais. Se ainda você vir as anotações de advertência no  ``ComposerData``  você pode tentar resolver o erro adicionando as instruções de importação ausentes.


[[servlet]]
=== Criando um Servlet

Crie um servlet para tratar o URL `autocomplete` que é recebido 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 para abrir o assistente para Novo Servlet. (Escolha Outros e selecione Servlet na categoria da Web se Servlet não for exibido por default no menu pop-up).
2. Nomeie o servlet `AutoCompleteServlet` e selecione `com.ajax` na lista drop-down no campo Pacote. Clique em Próximo.

image::images/newservlet-name-location.png[]


. No painel Configurar a Implantação do Servlet, altere o padrão do URL para *`/autocomplete`* para que ele corresponda ao URL que foi definido anteriormente no objeto `XMLHttpRequest`. 

image::images/newservlet-configure-deployment.png[]

Esse painel elimina a necessidade de adicionar manualmente esses detalhes no descritor de implantação.



. como opção, selecione "Adicionar informações do servlet ao descritor da implantação". Isso faz com que seu projeto seja o mesmo da amostra da qual fez download. Com versões posteriores do IDE, por default o servlet é registrado por uma anotação `@WebServlet`, em vez de um descritor da implantação. O projeto ainda funcionará se você usar a anotação `@WebServlet`, em vez de um descritor de implantação.


. Clique em Finalizar. O servlet será criado e aberto no Editor de Código-fonte.

Os únicos métodos que você precisa substituir são `doGet()`, para definir como o servlet trataa solicitação `autocomplete` `GET`, e `init()`, que precisa iniciar um `ServletContext` de forma que o servlet possa acessar outras classes na aplicação, depois de ter sido posto em serviço.

Você pode substituir métodos de superclasses usando o menu pop-up Inserir Código do IDE. Implemente `init()` executando as etapas a seguir.

1. Coloque o seu cursor embaixo da declaração de classe `AutoCompleteServlet` no Editor de Código-fonte. Pressione Alt-Insert (Ctrl-I no Mac) para abrir o menu pop-up Gerar Código. 

image::images/insert-code.png[title="Menu pop-up Inserir Código exibido no Editor de Código-fonte"]


. Selecione Substituir 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 config)`. 

image::images/new-override.png[title="A caixa de diálogo Substituir lista classes herdadas"]


. Clique em OK. O método `init()` é adicionado no Editor de Código-fonte.


. Adicione uma variável para um objeto `ServletContext` e modifique `init()` (alterações em *negrito*):

[source,java]
----

*private ServletContext context;*

@Override
public void init(ServletConfig *config*) throws ServletException {
    *this.context = config.getServletContext();*
}
----


. Adicione uma instrução de importação para `ServletContext`. Você pode fazer isso clicando no ícone da lâmpada exibido na margem esquerda do Editor de Código-fonte 

image::images/import-hint.png[title="Dicas de importação são exibidas na margem esquerda do Editor de Código-fonte"]

O método `doGet()` precisa fazer parsing do URL da solicitaçã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 exibi-la, pode ser necessário expandir métodos HttpServlet clicando no ícone de expansão (image:images/expand-icon.png[]) na margem esquerda.

1. Adicione as declarações de variável a seguir embaixo da declaração da classe `AutocompleteServlet`.

[source,java]
----

private ComposerData compData = new ComposerData();
private HashMap composers = compData.getComposers();
----
Isso cria um `HashMap` de todos os dados do composer, que é, em seguida, utilizado por `doGet()`.


. Role para baixo para `doGet()` e implemente o método da seguinte forma:

[source,xml]
----

@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);
        }
    }
    if (action.equals("lookup")) {

        // put the target composer in the request scope to display 
        if ((targetId != null) &amp;&amp; composers.containsKey(targetId.trim())) {
            request.setAttribute("composer", composers.get(targetId));
            context.getRequestDispatcher("/composer.jsp").forward(request, response);
        }
    }
}
----

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 você também pode trocar texto simples ou até mesmo snippets de JavaScript, que podem ser avaliados ou executados pela função chamada de retorno no cliente. Observe também que alguns browsers podem armazenar no 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 composers com nome ou sobrenome começando com os caracteres digitados pelo usuário. Este documento mapeia para os dados XML ilustrados no <<flow-diagram,fluxograma>> acima. Aqui está um exemplo de um documento XML que é retornado para o objeto `XMLHttpRequest`:


[source,xml]
----

<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>

----

Você pode utilizar o <<httpMonitor,Monitor HTTP>> do IDE para exibir os dados XML retornados ao concluir a aplicação.


[[client2]]
== Programando o Lado do Cliente: Parte 2

Você deve definir a função de chamada de retorno para tratar a resposta do servidor, e adicionar qualquer funcionalidade necessária para refletir alterações na página exibida pelo usuário. Isso requer a modificação do HTML DOM. Você precisa criar páginas JSP para exibir os resultados de uma solicitação bem-sucedida ou as mensagens de erro de uma solicitação com falha. Em seguida, é possível criar uma folha de estilo simples para a apresentação.

* <<callback,Adicionando a Funcionalidade de Retorno de Chamada>>
* <<htmldom,Atualizando o HTML DOM>>
* <<displayresults,Exibindo os Resultados>>
* <<stylesheet,Anexando uma Folha de Estilo>>


=== Adicionando a Funcionalidade de Retorno de Chamada

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

1. Abra `javascript.js` no Editor de Código-fonte e digite o código abaixo.

[source,java]
----

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. São elas:

|===
|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 <<htmldom,Atualizando o HTML DOM>>.


=== Atualizando o HTML DOM

A função `parseMessages()` trata os dados XML de entrada. Fazendo isso, ela conta com várias funções auxiliares, como `appendComposer()`, `getElementY()` e `clearTable()`. Você também deve introduzir novos elementos na página de índice, como uma segunda tabela HTML que serve como a caixa autocompletar, e os IDs dos elementos, para que eles possam ser referenciados em `javascript.js`. Finalmente, crie novas variáveis que correspondam aos IDs para os elementos na página do índice, inicialize-as na função `init()` implementada anteriormente e adicione alguma funcionalidade que seja necessária sempre que a página do índice for carregada.

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

1. Abra a página do índice no Editor de Código-fonte e digite o código abaixo para a segunda linha da tabela HTML que você criou anteriormente.

[source,xml]
----

<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 do composer.


. Abra `javascript.js` no Editor de Código-fonte e as três variáveis seguintes no início do arquivo.

[source,java]
----

var completeField;
var completeTable;
var autoRow;
----


. Adicione as seguintes linhas (em *negrito*) na função `init()`.

[source,java]
----

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 que estão dentro da página de índice acessíveis para outras funções que modificarão o DOM da página de índice.


. Adicione `appendComposer()` a `javascript.js`.

[source,java]
----

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&amp;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 criador utilizando os dados passados para a função por meio de seus três parâmetros e insere a linha no elemento `complete-table` da página de índice.


. Adicione `getElementY()` a `javascript.js`.

[source,java]
----

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 real do elemento, quando ele é exibido, frequentemente depende do tipo e da versão do browser. Note que o elemento `complete-table`, quando é exibido contendo nomes de criador, é deslocado para o lado direito inferior da tabela em que ele está. O posicionamento correto da altura é determinado por `getElementY()`. 

*Observação: *Consulte link:http://www.quirksmode.org/js/findpos.html[+esta explicação+] de `offset` em link:http://www.quirksmode.org/[+http://www.quirksmode.org/+].



. Adicione `clearTable()` a `javascript.js`.

[source,java]
----

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 criador existentes que tenham sido criadas.


. Modifique a função `callback()` para que chame `clearTable()` cada vez que novos dados forem recebidos do servidor. Quaisquer entradas do criador que já existam na caixa autocompletar serão, portanto, removidas, antes que esta seja preenchida com novas entradas.

[source,java]
----

function callback() {

    *clearTable();*

    if (req.readyState == 4) {
        if (req.status == 200) {
            parseMessages(req.responseXML);
        }
    }
}
----


. Adicione `parseMessages()` a `javascript.js`.

[source,java]
----

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 percorre programaticamente o documento XML, extraindo `firstName`, `lastName` e `id` de cada entrada e, em seguida, ela 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:


[source,xml]
----

<tr>
    <td class="popupCell">
        <a class="popupItem" href="autocomplete?action=lookup&amp;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 sendo enviados para a apresentação no <<flow-diagram,fluxograma>> acima.


[[displayresults]]
=== Exibindo os Resultados

Para exibir os resultados, você precisa de um arquivo JSP chamado `composers.jsp`. Esta página é chamada a partir do `AutoCompleteServlet` durante uma ação de busca. Você também precisa de um arquivo `error.jsp`, que é chamado a partir do `AutoCompleteServlet` se o composer não puder ser encontrado.

*Para exibir resultados e erros:*

1. Na janela Projetos, clique com o botão direito do mouse na pasta Páginas Web e selecione Novo > JSP. O assistente Novo JSP será aberto.
2. No campo Nome do Arquivo, digite `composer`. No campo Arquivo Criado, você verá um caminho que termina em `/web/composer.jsp`.
3. Clique em Finalizar. O arquivo `composer.jsp` será aberto no editor. Aparecerá um nó para o arquivo na janela Projetos na pasta Páginas Web.
4. Substitua o código do placeholder no `composer.jsp` pelo seguinte código:

[source,html]
----

<html>
  <head>
    <title>Composer Information</title>

    <link rel="stylesheet" type="text/css" href="stylesheet.css">
  </head>
  <body>

    <table>
      <tr>
        <th colspan="2">Composer Information</th>
      </tr>
      <tr>
        <td>First Name: </td>
        <td>${requestScope.composer.firstName}</td>
      </tr>
      <tr>
        <td>Last Name: </td>
        <td>${requestScope.composer.lastName}</td>
      </tr>
      <tr>
        <td>ID: </td>
        <td>${requestScope.composer.id}</td>
      </tr>
      <tr>
        <td>Category: </td>
        <td>${requestScope.composer.category}</td>
      </tr>      
    </table>

    <p>Go back to <a href="index.html" class="link">application home</a>.</p>
  </body>
</html>
----

*Observação.* Você precisará alterar o link para voltar à página de índice, se sua página de índice for  ``index.jsp`` .



. Crie outro arquivo JSP na pasta Páginas Web do projeto. Nomeie o arquivo de `error.jsp`.


. Substitua o código do placeholder no `error.jsp` pelo seguinte código:

[source,html]
----

<!DOCTYPE html>

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="stylesheet.css">      
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Seach Error</title>
    </head>
    <body>
        <h2>Seach Error</h2>
        
        <p>An error occurred while performing the search. Please try again.</p>
        
        <p>Go back to <a href="index.html" class="link">application home</a>.</p>
    </body>
</html>
----

*Observação.* Você precisará alterar o link para voltar à página de índice, se sua página de índice for  ``index.jsp`` .


[[stylesheet]]
=== Anexando uma Folha de Estilo

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

1. Na janela Projetos, clique com o botão direito do mouse no nó do projeto e selecione Executar. O projeto será recompilado e implantado no servidor de destino. Seu browser será aberto e você poderá ver a página de índice. 

image::images/no-css.png[title="Implantação com sucesso sem folha de estilo"]

Para adicionar uma folha de estilo à sua aplicação, basta criar um arquivo `.css` e vinculá-lo a partir da(s) página(s) da sua apresentação. Quando você trabalha em arquivos `.css`, o IDE oferece o suporte para autocompletar código. assim como as seguintes janelas, para ajudá-lo a gerar e editar regras de folhas de estilo:

* *Janela Estilos de CSS.* A janela Estilos de CSS permite editar as declarações de regras de elementos e seletores HTML em um arquivo CSS.
* *Caixa de diálogo Criar Regras CSS.* A caixa de diálogo Criar Regras de CSS permite criar novas regras em uma folha de estilos de CSS.
* *Caixa de diálogo Adicionar Propriedade de CSS.*A caixa de diálogo Adicionar Propriedade de CSS permite adicionar declarações a uma regra de CSS em uma folha de estilos, adicionando propriedades e valores.

Para adicionar uma folha de estilo à sua aplicação execute as etapas a seguir.

1. Na janela Projetos, clique com o botão direito do mouse no nó Páginas Web e selecione Novo > Folha de Estilo em Cascata (caso Folha de Estilo em Cascata não esteja listado, selecione Outro. Em seguida, escolha Folha de Estilo em Cascata na categoria Web no assistente Novo arquivo.)
2. No campo de texto Nome do Arquivo CSS, digite *`stylesheet`*. Clique em Finalizar.

O movo arquivo será criado e aberto no editor.



. Digite as seguintes regras em `stylesheet.css`, no editor. Você pode utilizar o suporte à funcionalidade autocompletar código do IDE pressionando Ctrl-Espaço nos pontos em que desejar acionar sugestões.

[source,java]
----

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;
}
----


. Abra a janela Estilos de CSS escolhendo Janela > Web > Estilos CSS. 

image::images/css-styles-window.png[title="Janela Estilos de CSS exibindo as propriedades de regra h1"]

Você pode usar a janela Estilos de CSS para exibir rapidamente as propriedades e editar as regras de estilo. Quando você seleciona uma regra no painel superior da janela Estilo de CSS, pode ver as propriedades da regra no painel inferior. Você pode adicionar uma Regra de CSS à folha de estilos clicando no ícone Editar Regras de CSS (image:images/newcssrule.png[title="Ícone Nova Propriedade de CSS"]) na barra de ferramentas do painel superior. Você pode modificar as regras no painel inferior, editando a folha de propriedades, e adicionar propriedades clicando no ícone Adicionar Propriedade (image:images/newcssproperty.png[title="Ícone Nova Propriedade de CSS"]) na barra de ferramentas do painel inferior.



. Alterne para a página no Editor de Código-fonte, e adicione uma referência à folha de estilo entre as tags `<head>`.

[source,java]
----

<link rel="stylesheet" type="text/css" href="stylesheet.css">
----


. Adicione a classe `popupBox` que está definida na folha de estilo ao elemento `complete-table` (alterações em *negrito*).

[source,xml]
----

<tr>
    <td id="auto-row" colspan="2">
        <table id="complete-table" *class="popupBox"* />
    </td>
</tr>
----

É possível usar o recurso autocompletar código no editor para ajudá-lo a selecionar a regra de estilo que você quer aplicar ao seletor.

image::images/css-completion.png[title="Recurso autocompletar código no editor"]

Como indicado em `stylesheet.css`, esta regra posiciona o elemento `complete-table` para que seja exibido um pouco à direita de seu elemento pai.

Quando você salva a página de índice, a aplicação é automaticamente reimplantada no servidor. Se a página ainda estiver aberta no browser, você poderá recarregá-la para ver se ela agora é renderizada de acordo com as regras da folha de estilos de CSS.



[[run]]
== Executando o Projeto

Quando você executar a aplicação novamente, ela será exibida no browser 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ê digita mais caracteres, o número de nomes de criador diminui para refletir a nova lista de correspondências.


[[httpMonitor]]
=== Utilizando o Monitor do Servidor HTTP

Você pode utilizar o monitor do Servidor HTTP do IDE para verificar a comunicação HTTP que acontece quando as solicitaçõ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, selecionando Ferramentas > Servidores no menu principal.
2. No painel esquerdo, selecione o servidor que está usando com o projeto. Em seguida, no painel direito, selecione a opção Ativar Monitor HTTP.

*Observação:* essa opção é exibida na guia Comum do GlassFish Server. Para Tomcat, ela reside na guia Conexão.



. Clique em Fechar.

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

Agora, quando você executar a aplicação novamente, o monitor HTTP será aberto na região inferior do IDE. Você pode selecionar um registro no painel esquerdo e, em seguida, clicar nas guias na janela principal para exibir as informações sobre cada solicitação que é feita.

image::images/http-monitor.png[title="O monitor do Servidor HTTP é exibido no IDE"]

Você pode verificar os dados XML que são enviados do servidor como resultado da solicitação assíncrona feita quando um usuário indica um caractere no campo autocompletar.

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

A resposta será gerada em seu browser. Nesse caso, como a resposta consiste em dados XML, o browser exibirá os dados em seu visualizador XML nativo.

image::images/xml-data.png[title="O monitor do Servidor HTTP é exibido no IDE"]


[[conclusion]]
=== Conclusão

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

Você talvez note que a aplicação que construiu tem vários problemas, como, por exemplo, nada acontece quando o nome de um criador é selecionado na caixa autocompletar! Você é bem-vindo a link:https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaScript%252FMyAjaxApp.zip[+fazer download do 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. Você pode aprender mais sobre essas técnicas e tecnologias, seguindo outros tutoriais na link:../../trails/java-ee.html[+Trilha de Aprendizado do Java Web e do Java EE+].

link:/about/contact_form.html?to=3&subject=Feedback:%20Introduction%20to%20Ajax%20(Java)[+Envie-nos Seu Feedback+]



[[seeAlso]]
== Consulte Também

Para obter mais informações sobre a tecnologia Ajax e Java em link:https://netbeans.org/[+netbeans.org+], consulte os seguintes recursos:

* link:../../docs/web/js-toolkits-jquery.html[+Usando jQuery para Melhorar a Aparência e o Uso de uma Página Web+]. Demonstra como integrar o núcleo jQuery e bibliotecas UI em um projeto NetBeans.
* link:../../docs/web/js-toolkits-dojo.html[+Conectando um Dojo Tree a uma ArrayList utilizando JSON+]. Com base em um JavaOne Hands-On Lab, esse documento mostra como implementar um widget Dojo Tree em uma página web e permitir que o servidor responda a solicitações Tree no formato JSON.
* link:http://www.oracle.com/pls/topic/lookup?ctx=nb8000&id=NBDAG2272[+Criando Arquivos JavaScript+] em _Desenvolvendo Aplicações com o NetBeans IDE_
* link:quickstart-webapps-wicket.html[+Introdução ao Wicket Web Framework+]. Uma introdução para criar componentes reutilizáveis e aplicá-los a uma aplicação Web utilizando o framework Wicket.
