Vraptor3: conflito de rotas [resolvido]

Criei o controller abaixo usando as mesmas rotas mas diferenciando os métodos via @Get e @Post.

[code]@Get
@Path( { “/customer/{id}/”, “/customer/new/” })
public void edit(Long id) {
[…]
}

@Post
@Path( { “/customer/{id}/”, “/customer/new/” })
public void store(Customer customer) {
[…]
}
[/code]

Quando faço o submit do formulário recebo o seguinte erro.

Os logs de inicialização do vraptor:

INFO: /customer/ --> public void CustomerController.list(Paging) INFO: /customer/page-{paging}/ --> public void CustomerController.list(Paging) INFO: /customer/{id}/ --> public void CustomerController.store(Customer) INFO: /customer/new/ --> public void CustomerController.store(Customer) INFO: /customer/{id}/ --> public void CustomerController.edit(Long) INFO: /customer/new/ --> public void CustomerController.edit(Long)

Conforme as mensagens de erro, será que o vraptor se perde quando há um array de paths sendo os mesmos para post e get? Em caso que uso apenas um path para post e outro para get funciona bem. O erro aparece apenas quando tenho array de path.

no edit:

@Path( { "/customer/{id}/", "/customer/new/" })  
public void store(Customer customer) {  
    [...]  
}

vc fez o {id} mas não existe nenhum parâmetro chamado id… então o vraptor não coloca nenhuma restrição nesse parâmetro, fazendo com que a uri /customer/new/ possa ser usada em ambas as uris…

troque pra {customer.id} que vai funcionar…

PS: faz sentido editar um /customer/new?

Lucas, funcionou. Era por causa do {id}. Na hora do copy and past deu isso, hahahaha.

Sobre o new, na verdade o método para editar e incluir é o mesmo. Caso o id não for nulo eu carrego o objeto e jogo na tela. Como uso resources-rest deixei /customer/xx/ para quando o cara quiser editar, e /customer/new/ para inclusão. Só para deixar mais bonita a uri, hahaha. No caso o método store usa a mesma coisa porém como POST.

Abraços

entendi… só por curiosidade: é costume usar POST /customer para adicionar um customer, não POST /customer/new

Lucas, é verdade. O sono não me deixou notar isso, hehe. O pior que esse projeto é só para webservice rest de uma ferramenta de auto-atualização. Já que é tudo rest posso usar o grupo @Post, @Get, @Put e @Delete muito fácil. Nem reparei mesmo.

Em uma outra aplicação minha maior que tenho com vraptor não posso usar rest dessa forma, uso apenas as user-friendly urls. Então o padrão é eu fazer coisas como /customer/ para listar, /customer/new para novo, /customer/edit/xx para editar, /customer/delete/xx para excluir… Não uso os @Delete por exemplo porque a exclusão não vem de um form, então passar na querystring ficou feio, além do mais o projeto não envolve muito crud, por isso adorei um padrão mais flexível. Assim posso ter por exemplo /customer/store-enrollment/xxx, etc.

mesmo não usando todos os verbos HTTP, é recomendável respeitar que requisições GET não tenham efeitos colaterais na sua aplicação, ou seja, que elas não modifiquem nada…

vc faz exclusões usando links? ajax?

Lucas, está errado eu usar, por exemplo, /customer/delete/xx?

Por incrível que possa parecer, tenho uma aplicação monstro fazendo exclusão via link, por exemplo, /customer/delete/xx. Porém quando esse link é acessado vocẽ vai para a tela que mostra os dados do registro e pergunta: “você tem certeza que deseja remover o registro xx?”.

Ou seja, na verdade o get não faz modificações em minha aplicação, ele serve apenas de ponte para ação, que esta sim está no post. Acho que me expressei mal no post acima (efeito do sono, hehe).

se for assim tudo bem então =)

o q vc pode fazer tb, é fazer essa confirmação via javascript (usando um plugin do JQuery que faz Dialogs, por exemplo) e fazer a requisição com ajax, até usando o método DELETE mesmo…

mas enfim, dei palpites demais já :wink:

Lucas, seus palpites me deram uma boa clareada nas idéias, hehe. Realmente algumas coisas eu estava fazendo errado.

Vou analisar essa sugestão de usar o @Delete com uma confirmação via jquery. Muito boa a sugestão.

Abraços, e obrigado,

Lucas, como eu faço para chamar o @Delete via jquery? Há alguma forma diferente ou basta adicionar o parametro _method?

se vc usar o $.ajax (http://api.jquery.com/jQuery.ajax/), ele tem uma configuração chamada type:

$.ajax(...., {
     ...,
     type: 'DELETE'
  });

mas, de acordo com a documentação:

o mais garantido é fazer uma requisição POST com _method=DELETE (não pode ser query parameter)