Boa tarde!
Eu estou tentando fazer um crud que usa Ajax para fazer o save, então no data desse ajax eu estou passando os inputs, assim:
{"obj.email": "admin@frontend.com.br",
"obj.groups[0]": 1,
"obj.groups[1]": 2,
"obj.groups[2]": 3,
"obj.id": "1",
"obj.name": "ADMINISTRATOR",
"obj.status": "ATIVO",
"obj.username": "admin"}
Porém, eu percebi que o VRaptor estava acionando o meu converter de User:
@Convert(User.class)
public class UserConverter implements Converter<User> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private UserDAO dao;
public UserConverter(UserDAO dao) {
this.dao = dao;
}
@Override
public User convert(String value, Class<? extends User> type,
ResourceBundle bundle) {
try {
return this.dao.get(Long.parseLong(value));
} catch (NumberFormatException e) {
logger.warn("Unable to convert to long. Value: '" + value + "'\n"
+ e.getMessage());
} catch (HibernateException e) {
logger.warn("Unable to get this record. Value: '" + value + "'\n"
+ e.getMessage());
} catch (Exception e) {
logger.warn("An error occured. Value: '" + value + "'\n"
+ e.getMessage());
}
return new User();
}
}
Como ele retorna uma instância de User, ele está chegando assim no meu controller:
User: {id:null, name:'null', status:'null', email:'null', username:'null', language:'null'}
Minha dúvida é: ele não deveria acionar o converter, certo?
É algo que eu estou passando errado no data do ajax? 
ele só chama o converter se tiver um parametro do request que é o caminho para um user, por exemplo:
user=1
//ou
algumaCoisa.user=1
Então, nesse request não tem. Mas em outro request ele faz certinho. Será que ele não está chamando o converter por que ele não encontrou ninguém que populasse aquele dado? Pois no meu log, ele está chamando o converter e mandando value = “”…
17/01/13 16:24:31 WARN hamburgsud.frontend.converter.UserConverter:31
Unable to convert to long. Value: ''
For input string: ""
Eu coloquei esse código para interceptar o que estava sendo enviado ao servidor:
$(document).ajaxSend(function(event, jqXHR, ajaxOptions){
console.log(ajaxOptions);
});
Verifiquei a saída e ficou assim (eu dei uma arrumada para vizualizarmos melhor):
isAjax=true&
obj.name=ADMINISTRATOR&
obj.language=en&
obj.email=admin@frontend.com.br&
obj.username=admin&
obj.status=ATIVO&
obj.id=1&
obj.groups[0]=1&
obj.groups[1]=2&
obj.groups[2]=3
Essa primeira variável é para eu interceptar requisições ajax quando o usuário estiver deslogado e devolver um erro 403…
tenta trocar o obj.id=1 por obj=1
Mas ai ele vai carregar o User com id 1 no meu converter… A ideia é que ele não passe pelo converter dessa vez…
Essa é o update do meu CRUD, preciso pegar o que foi alterado e atualizar…
se nenhum dos parâmetros cair num user ele não deveria passar no converter…
tem certeza que não tem nenhum outro parametro perdido na requisição? dá uma olhada num firebug ou no @Path do método.
Eu dei uma olhada no Network > Header do Chrome:
Request URL:http://localhost:8080/user/save/
Request Method: POST
Status Code:200 OK
Request Headers
Accept:application/json, text/javascript, /; q=0.01
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:243
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Cookie:JSESSIONID=5771819C524F8DF3BBA791072DAEDFD1
Host:localhost:8080
Origin:http://localhost:8080
Pragma:no-cache
Referer:http://localhost:8080/user
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
X-Requested-With:XMLHttpRequest
Form Data
isAjax:true
"obj.name":ADMINISTRATOR
"obj.language":en
"obj.email":admin@frontend.com.br
"obj.username":admin
"obj.status":ATIVO
"obj.id":1
"obj.groups[0]":1
"obj.groups[1]":2
"obj.groups[2]":3
Response Headers
Content-Type:application/json;charset=UTF-8
Date:Thu, 17 Jan 2013 19:12:28 GMT
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
Na parte do Form Data ele lista os parâmetros da requisição… Eu vou tentar retirar a parte que manda o groups para ver se resolve alguma coisa…
EDIT
Antes de remover o group, eu vou colocar aspas entre os valores da requisição… Ele pode estar se perdendo…
tenta no servidor debugar e ver o request.getParameterMap(), ver o que tá lá
Fiz os dois testes. Ainda ocorre o mesmo problema… 
viu os parâmetros que chegaram no servidor?
Ah! Eles estão vindo… Porém estão vindo com as aspas que eu coloquei, conforme aquele tópico…
Faz sentido ele não encontrar pois “obj.status” não existe, mas obj.status existe…
Eu preciso ou remover as aspas quando chega no servidor ou mudar a minha forma de enviar parâmetros via ajax…
e se eu fizesse assim no ajax:
data = {
obj : {
name : "ADMINISTRATOR",
language : "en",
email : "admin@frontend.com.br",
username : "admin",
status : "ATIVO",
id : "1",
groups : [1, 2, 3]
}
}
O servidor iria entender?
o problema não é o servidor entender… é o como o jquery serializa isso na requisição… dá uma olhada como o browser faz lá no Form Data do chrome
É… o jQuery serializou de uma forma estranha:
isAjax:true
obj[name]:ADMINISTRATOR
obj[language]:en
obj[email]:admin@frontend.com.br
obj[username]:admin
obj[status]:ATIVO
obj[id]:1
obj[groups][]:1
obj[groups][]:2
obj[groups][]:3
Então como que eu faço para remover as aspas dos names das variáveis?
Sobrescrevendo ParanamerProvider?
se vc fizer:
data = {
"obj.name" : "ADMINISTRATOR",
"obj.language" : "en",
...
}
deve funcionar
Isso funciona pois eu já usei assim…
Mas como que eu faço isso, já que eu vou pegar o atributo name do input dinamicamente?
Eu estou fazendo assim:
form.find('[name]').each(function(){
var self = $(this);
var name = '"' + self.attr('name') + '"';
data[name] = self.val();
});
Se eu fizer sem essas aspas, ele dá aquela exception maluca…
data[self.attr('name')] = self.val();
deveria funcionar…
em todo caso, form.serialize() já faz isso que vc quer 
O form.serialize() vai gerar uma String… Se eu passar essa String para o data, vai funcionar?
Mas existe um tipo de elemento que eu estou usando que não é um input… O form.serialize() não iria considerá-lo, e para considerá-lo, eu precisaria transformá-lo em checkbox, o que seria um pouco chato de ser feito…
De todo jeito, isso:
form.find('[name]').each(function(){
var self = $(this);
// var name = '"' + self.attr('name') + '"';
data[self.attr('name')] = self.val();
});
Não é a mesma coisa que isso:
form.find('[name]').each(function(){
var self = $(this);
// var name = '"' + self.attr('name') + '"';
var name = self.attr('name');
data[name] = self.val();
});
E dessa forma (sem as aspas) dava aquela exception…
o data funciona com string sim
se o cara não é um input é o que? o serialize funciona com select e textarea tb.
Ele é um ul… Ele tem um atributo chamado “data-name” e eu faço um processo diferente para ele:
[code]form.find(’[data-name]’).each(function(){
var self = $(this);
var name = ‘"’ + self.attr(‘data-name’) + ‘"’;
if (self.hasClass('selectable')) {
var position = 0;
self.children().each(function(){
self = $(this);
if (self.hasClass('ui-selected'))
data[name.replace(/\{0\}/g, position++)] = self.val();
});
} else if (self.hasClass('ui-selected'))
data[name] = self.val();
});[/code]
Eu fiz isso para poder usar com o jquery-ui selectable, então dá para usar com tables, ul… Desde que usem o selectable…
Eu vou mudar a minha função para gerar uma String igual o form.serialize() faz… Vou usá-lo e complementar com o que eu vou gerar para o selectable.
vc pode fazer ao invés do data[name] = self.val():
form.append($('<input/>' {name: name, value: self.val(), type: "hidden"});
isso só precisa rodar antes do form.serialize();