JavaScript EE, Parte 3: Utilize API de script de Java com JSP

compilar código JavaScript que pode ser executado no servidor de Web ou no navegador de Web

Nas duas partes anteriores desta série, você viu como executar arquivos JavaScript no servidor e como acessar funções JavaScript remotas com o Ajax. Este artigo explica como utilizar código JavaScript server-side com a tecnologia Java™Server Pages (JSP) e como compilar interfaces de usuário Asynchronous JavaScript e XML (Ajax) que permanecem funcionando quando o JavaScript está desativado no navegador de Web. O código amostra consiste em uma pequena biblioteca de tags JSP que pode ser reutilizada em seus próprios aplicativos e em um formulário de Web dinâmico, gerado com uma parte de código JavaScript que pode ser executada no servidor ou navegador de Web.

Andrei Cioroianu, Senior Java Developer and Consultant, Devsphere

Andrei Cioroianu é o fundador do Devsphere, um fornecedor de desenvolvimento de Java EE e serviços de consultoria Web 2.0/Ajax. Ele utiliza tecnologias Java e Web desde 1997 e tem mais de 10 anos de experiência profissional, resolvendo problemas técnicos complexos e gerenciando todo o ciclo de vida de produtos comerciais, aplicativos personalizados e estruturas de software livre. É possível entrar em contato com Andrei através do formulário de contato em www.devsphere.com.



02/Jun/2009

A habilidade de executar o mesmo código JavaScript em ambos os servidores e clientes possui vantagens significativas: ela permite manter uma única base de códigos para clientes Ajax e não Ajax, oferecendo mais flexibilidade. Por exemplo, se você desenvolver algum código JavaScript que não deseja que outros analisem, pode executá-lo no servidor, protegendo sua propriedade intelectual e minimizando riscos de segurança. Caso mais tarde você deseje liberar o código, pode mover o código de JavaScript para o cliente, melhorando o desempenho do aplicativo.

Contextos de página e contextos de script

Java Scripting API e JavaServer Pages são duas tecnologias Java separadas que podem ser facilmente integradas. Cada um deles executa códigos em um contexto bem definido. Com a tecnologia JSP, você tem acesso a um conjunto de objetos JSP implícitos: pageContext, page, request, response, out, session, config eapplication. Na Parte 1, você já viu como exportar esses objetos para um arquivo JavaScript, executado por um servlet. Neste artigo, você vai aprender como fazer o mesmo no caso de scripts que são executados por uma página JSP.

O mecanismo JavaScript utiliza um tipo diferente de contexto para manter variáveis e funções de script definidas no código de aplicativo. Se você executar um script que defina variáveis ou contém funções, scripts futuros executados no mesmo contexto podem usar as variáveis e funções dos scripts anteriores. Sendo assim, faz sentido utilizar um único contexto de script durante o processamento de uma solicitação HTTP, como você verá na próxima seção.

Scripts escritos na linguagem JavaScript podem acessar os campos públicos e chamar os métodos públicos de qualquer objeto Java. Adicionalmente, você pode obter e modificar o valor de uma propriedade JavaBean, utilizando a sintaxe object.property ao invés de chamar os métodos obter e definir. Devido à facilidade de utilizar objetos Java em seu código JavaScript, a única coisa que fica faltando é um conjunto de tags personalizados para trocar objetos entre o contexto de página JSP e o contexto JavaScript. Eles podem ser implementados com apenas algumas linhas de código, como demonstrado neste artigo.

Utilizando código Javascript server-side em páginas de Web

Esta seção mostra como administrar um contexto JavaScript ao longo de uma solicitação Ajax/HTTP, e como trocar variáveis entre o contexto da página JSP e o contexto JavaScript.

Disponibilizando objetos JSP em seu código JavaScript

A primeira parte desta série apresentou um servlet Java baseado no Java Scripting API, o qual foi utilizado para executar arquivos JavaScript no servidor. Esta seção descreve uma classe chamada JSUtil, a qual utiliza o mesmo Java Scripting API para executar fragmentos de código JavaScript durante a execução de uma página JSP. Em primeiro lugar, você precisa criar um objeto ScriptEngineManager e obter uma instância ScriptEngine, como mostrado na Listagem 1.

