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).
-
Modifique o método
finaliza
da classeTarefasController
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); }
-
Teste a aplicação, tentando finalizar uma tarefa. Deixa o
F12
habilitado e fique ligado na aba Network. -
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 bibliotecaJackson
e suas dependências. Baixe os seguintes jars, copiando-os para/WEB-INF/lib
: -
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.
-
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>
- Vamos colocar um id para o
-
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. -
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étodotoLocaleDateString
.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!
Amigo, muito obrigado não estava conseguindo retornar um objeto para o ajax, com a sua dica do jackson funcionou!