Gostaria de criar webservices rest com vraptor.
Queria fazer algo mais o menos como rails.
/clientes/1.json -> retorno json
/clientes/1 -> retorno html
Como eu posso fazer isso com vraptor?
Gostaria de criar webservices rest com vraptor.
Queria fazer algo mais o menos como rails.
/clientes/1.json -> retorno json
/clientes/1 -> retorno html
Como eu posso fazer isso com vraptor?
O ideal é fazer isso via o header Accepts…
daí vc faria:
GET /clientes/1 Accepts: application/json
GET /clientes/1 Accepts: text/html
daí é só vc usar o result.use(Results.representation()).from(objeto).serialize(); que já funciona.
agora dá pra simular esse comportamento criando um filtro que modifica o request de acordo com a extensão… se quiser ajuda pra isso dá um toque 
O ideal é fazer isso via o header Accepts…daí vc faria:
GET /clientes/1 Accepts: application/json GET /clientes/1 Accepts: text/htmldaí é só vc usar o
result.use(Results.representation()).from(objeto).serialize(); que já funciona.agora dá pra simular esse comportamento criando um filtro que modifica o request de acordo com a extensão… se quiser ajuda pra isso dá um toque ;)
Lucas,
O header Accepts seria configurado no client, certo?
Não entendi direito como fazer isso.
A minha situação é a seguinte, vou criar uma aplicação que terá 3 clientes: IPhone, Android e o Site.
Gostaria de escrever apenas 1 Controller para as 3 interfaces.
Para as interfaces mobile eu utilizaria o retorno json, como um webservice. Para a interface web seria o fluxo normal do vraptor, com forwards, redirects e etc.
Como seria a melhor maneira de fazer isto?
se vc está usando algum http client para fazer a requisição, só pedir pra adicionar o header Accept do jeito que eu te falei
httpClient.addHeader("Accept", "application/json");
todo http client deveria ter como fazer isso, de algum jeito.
daí é só usar o representation() que ele vai fazer do jeito que vc quer.
se vc está usando algum http client para fazer a requisição, só pedir pra adicionar o header Accept do jeito que eu te faleihttpClient.addHeader("Accept", "application/json");todo http client deveria ter como fazer isso, de algum jeito.
daí é só usar o representation() que ele vai fazer do jeito que vc quer.
Vamos supor o seguinte fluxo:
if(json) {
//serializa o objeto e retorna o json
} else if(html) {
//forward pra outra action que irá listar os resultados
}
Como eu faria isso com este representation?
não é só dar forward pra action de listagem? e nela fazer a lógica do representation()?
tenta fazer o seguinte:
public void metodo(....., @HeaderParam("Accept") String accept) {
.....
if ("application/json".equals(accept)) {
....
} else {
;;;;
}
}
não é só dar forward pra action de listagem? e nela fazer a lógica do representation()?tenta fazer o seguinte:
public void metodo(....., @HeaderParam("Accept") String accept) { ..... if ("application/json".equals(accept)) { .... } else { ;;;; } }
Lucas, vou tentar fazer conforme você esta falando com o @HeaderParam.
Você pode me explicar o que o código abaixo faz quando o retorno é para ser HTML?
result.use(Results.representation()).from(objeto).serialize();
pro html é como se vc tivesse feito:
result.include(objeto);
e ele vai pra jsp padrão
pro html é como se vc tivesse feito:result.include(objeto);e ele vai pra jsp padrão
Lucas, muito obrigado pela ajuda mas acho que vou seguir a opção de criar um filtro para tratar a extensão da url (ex: client/1.json)
Você havia dito que poderia ajudar nesta implementação, você já tem algo pronto sobre isso?
registra esse filtro antes do filtro do vraptor:
public class ContentTypeFilter implements Filter {
//init
//destroy
public void doFilter(req, res, chain) {
chain.doFilter(new HttpServletRequestWrapper(req) {
@Override
public String getRequestURI() {
return super.getRequestURI().replaceFirst(".json$", "");
}
@Override
public String getHeader(String name) {
if ("Accept".equalsIgnoreCase(name)) {
String header = super.getHeader(name);
if (header == null) {
if (super.getRequestURI().endsWith(".json"))
return "application/json";
}
}
return super.getHeader(name);
}
}, res);
}
}
bom, com as devidas compilações corrigidas
e se precisar de mais tipos, só adicionar nos ifs
Aproveitando o tópico, bastante útil por sinal.
Qual o comportamento padrão do vraptor quando eu mando um header “Accept”?
Fiz uma requisição para uma controller com o header de valor “text/plain” e resultou nisso:
<html>
<head>
<title>Apache Tomcat/7.0.29 - Error report</title>
<style>
<!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}-->
</style>
</head>
<body>
<h1>HTTP Status 404 - /WEB-INF/jsp/pessoa/index.text/plain.jsp</h1>
<HR size="1" noshade="noshade">
<p>
<b>type</b> Status report
</p>
<p>
<b>message</b>
<u>/WEB-INF/jsp/pessoa/index.text/plain.jsp</u>
</p>
<p>
<b>description</b>
<u>The requested resource (/WEB-INF/jsp/pessoa/index.text/plain.jsp) is not available.</u>
</p>
<HR size="1" noshade="noshade">
<h3>Apache Tomcat/7.0.29</h3>
</body>
</html>
Quando mando “text/html” tudo ok. “application/json”, o mesmo erro a cima.
Valeu!
qdo vc manda o accept e não é html, o VRaptor tenta chamar a jsp do content-type desse accept, daí vc teria que implementar esse jsp…
outra forma é colocar ao final do método do controller:
result.use(Results.representation()).from(umObjeto).serialize();
assim se o accept for html ele mostra a jsp, se for json ou xml ele serializa, se for text/plain vc vai ter que escrever um deserializer pra isso.