Listagem 1. O método getScriptEngine() de JSUtil
 package jsee.util;  import javax.script.*; import javax.servlet.*; 
  import javax.servlet.http.*; import javax.servlet.jsp.*; import java.io.*;  
  public class JSUtil {     private static ScriptEngine engine;          
  public static synchronized ScriptEngine getScriptEngine() {         
  if (engine == null) {             
  ScriptEngineManager manager = new ScriptEngineManager();             
  engine = manager.getEngineByName("JavaScript");         }         
  return engine;     }    
  ... }

A listagem 2 contém o método createScriptContext(), o qual inicializa uma instância ScriptContext, obtendo os objetos JSP implícito a partir de um contexto de página e definindo esses objetos como as variáveis do contexto de script. Essa operação torna os objetos implícitos acessíveis a partir do código JavaScript que será executado no contexto de script:

  • O objeto pageContext e um repositório para variáveis com escopo de página e possui métodos para a obtenção de todos os outros objetos implícitos.
  • O objeto page é a instância da classe de servlet que está processando a solicitação atual.
  • O objeto request permite que você obtenha os parâmetros e cabeçalhos da solicitação HTTP.
  • O objeto response permite que você defina cabeçalhos de resposta HTTP e fornece um gravador identificado por out no código JSP.
  • O objeto out é utilizado para a saída da página JSP.
  • O objeto session mantém um estado relacionado ao usuário entre as solicitações.
  • O objeto config representa a configuração do servlet que implementa o JSP.
  • O objeto application é utilizado para armazenar instâncias de bean compartilhadas por todos os usuários e obter parâmetros de inicialização especificados no arquivo web.xml.
Listagem 2. O método createScriptContext() de JSUtil
 public class JSUtil {     ...     
  public static ScriptContext createScriptContext(PageContext pageContext) 
  {         
  ScriptContext scriptContext = new SimpleScriptContext();         
  int scope = ScriptContext.ENGINE_SCOPE;        
  scriptContext.setAttribute("pageContext", pageContext, scope);         
  scriptContext.setAttribute("page", pageContext.getPage(), scope);         
  scriptContext.setAttribute("request", pageContext.getRequest(), scope);         
  scriptContext.setAttribute("response", pageContext.getResponse(), scope);         
  scriptContext.setAttribute("out", pageContext.getOut(), scope);         
  scriptContext.setAttribute("session", pageContext.getSession(), scope);         
  scriptContext.setAttribute("config", pageContext.getServletConfig(), scope);         
  scriptContext.setAttribute("application",                 
  pageContext.getServletContext(), scope);         
  scriptContext.setWriter(pageContext.getOut());         
  return scriptContext;     }    
  ... }

Durante o processamento de uma solicitação HTTP, é preferível utilizar apenas um contexto de script, de forma que qualquer fragmento JavaScript possa utilizar as variáveis e funções definidas pelos scripts executados anteriormente. Um jeito fácil de satisfazer essas condições é armazenar o contexto de script como um atributo do objeto request. O método getScriptContext() (vide listagem 3) utiliza jsee.ScriptContext como um nome de atributo.

Listagem 3. O método getScriptContext() de JSUtil
 public class JSUtil 
  {     ...    
  public static ScriptContext getScriptContext(PageContext pageContext)             
  throws IOException {        
  ServletRequest request = pageContext.getRequest();         
  synchronized (request) {             
  ScriptContext scriptContext                
  = (ScriptContext) request.getAttribute("jsee.ScriptContext");             
  if (scriptContext == null) {                 
  scriptContext = createScriptContext(pageContext);                 
  request.setAttribute("jsee.ScriptContext", scriptContext);            
  }             
  return scriptContext;         
  }     
  }     
  ... }

