Skip to content

Instantly share code, notes, and snippets.

@alexandreaquiles
Last active August 29, 2015 14:21
Show Gist options
  • Save alexandreaquiles/b228f8572e1220dddad9 to your computer and use it in GitHub Desktop.
Save alexandreaquiles/b228f8572e1220dddad9 to your computer and use it in GitHub Desktop.
Exercício extra do FJ-21: AJAX retornando JSON com Spring MVC.

No exercício 11.21, a data da finalização não era preenchida ao finalizarmos uma tarefa por AJAX.

No método finaliza do TarefasController, o retorno era void:

@RequestMapping("finalizaTarefa")
public void finaliza(Long id, HttpServletResponse response) {
	//resto do código...
}	

No exercício opcional 11.23, passamos a mostrar a data da finalização. Fizemos isso renderizando, no servidor, a página finaliza.jsp com o trecho de dentro da <tr> que acabou de ser finalizada, usando o jQuery para trocar o conteúdo HTML.

O método finaliza do TarefasController passou a retornar String:

@RequestMapping("finalizaTarefa")
public String finaliza(Long id, Model model) {
	//resto do código...
	return "tarefa/finalizada";
}

Será que não podemos retornar um objeto do tipo Tarefa com as informações atualizadas, que acabaram de ser persistidas no banco de dados? Algo como:

public Tarefa finaliza(Long id, Model model) {
	//resto do código...
}

Podemos, mas temos que usar antes do tipo de retorna a anotação @ResponseBody, sinalizando para o Spring MVC que queremos que seja retornado o objeto (e não um nome de uma página).

  1. Modifique o método finaliza da classe TarefasController para ter o seguinte código:

    @RequestMapping("finalizaTarefa")
    public @ResponseBody Tarefa finaliza(Long id, Model model) {
      JdbcTarefaDao dao = new JdbcTarefaDao();
      dao.finaliza(id);
      return dao.buscaPorId(id);
    }
  2. Teste a aplicação, tentando finalizar uma tarefa. Deixa o F12 habilitado e fique ligado na aba Network.

  3. Ih, não funcionou! Observe que o código de erro do response foi 406 Not Acceptable. Para o Spring MVC saber como retornar uma tarefa, precisamos da biblioteca Jackson e suas dependências. Baixe os seguintes jars, copiando-os para /WEB-INF/lib:

  4. Teste a aplicação novamente, finalizando uma tarefa e veja na aba Network que o response vai ser algo como:

    {"id":7,"descricao":"Estudar Spring MVC","finalizado":true,"dataFinalizacao":1432522800000}

    Isso é um JSON. É um formato de transferência de dados otimizado para a linguagem Javascript.

  5. Agora temos os dados, mas as coisa não estão funcionando direito ainda. Precisamos alterar o lista.jsp um pouquinho:

    • Vamos colocar um id para o <td> da data de finalização:
    <td id="dataFinalizacao_${tarefa.id}"><fmt:formatDate value="${tarefa.dataFinalizacao.time}" pattern="dd/MM/yyyy" /></td>
    • Vamos colocar um id para o <td> de finalizado também:
    <c:if test="${tarefa.finalizado eq false}">
      <td id="finalizado_${tarefa.id}"><a href="#" onClick="finalizaAgora(${tarefa.id})">Finaliza agora!</a></td>
    </c:if>
  6. Precisamos alterar também o código Javascript. Mude o código da função finalizaAgora para algo como:

    function finalizaAgora(id) {
      $.post("finalizaTarefa", {'id' : id}, function(resposta) {
        $("#finalizado_"+id).html("Finalizado");
        $("#dataFinalizacao_"+id).html(resposta.dataFinalizacao);
      }, "json");
    }

    No código acima, trocamos o <td> de finalizado para Finalizado e o <td> de data de finalização para a data que obtemos da resposta que veio do servidor.

    Um detalhe pequeno e importante é o último parâmetro, o texto "json". Passando isso, informamos para o jQuery que o que vem do servidor é um JSON.

  7. Mas peraí! A data ficou estranha. Algo como 1432522800000. Não era isso que queríamos.

    No Java, a data de finalização de uma tarefa é do tipo Calendar. Mas no JSON, é enviado como um número (os ms desde 01/01/1970 00:00).

    Para transformar em um texto formatado no Javascript temos que criar um Date a partir desse número e utilizar o método toLocaleDateString.

    Mude a função finalizaAgora para o seguinte:

    function finalizaAgora(id) {
    	$.post("finalizaTarefa", {'id' : id}, function(resposta) {
    		var dataFinalizacao = new Date(resposta.dataFinalizacao);
    		var dataFormatada = dataFinalizacao.toLocaleDateString("pt-BR");
    
    		$("#finalizado_"+id).html("Finalizado");
    		$("#dataFinalizacao_"+id).html(dataFormatada);
    
    	}, "json");
    }

    Agora é partir pro abraço!

@GeovanGoes
Copy link

Amigo, muito obrigado não estava conseguindo retornar um objeto para o ajax, com a sua dica do jackson funcionou!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment