Estou trabalhando em um projeto onde estamos planejando criar uma camada de serviço que será acessada a partir de vários clients. Nossa idéia é criar uma API REST para expor esses serviços usando Restfulie/Vraptor.
Uma dúvida que surgiu é com relação ao cache do que será retornado da chamada para o serviço. Li nos docs que o Restfulie consegue incluir metadados/heades referentes ao cache no lado do servidor (last modified, etag, max age, etc). Mas esse resultado pode ser cacheado em um client Java?
Não sei se estou sendo claro, mas supondo um código usando commons-http que faça a chamada para a URI do serviço que retorna uma entidade, uma vez que o Restfulie inclui as informações de cache no response, esse resultado já será cacheado na aplicação client “magicamente”?
(aproveitando, o Restfulie tem API pro lado client?)
[quote=felipeguerra]o que vai estar em caché? dados? esses dados são consultados no banco? sua API de ORM está com o cache habilitado? 1º e 2º nível?
[/quote]
Sim. Sim. Sim. Sim.
Mas independente da API de ORM estar com o cache habilitado, o que eu desejo cachear é a resposta da chamada HTTP, uma vez que pra quem vai invocar o serviço a origem dos dados vai ser transparente.
se o servidor retornou na requisição os headers de cache (ETag, LastModified, etc), você não só pode como deve cachear o conteúdo ou pelo menos fazer a requisição condicional (If-None-Match, If-Modified-Since).
e o httpclient faz isso com o caching-http-client.
beleza Lucas, minha idéia era isso mesmo. De fato, parece que o httpclient resolve esse galho. Os caras que voce citou ((If-None-Match, If-Modified-Since) são o que, headers que devo passar na requisição?
Aproveitando, eu estava lendo nessa documentação do Restfulie aqui, https://github.com/caelum/restfulie-java, e sobre o cache diz pra implementar a interface RestfulEntity. Essa implementação deve ser feita na classe que expoe o serviço (o controller, por ex.) ou na classe do recurso (que seria a entidade)? Percebo também que os exemplos contem entidades com anotações do XStream, o Restfulie não trabalha com as anotações do JAX-B?
em geral, se vc usa um cliente que suporta caching, ele manda esses headers já automaticamente, se a resposta do servidor tiver ETag ou Last-Modified… se vc conseguir monitorar o servidor pra ver se esses headers estão sendo enviados.
o restfulie usa o XStream, mas vc consegue sobrescrever um componente pra ele começar a usar o jaxB sem problemas.
pelo nome da interface (RestfulEntity) era de se supor, me perdoe a ignorancia :lol: ,
mas não é um pouco intrusivo isso? se eu quiser retornar uma entidade qualquer lá do meu modelo, a princípio essa classe não deveria se preocupar com cache…
não, mas ela sabe quando ela foi modificada pela última vez, e sabe gerar o ETag de acordo com os seus dados (um hash md5 de alguns campos por exemplo)… a única coisa estranha é o maximum age…
mas é razoável supor que a entidade saiba mais ou menos de qto em qto tempo ela é executada.
Uma entidade não precisa ser apenas um monte de atributo e getters/setters
Hm, tem razão…essas informações, embora não sejam necessiariamente pertinentes para o funcionamento interno da classe, são parte do dominio da entidade. Faz sentido
Voltando ao assunto, Lucas, pode dar mais uma ajudinha aqui? Tô fazendo uma provinha de conceito aqui sobre esses items,
O meu controller é esse aqui,
package br.com.service.controller;
import static br.com.caelum.vraptor.view.Results.*;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.service.model.Model;
@Resource
public class ModelController {
private Result result;
public ModelController(Result result){
this.result = result;
}
public void all(){
Model model = new Model(1, "Model 1");
result.use(representation()).from(model).serialize();
}
}
a classe do recurso,
package br.com.service.model;
import java.util.Calendar;
import org.joda.time.DateTime;
import br.com.caelum.vraptor.restfulie.hypermedia.HypermediaResource;
import br.com.caelum.vraptor.restfulie.relation.RelationBuilder;
import br.com.caelum.vraptor.restfulie.resource.RestfulEntity;
public class Model implements RestfulEntity, HypermediaResource {
private int id;
private String name;
public Model(){}
public Model(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public int getMaximumAge() {
return 300;
}
@Override
public String getEtag() {
return id + "." + name.toLowerCase();
}
@Override
public Calendar getLastModified() {
return DateTime.now().toGregorianCalendar();
}
@Override
public void configureRelations(RelationBuilder builder) {
}
}
Fiz um client usando o http-client (a proposito onde estão os jars do client do restfulie, no repositorio do github?), e os cabeçalhos sobre o cache funcionaram mesmo (viva!). Só que,
Quando eu faço o controller assim, forçando o retorno para json
Model model = new Model(1, "Model 1");
result.use(json()).from(model).serialize();
os headers (etag, last-modified, etc) não são adicionados. é assim mesmo que é pra ser?
os cabeçalhos também só foram adicionados quando, alem de RestfulEntity, eu implementei HypermediaResource na classe Model. Essa interface também é imperativa?
então só funciona com o representation() mesmo e com HypermediaResource, infelizmente.
abre uma issue pedindo pra mudar isso por favor?
e se quiser fazer um pull request melhor ainda =)
pra funcionar com o json() vc pode criar uma implementação sua do JSONSerialization que usa a mesma lógica do DefaultRepresentationResult (com o RestfulEntity se vc preferir)
vc pode criar uma classe que estende XStreamJSONSerialization e sobrescrever o método from colocando o código dos headers a mais.
cara mais uma duvida, por favor…a resposta também está retornando o JSESSIONID, via cookie. é o vraptor que está criando a sessão?
e outra menos importante, hehe, nessa classe ai a principio eu extendi RestfulSerializationJSON, mas ocorreu um erro do Spring informando que não havia nenhuma implementação da interface Restfulie (mas tem, br.com.caelum.vraptor.restfulie.DefaultRestfulie). Algum motivo pra esse erro (aliás pra que serve exatamente a classe RestfulSerializationJSON :lol: )?
edit: ops abro a issue sim, e esse detalhe que os headers só são adicionados pra objetos do tipo HypermediaResource, comenta na issue pra alterar tambem?
acho que essa restfulxxxjson não está suportada oficialmente… é uma implementação parcial…
você não usa a sessão em nenhum outro lugar? o vraptor não tem nenhum componente sessionScoped registrado. Só talvez use a sessão pra implementar o FlashScope
mas o método handle da interface RestHeadersHandler só aceita um HypermediaResource como parametro, e ele já tem a lógica pra adicionar o header…
vou abrir a issue lá, na descrição posso comentar sobre a obrigatoriedade dessa interface? na documentação tambem diz pra implementar apenas RestfulEntity