O métodorunScript() (exibido na Listagem 4) executa o fragmento JavaScript fornecido no contexto da atual solicitação HTTP, utilizando o método eval() do mecanismo de script. se houver uma exceção de script, runScript() fornece o código de origem, seguido do rastreio de pilha e envia um ServletException para parar a execução da página JSP.

Listagem 4. O método runScript() de JSUtil
  public class JSUtil 
  {     ...     
  public static void runScript(String source, PageContext pageContext)             
  throws ServletException, IOException {         
  try {             
  getScriptEngine().eval(source, getScriptContext(pageContext));         
  } catch (ScriptException x) {             
  ((HttpServletResponse) pageContext.getResponse()).setStatus(500);             
  PrintWriter out = new PrintWriter(pageContext.getOut());             
  out.println("<pre>" + source + "</pre>");             
  out.println("<pre>");            
  x.printStackTrace(out);             
  out.println("</pre>");            
  out.flush();             
  throw new ServletException(x);         
  }     
  }  
  }

Utilizando uma tag personalizada para executar fragmentos de código JavaScript

O arquivo script.tag (vide listagem 5) permite que você execute um fragmento de código JavaScript no servidor, no cliente ou em ambos, conforme o valor do atributorunat. Se runat for client ou both, o arquivo de tag fornece um elemento HTML <script> contendo o código que você posiciona entre <js:script> e </js:script> em seu website. Se o atributo runat for server ou both, o fragmento de código JavaScript é obtido como uma variável JSP chamada source, cujo valor é passado para o método runScript() da classe JSUtil.

Listagem 5. O arquivo script.tag
  <%@ attribute name="runat" required="true" 
  rtexprvalue="true" %> <%@ tag body-content="scriptless" %>
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
  <c:if test="${runat == 'client' or runat == 'both'}">     
  <script type="text/javascript">         
  <jsp:doBody/>    
  </script> </c:if>  
  <c:if test="${runat == 'server' or runat == 'both'}">     
  <jsp:doBody var="source"/>     
  <%         jsee.util.JSUtil.runScript(                 
  (String) jspContext.getAttribute("source"),                 
  (PageContext) jspContext);     
  %> </c:if>

Uma maneira fácil de entender como a tag <js:script> funciona é observar um exemplo simples. A Listagem 6 contém a página ScriptDemo.jsp, a qual define uma função chamada link(), que retorna um elemento<a>. Essa função pode ser executada no servidor de Web e no navegador de Web, pois o atributo runat é both.

Durante o processamento da página JSP server-side a chamada println(link(request.requestURL)) fornece um link para a página atual. O objeto request é acessível a partir do código JavaScript (no servidor), graças à inicialização de contexto realizada pela classe JSUtil, cujo método runScript() é invocado pelo arquivo tag. Quando o mecanismo JavaScript avalia a expressão request.requestURL, ele chama o método getRequestURL() da instância HttpServletRequest.

No lado do cliente, a document.writeln(link(location)) chamada irá fornecer um outro link para a página ScriptDemo.jsp cujo URL é obtido com a propriedade location, disponível apenas no navegador de Web.

Listagem 6. O exemplo de ScriptDemo.jsp
 <%@ taglib prefix="js" tagdir="/WEB-INF/tags/js" %> 
 <js:script runat="both">    
 function link(url) {         
 return '<a href="' + url + '">' + url + '</a>';    
 } </js:script>  <js:script runat="server">     
 println(link(request.requestURL)); </js:script>  <br>  
 <js:script runat="client">     
 document.writeln(link(location)); 
 </js:script>

A Listagem 7 mostra a saída de HTML produzida pela página ScriptDemo.jsp, a qual contém a função link(), o elemento <a> gerado no server-side e o código JavaScript que fornece o segundo link no lado do cliente.

Listagem 7. A saída gerada pelo ScriptDemo.jsp
  <script type="text/javascript">    
  function link(url) {        
  return '<a href="' + url + '">' + url + '</a>';    
  } </script>      
  <a href="http://localhost:8080/jsee/ScriptDemo.jsp"> 
  http://localhost:8080/jsee/ScriptDemo.jsp</a>  
  <br>  <script type="text/javascript">     
  document.writeln(link(location)); </script>

