Olá pessoal,
Falarei um pouco de um novo jeito de manipular dados: JSon.
Com o JSon é possivel transformar um objeto Java em um conjunto de Strings que representará seu objeto e terá a forma de acesso aos seus atributos da mesma forma que um objeto Java normal, tornando-se um intermediário poderoso entre uma linguagem e o JavaScript.
Objetivo
Criar uma função que busca um usuário no banco e coloca os dados em um formulário deixando tudo pronto para uma edição, tudo via ajax utilizando JSon como meio de transporte e o VRaptor como gerenciador.
Para começarmos precisaremos de um projeto VRaptor, você pode baixar o Blank Project que atualmente esta em sua versão 3.1 e caso tenha alguma dificuldade poderá ler o artigo Iniciando Com VRaptor 3
Mãos à obra
Começaremos criando um classe chamada Contato
:
public class Contato {
private String telefone;
private String celular;
// getters e setters
}
E outra classe Usuario
que possui um Contato
.
public class Usuario {
private Long id;
private String nome;
private String senha;
private String email;
private Contato contato;
// getters e setters
}
Criamos duas classes nas quais representarão os dados do usuário buscado no banco.
Criaremos um DAO para simular o retorno do usuário a partir do banco:
@Component
public class UsuarioDao {
public Usuario loadById(Long id) {
if (id != null) {
Usuario usuario = new Usuario();
usuario.setId(id);
usuario.setEmail("[email protected]");
usuario.setNome("Washington Botelho dos Santos");
usuario.setSenha("wbotelhos");
Contato contato = new Contato();
contato.setCelular("13012010");
contato.setTelefone("13012005");
usuario.setContato(contato);
return usuario;
}
return null;
}
}
Nosso DAO simula a recepção de um ID que a partir do mesmo buscaria um usuário no banco, mas ao invés disso, apenas criaremos um objeto Usuario
na mão e retornaremos para quem chamar o método loadById
.
Com nossa camada de persistência pronta vamos criar o controller que irá gerenciar nossas ações:
@Resource
public class UsuarioController {
private UsuarioDao usuarioDao;
private Result result;
public UsuarioController(Result result, UsuarioDao usuarioDao) {
this.result = result;
this.usuarioDao = usuarioDao;
}
@Get
@Path("/usuario")
public void novo() {
}
@Get
@Path("/usuario/editar/{usuario.id}")
public void editar(Usuario usuario) {
Usuario user = usuarioDao.loadById(usuario.getId());
result.use(json()).from(user).include("contato").serialize();
}
}
- Injetamos o
Result
e oUsuarioDao
para que possamos utilizá-los no controller; - Um método para redirecionar para a página
novo.jsp
na qual contêm nosso formulário e se encontra dentro da pasta usuario; e - Um método
editar
que recebe um ID e chama o DAO para buscar o usuário correspondente no banco.
Pra quem já esta familiarizado com o VRaptor, este controller não tem nada demais, a não ser uma recente funcionalidade na qual serializa um objeto em formato JSon:
result.use(json()).from(user).include("contato").serialize();
Nessa linha acima dizemos ao result que iremos utilizar o resultado em formato JSon e logo em seguida dizemos de onde virá os dados, neste caso do objeto Usuario
que acabamos de buscar no banco. Sei que você lembrou que este possui uma referência para um objeto Contato
, e logo percebeu que o incluímos na serialização, bastanto agora apenas chamar o método serialize
para concluir a ação.
Onde ficam estes dados?
Caso não serializássemos o nosso objeto o VRaptor iria nos redirecionar para a página /usuario/novo.jsp
, porém mudamos o content-type do nosso resultado para json()
com isso iremos para uma "página" criada pelo VRaptor com os dados serializados.
Se acessarmos a URL http://ip:porta/json-ajax-vraptor-3/usuario/editar/1 por exemplo o navegador irá pedir para fazermos download de um arquivo sem extensão de mesmo nome do ID que passamos, no caso 1. Abra este arquivo e verá os dados serializados.
Como são estes dados serializados?
Os dados são de simples leitura representados por Strings sempre dentro de chaves iniciais padrão:
{
"usuario": {
"id": 2,
"nome": "Washington Botelho dos Santos",
"senha": "wbotelhos",
"email": "[email protected]",
"contato": {
"telefone": "13012005",
"celular": "13012010"
}
}
}
- Nosso JSon começa com chaves e dentro delas o nome do nosso objeto que se chama
usuario
; - Dentro de
usuario
envolvido por chaves para indicar um conjunto de atributos pertecente a um objeto esta todos os atributos do objetousuario
; - Separamos do lado esquerdo o nome do atributo e do lado direto separado por dois pontos ':' o valor do atributo em questão;
- Repare que temos todos nossos atributos entre aspas, assim como os valores dos mesmos;
- Temos um sub-bloco dentro de
usuario
chamado decontato
, que também é um objeto, logo os atributos de contato também estarão contidos dentro de um conjunto de chaves.
Por padrão o nome do objeto é utilizado no JSon, caso queira personalizá-lo basta incluir como primeiro parâmetro do método
from
o nome que deseja:.from("nomeObjeto", user)
>
Parabéns, você agora já conhece o formato JSon e já esta preparado para capturar estes dados e manipulá-los da forma que achar melhor. O VRaptor já fez seu trabalho, agora vamos desfrutar do Ajax para concluirmos nosso objetivo e nos tornamos "Trendys"! d:B
Formulário de edição:
Vamos criar nosso formulário que será preenchido com os dados consultados:
<form>
ID: <input id="id" type="text"/>
Nome: <input id="nome" type="text"/>
Senha: <input id="senha" type="text"/>
E-mail: <input id="email" type="text"/>
Telefone: <input id="telefone" type="text"/>
Celular: <input id="celular" type="text"/>
<input type="button" value="Salvar"/>
</form>
Um formulário normal, sem muito segredo. Todos os campos devem ter um ID para servir de âncora e podermos manipulá-los.
Também criaremos um formulário para que possamos digitar o ID da consulta:
<form>
Buscar ID: <input id="idBusca" type="text"/>
<input type="button" value="Consultar" onclick="consultar();"/>
</form>
Com isso nosso objetivo esta quase concluído, faltando apenas fazer uma manipulação JavaScript.
Como sabemos trabalhar com JavaScript puramente é massante, trabalhoso e mais propício a erros, então vamos ser "descolados" e utilizar uma framework, no caso o jQuery.
Ah! No dia 14 de Janeiro de 2009 foi aniversário do jQuery e nada melhor do que começarmos a utilizar sua nova versão 1.4. (;
Vamos importar o script jquery-1.4.js
:
<script type="text/javascript" src="<c:url value='/js/jquery-1.4.js'/>"></script>
Com o script importado só nos resta criar a função que chama a página com os dados JSon via Ajax e logo em seguida utilizá-los. (:
Função JavaScript Consultar:
Primeiramente vamos declará-la e já capturar o ID pelo qual o usuário quer fazer a busca.
<script type="text/javascript">
function consultar() {
var idBusca = $('#idBusca').val();
// ...
}
</script>
Precisamos agora de um método do jQuery chamado getJSON, no qual a partir de uma url nos retorna um objeto em JavaScript vindo de uma página com dados JSon via ajax, ou seja, de forma assíncrona.
$.getJSON('<c:url value="/usuario/editar/"/>' + idBusca, function (json) {
// ...
}
A passagem de parâmetro como segundo argumento é opcional e como queremos passar apenas o valor do ID para ser "injetado" na entidade que o espera no controller, este foi passado embutido no primeiro parâmetro junto a URL.
Podemos também utilizar a função que nos retorna um JSon via post, porém não existe postJSON, sendo necessário passar um parâmetro entre aspas do tipo do retorno, no caso 'json' logo após o callback.
O callback (retorno) estando contindo dentro da variável json
, podemos utilizar este conteúdo como se fosse um objeto normal, assim se temos um objeto Usuario
, basta acessar seus atributos com um ponto '.' da mesma forma que um objeto Java, ficando nosso método final o seguinte:
<script type="text/javascript">
function consultar() {
var idBusca = $('#idBusca').val();
$.getJSON('<c:url value="/usuario/editar/"/>' + idBusca, function (json) {
$('#id').val(json.usuario.id);
$('#nome').val(json.usuario.nome);
$('#email').val(json.usuario.email);
$('#senha').val(json.usuario.senha);
$('#telefone').val(json.usuario.contato.telefone);
$('#celular').val(json.usuario.contato.celular);
});
}
</script>
Pronto, agora cada campo recebe seus devidos valores de atributo.
Com isso vimos como o VRaptor nos ajuda a criar o JSon, uma ótima estrutura de dados na qual é totalmente compatível com JavaScript e consequentemente muito conveniente a implementação com Ajax.
Link do projeto:
http://github.com/wbotelhos/manipulando-dados-json-via-ajax-com-vraptor-3
[DÚVIDA]
Sei que faz muito tempo deste post mas...
e se o usuário tiver uma lista de contatos como eu faço? Estou com esse problema :(
Oi Bayma,
Dá uma lida nesse artigo: http://www.wbotelhos.com.br/2010/12/06/manipulando-listas-com-jquery-e-vraptor-3
Washington,
O exemplo apresentado está sendo utilizado em um sistema que estamos desenvolvendo na minha empresa. O sistema estava sendo testado no JBOSS 5.1 EAP. Agora a empresa comprou o WEBLOGIC 11g (10.3.5) e vamos ter que fazer o deploy da aplicação no WEBLOGIC. Ao fazer os testes iniciais no WEBLOGIC, ocorreu o seguinte:
Você tem alguma dica para resolver este problema no WEBLOGIC?
Fala Geovane,
Cara, tú já fez um debug pra ver se a entidade esta chegando certinha, é o mesmo método com o
.withoutroot()
e tal?Atualiza o VRaptor para a versão 3.4 que tem alguns fix do XStream também.
Esse é aquele tipo de erro que você se mata pra descobrir depois de tempos que é uma outra coisa totalmente fora do contexto.
Como vai fiar o script :
ja que os meus dados vem do banco?
os nomes dos meus campos ficam como?
por exemplo:
clienteFisica.clfiNome
Parabéns, seu blog é muito bom!!!
Excelente!! Parabens!
mas eu quero criar o arquivo pagina.json.jsp para json não tem muito sentido, mas por exemplo com um xml para formatar para RSS tem algum sentido dai eu criei o arquivo mas não ta funcionando :(
tens idéia do que pode ser?
Flávio,
Seu arquivo deve ter o nome do método do seu controller + .xml.jsp (usuario.xml.jsp). Lembrando que você inclui o objeto no
result
, logo na sua jsp você recupera este mesmo objeto usando${nomeDadoNoInclude}
. Detalhe que o VRaptor nesse caso não vai gerar o XML nem o JSON pra você, terá de fazer isso na unha.Legal o tutorial, eu depois estava dando uma olhada na documentação e com a necessidade de implementar um template para o json e achei essa página: http://vraptor.caelum.com.br/documentacao/view-e-ajax que fala: Accepts e o parâmetro _format
fiz tudo o que ta ali e não funcionou, tens idéia por que?
Abraços
Fala Flávio,
Não entendi qual é a dúvida. Especifique melhor o que você quer fazer e o que esta dando errado.
Se for um resultado JSON, utilize o
Results.json()
, em vez dehttp://URL?_format=json
Assim evita criar um pagina.json.jsp para manter o resultado, pois o VRaptor já te entrega isso como resposta.
Boa cara!
O tutorial ajudou bastante.
Cara ficou muito bom esse teu exemplo, eu tava apanhando em uns detalhes no vraptor 3 mais agora realmente me abriu a mente, valeu mesmo.
Ainda não percebo pq o vraptor inclui o XStream original e não a versão modificado que resolve os issues de reflecção com a Google Appengine !???
json + vraptor 311 não funciona ("out of the box") em cima de GAE !!!!!
Eu não tive esse problema já que não utilizo o GAE.
Mas você pode ajudar os desenvolvedores mandando este bug para a Lista do VRaptor:
caelum-vraptor[@]googlegroups[.]com
Caso resolva seu problema, utilize o FlexJson que é muito bom.
Obrigado pelo feedback.
Tá ... pode me chamar de mané!
Não entendi esse tal json() ... daonde veio isso?
json() é um método próprio do VRaptor, porém esta escrito de uma forma resumida, sem mencionar o pacoto no qual pertence, que no caso é uma nova feature do Java 5. O
import static
serve apenas para resumir a escrita. Vejamos:Desta forma, para acessar o
PI
que é estático devemos mencionar o pacote, porém podemos resumir simplesmente com:No nosso caso a forma sem
static
ficaria:De fato, o
static
torna o código muito mais ilegível e não é todos programadores que gostam.Washington,
Utilizando seu exemplo, estava com problemas com acentuação.
Para funcionar fiz as seguintes alterações no novo.jsp:
no web.xml:
Isso ai Rodrigo, eu apenas tinha omitido tais códigos assim como outras tags padrões.
Eu costumo utilizar:
Pois já incluo um prelude nessa tag.
Mas ambos funcionam. (:
Abraço.
Tudo o q eu procurava!
Washington,
Muito legal esse exemplo !!
Valeu.