Obtendo e definindo variáveis

Ao utilizar código JavaScript em páginas da Web pages, você terá que trocar variáveis entre o contexto JSP e o contexto de script. O arquivo get.tag (vide Listagem 8) implementa uma tag personalizada chamada <js:get>, o qual exporta uma variável de script como variável JSP cujo nome é fornecido através do atributovar.

O nome da variável é obtido a partir do contexto JSP, uma vez que o mesmo é passado para o arquivo tag como um atributo JSP. O valor da variável de script é recuperado com o método getAttribute() do contexto de script. Então, uma variável JSP chamada varAlias é criada no escopo de página do arquivo tag com jspContext.setAttribute(). A diretiva <%@variable%> utilizada no arquivo tag instrui o contêiner JSP (por exemplo, Tomcat) a exportar a variável varAlias para a página que invoca o arquivo tag, utilizando o nome de variável especificado com o atributo var. Essa técnica permite que o arquivo tag invocado defina variáveis JSP no escopo page do JSP utilizando a tag <js:get>.

Listagem 8. O arquivo get.tag
  <%@ attribute name="var" required="true" rtexprvalue="false" %> 
  <%@ variable name-from-attribute="var" alias="varAlias" scope="AT_END"     
  variable-class="java.lang.Object" %> <%@ tag body-content="empty" %>  
  <%     String var = (String) jspContext.getAttribute("var");     
  Object value = jsee.util.JSUtil.getScriptContext(             
  (PageContext) jspContext).getAttribute(var);     
  jspContext.setAttribute("varAlias", value); %>

A tag <js:set>, implementado pelo arquivo set.tag (exibido na Listagem 9), assume dois atributos (um nome de variável e um valor), os quais são utilizados para definir uma variável JavaScript com o método setAttribute() do contexto de script. Se o atributo opcional value não for fornecido, o arquivo tag utiliza <jsp:doBody var="value"/> para executar o código localizado entre <js:set> e </js:set> na página JSP.

Listagem 9. O arquivo set.tag
  <%@ attribute name="var" required="true" rtexprvalue="false" %> 
  <%@ attribute name="value" required="false" rtexprvalue="true"    
  type="java.lang.Object"%> <%@ tag body-content="scriptless" %> 
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
  <c:if test="${empty value}">     <jsp:doBody var="value"/> 
  </c:if>  <%     String var = (String) jspContext.getAttribute("var");    
  Object value = jspContext.getAttribute("value");    
  jsee.util.JSUtil.getScriptContext((PageContext) jspContext)         
  .setAttribute(var, value, javax.script.ScriptContext.ENGINE_SCOPE); 
  %>

a Listagem 10 contém o exemplo de VarDemo.jsp que utiliza a tag <js:set> para inicializar duas variáveis de script que são modificadas em um fragmento de código JavaScript executado no servidor com ajuda de <js:script>. Assim, os novos valores das duas variáveis são obtidos com a tag <js:get> e incluídos na saída da página com a tag <c:out> de JSTL.

Listagem 10. O exemplo de VarDemo.jsp
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
 <%@ taglib prefix="js" tagdir="/WEB-INF/tags/js" %>  
 <js:set var="x" value="1"/> <js:set var="y">2</js:set>  
 <js:script runat="server">     x++;     
 y--; </js:script>  <js:get var="x"/> 
 <js:get var="y"/>  <c:out value="x = ${x}"/> 
 <br> <c:out value="y = ${y}"/>

Compilando UIs de Ajax que funcionam em qualquer navegador

Esta seção apresenta um formulário dinâmico baseado em Ajax e DHTML. Se o JavaScript estiver desativado no navegador de Web, a interface de usuário produzida pela página DynamicForm.jsp continua funcionando através da execução do código de script no server-side. Um arquivo JavaScript chamado BackendScript.jss é utilizado para processar os dados de formulário enviados.

O formulário é simples, de forma que o código pode ser facilmente entendido. O objetivo principal deste exemplo é demonstrar diversas técnicas de Web que podem ser utilizadas em aplicativos complexos da vida real.

Desenvolvendo formulários dinâmicos

A captura de tela incluída na Figura 1 exibe o formulário de amostra, o qual consiste em um número variável de campos de entrada e três botões identificados como Adicionar, Remover, e Enviar. O botão Adicionar inclui um novo campo de entrada no formulário, o botão Remover exclui o último campo e o botão Enviar envia os dados de formulário para o servidor.

Figura 1. formulário dinâmico simples
A screenshot showing three variable entry fields and the buttons Add, Remove and Send

Quando o DynamicForm.jsp é executado no servidor, os campos de entrada iniciais são gerados com uma função JavaScript chamadaoutputForm(). Como mostrado na Listagem 11, esses campos são posicionados dentro de um elemento <div>, cujo conteúdo será modificado com a função updateForm(), chamada no navegador de Web quando o usuário clica em Adicionar ou Remover. quando o usuário clica em Enviar, a entrada do usuário é enviada ao servidor com a função submitForm(), a qual utiliza XMLHttpRequest.

Se o JavaScript estiver desativado, nenhuma função é chamada quando o usuário clica em um botão. Nesse caso, o navegador de Web envia os dados ao servidor. Isso não ocorre quando o JavaScript está ativado, pois as funções updateForm() e submitForm() retornam false.

Listagem 11. O formulário de DynamicForm.jsp
  <html> <head> <title>Dynamic Form</title>    
  ... </head> <body>    
  <b>Dynamic Form</b><br>     
  <form name="dynamicForm" method="POST" 
  action="DynamicForm.jsp">         
  <div id="inputDiv">             
  <js:script runat="server">                 
  outputForm();             
  </js:script>        
  </div>         
  <input type="submit" name="add" value="Add"                
  onclick="return updateForm('add')">        
  <input type="submit" name="remove" value="Remove"                 
  onclick="return updateForm('remove')">         
  <input type="submit" name="send" value="Send"                 
  onclick="return submitForm()">     
  </form>
  </body> 
  </html>

A página DynamicForm.jsp contém diversas funções que podem ser executadas no servidor de Web ou no navegador de Web. As rotinas htmlEncode() e buildInput() (vide Listagem 12) são utilizadas para gerar um único elemento <input>.

Listagem 12. As funções htmlEncode() e buildInput() do DynamicForm.jsp
  <%@ taglib prefix="js" tagdir="/WEB-INF/tags/js" %> ... 
  <js:script runat="both">     
  function htmlEncode(value) 
  {         
  return value ? value.replace(/&/g, "&amp;").replace(/"/g, "&quot;")             
  .replace(/</g, "&lt;").replace(/>/g, "&gt;") : "";     
  }      function buildInput(name, value) {         
  var content = '<input type="text"';         
  if (name)             
  content += ' name="' + htmlEncode(name) + '"';         
  if (value)            
  content += ' value="' + htmlEncode(value) + '"';         
  content += ' size="30">';         
  return content;     
  }    
  ... </js:script>

A função buildForm() (mostrada na Listagem 13) assume dois parâmetros: uma lista de valores e um comando. O último valor é ignorado quando o comando fornecido é remove. Se o parâmetro cmd é add, um campo vazio é adicionado no final da cadeia de caractere HTML retornada.

Listagem 13. A função buildForm() do DynamicForm.jsp
  <js:script runat="both">     ...    
  function buildForm(values, cmd) { 
  
  var n = values.length;         
  if (cmd == 'remove' && n > 1)            
  n--;         var content = '';         
  for (var i = 0; i < n; i++)             
  content += buildInput("inputField", 
  String(values[i])) + '<br>';         
  if (cmd == 'add')             
  content += buildInput("inputField") + '<br>';         
  return content;     } </js:script>

Implementando o código server-side

A página DynamicForm.jsp também contém duas funções JavaScript que são executadas apenas no servidor de Web. A Listagem 14 mostra a rotina getInputValues(), a qual retorna os valores do parâmetro inputField se o método HTTP for POST.

Listagem 14. A função getInputValues() do DynamicForm.jsp
  <js:script runat="server">     
  function getInputValues() {         
  if (request.getMethod().toUpperCase().equals("POST"))            
  return request.getParameterValues("inputField");        
  else             
  return null;     
  }     
  ... </js:script>

A outra função server-side é outputForm() (vide Listagem 15). Como mencionado anteriormente, se o JavaScript estiver desativado quando o usuário clicar em um botão, o navegador de Web envia os dados de formulário para o servidor. Nesse caso, outputForm() detecta que botão foi clicado e define a variável cmd.

Se o comando for send, a página DynamicForm.jsp inclui a saída de um script chamado BackendScript.jss, executado pela classe JSServlet que estava presente na primeira parte da série. O script retorna uma lista de valores codificados com o formato JSON.

A saída do BackendScript.jss torna-se parte de um fragmento de JavaScript executado no server-side uma vez que <jsp:include page="BackendScript.jss"/> é posicionado entre <js:script runat="server"> e </js:script>.

No final, a função outputForm() gera a lista de campos de entrada HTML com buildForm() e imprime a cadeia de caractere resultante.

Listagem 15. A função outputForm() do DynamicForm.jsp
  <js:script runat="server">    
  ...     
  function outputForm() {        
  var cmd = "";         
  if (request.getParameter("add") != null)             
  cmd = "add";        
  else if (request.getParameter("remove") != null)            
  cmd = "remove";        
  else if (request.getParameter("send") != null)            
  cmd = "send";         
  var values = null;         
  if (cmd == "send") {             
  values = <jsp:include page="BackendScript.jss"/>;         
  } else {            
  values = getInputValues();             
  if (!values)                 
  values = ["", "", ""]; // default input values       
  }         
  println(buildForm(values, cmd));     
  } 
  </js:script>

A Listagem 16 mostra o BackendScript.jss, o qual obtém os valores de entrada com paramValues.inputField e classifica o array, o qual é convertido para JSON com toSource(). A variável paramValues é inicializada com os valores dos parâmetros solicitados no script init.jss executado por JSServlet, como explicado na Parte 1 da série.

Listagem 16. O arquivo BackendScript.jss
  var values = 
  paramValues.inputField; 
  if (values)     
  println(values.sort().toSource()); 
  else     
  println("[]");

Utilizando o JavaScript no lado do cliente

A página DynamicForm.jsp possui diversas rotinas projetadas para serem executadas apenas no navegador de Web. A função getInputValues() (vide Listagem 17) utiliza a expressão document.forms.dynamicForm.inputField para obter o array de objetos DOM que representam os campos de entrada. Essa expressão pode retornar um objeto DOM, caso haja apenas um campo de entrada. Assim, getInputValues() verifica se fields é um array testando a disponibilidade da propriedade length. Os valores dos campos de entrada são retornados como um array de cadeias de caractere.

Listagem 17. A função getInputValues() do DynamicForm.jsp
 <js:script runat="client"
  >     function getInputValues() 
  {        
  var values = new Array();         
  var fields = document.forms.dynamicForm.inputField;         
  if (typeof fields.length == "number")             
  for (var i = 0; i < fields.length; i++)                 
  values[i] = fields[i].value;         
  else if (fields)            
  values[0] = fields.value;         
  return values;     }    
  ... </js:script>

A função setInputValues() (mostrada na Listagem 18) define os valores dos campos de entrada do formulário. Após invocar essa função, o usuário verá os novos valores no navegador de Web.

Listagem 18. A função setInputValues() do DynamicForm.jsp
 <js:script runat="client"
  >  ...     
  function setInputValues(values) 
  {        
  var fields = document.forms.dynamicForm.inputField;         
  if (typeof fields.length == "number")        
  for (var i = 0; i < fields.length; i++)             
  fields[i].value = values[i];         
  else if (fields)             
  fields.value = values[0];     
  }     ... </js:script>

Quando o usuário clica em Adicionar ou Remover, o navegador de Web chama a função updateForm() (vide Listagem 19), a qual é utilizada com o atributo onclick desses botões. A lista de campos de entrada é gerada novamente com a função buildForm(), a qual preserva os valores atuais dos campos, e o novo conteúdo HTML é inserido na página de Web, utilizando a propriedade innerHTML do elemento inputDiv.

Listagem 19. A função updateForm() do DynamicForm.jsp
 <js:script runat="client"
  >     ...     
  function updateForm(cmd) 
  {         
  document.getElementById('inputDiv').innerHTML            
  = buildForm(getInputValues(), cmd);         
  return false;     }     
  ... </js:script>

Se o JavaScript estiver ativado, o navegador de Web invoca a função submitForm() (mostrada na Listagem 20) quando o usuário clica no botão Enviar cujo atributo onclick contém return submitForm(). Essa função JavaScript utiliza uma pequena biblioteca Ajax que estava presente na segunda parte desta série. Você pode encontrar o código de origem da livraria no arquivo xhr.js.

Na página DynamicForm.jsp, um objeto XHR é criado e armazenado na variável xhr. O XHR() construtor assume três parâmetros:

  • O método HTTP, que é POST neste exemplo
  • O URL da solicitação HTTP, que é BackendScript.jss
  • Um parâmetro booleano indicando se as solicitações devem ou não ser assíncronas. Nesse exemplo elas são síncronas, o que significa que a função espera pela resposta HTTP antes de retornar o controle.
Listagem 20. A função submitForm() do DynamicForm.jsp
 <script src="xhr.js" type="text/javascript"
  > </script> ...
  <js:script runat="client">     ...    
  var xhr = new XHR("POST", "BackendScript.jss", false);      
  function submitForm() 
  {         
  var request = xhr.newRequest();        
  if (!request)             
  return true;         
  var values = getInputValues();         
  for (var i = 0; i < values.length; i++)            
  xhr.addParam("inputField", values[i]);         
  function processResponse() {             
  if (xhr.isCompleted()) {                 
  var newValues = eval(request.responseText);                 
  setInputValues(newValues);             
  }         
  }         
  xhr.sendRequest(processResponse);         
  return false;    
  } 
  </js:script>

A função submitForm() cria uma nova instância XMLHttpRequest com xhr.newRequest(). Se esse objeto não puder ser criado (ou seja, se o navegador de Web não suportar Ajax), submitForm() retorna true de forma que a expressão onclick do botão Enviar pode retornar true, o que significa que o navegador de Web irá enviar os dados do formulário ao servidor.

Se o novo objeto XMLHttpRequest for criado com êxito, o próximo passo é obter os valores dos campos de entrada, que serão adicionados como parâmetros de solicitação com ajuda de xhr.addParam().

A função interna processResponse() é utilizada como retorno. Se a solicitação HTTP for completada e o código de status for 200, a resposta de texto é avaliada e o array obtido é passado para a função setInputValues(), a qual atualiza os valores dos campos de entrada.

A chamada xhr.sendRequest() invoca o método send() da instância XMLHttpRequest. Em seguida, submitForm() retorna false de forma que a expressão onclick do botão Enviar pode retornar false, indicando que o navegador não precisa enviar os dados do formulário ao servidor. Esse comportamento é correto, uma vez que os valores de entrada são enviados com XMLHttpRequest quando o JavaScript está ativado e o navegador não deve re-enviar os mesmos dados.

Conclusão

Neste artigo você aprendeu como executar código JavaScript server-side integrado em páginas JSP, e como trocar variáveis entre o contexto da página JSP e o contexto JavaScript. Você também aprendeu como compilar uma interface de usuário Ajax que continua funcionando quando o JavaScript está desativado no navegador de Web. Você pode utilizar as mesmas técnicas quando, além de navegadores de Web aptos a Ajax, seu aplicativo precisar suportar dispositivos de cliente não-Ajax.


Download

DescriçãoNomeTamanho
Sample application for this articlejsee_part3_src.zip26KB

Recursos

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=405375
ArticleTitle=JavaScript EE, Parte 3: Utilize API de script de Java com JSP
publish-date=06022009