é possível anotar um método de uma Controller com a @Transactional do Spring?
assim:
@Path("/detalhado/{idBaseProcessamento}")
@Transactional
public void detalhado(Long idBaseProcessamento) {
BaseProcessamento base = dao.findById(idBaseProcessamento);
base.getItems().size(); //fiz isso pra rodar o lazy loading.. só pra teste
result.include("base", base);
}
acontece que desde que coloquei comecou a dar pau de CGLib… mas eu inclusive já tenha a lib dela…
antes deu classnotfound do AspectJ… coloquei o jar… aí depois começou a dar IllegalStateException de CGLib alegando que não poderia passar null num tal construtor la…
Qual a maneira correta de transacionar um método do Controller?
o melhor jeito de usar um Transactional no controller é usando Interceptors do VRaptor mesmo…
crie esse interceptor:
@Intercepts
public class TransactionalInterceptor {
//sem construtor
public boolean accepts(ResourceMethod method) {
return method.containsAnnotation(MeuTransactional.class); //crie essa anotação
}
@Transactional // do spring
public void intercept(...) {
stack.next(...);
}
}
outra solução é fazer injeção por init method nos controllers que precisarem do @Transactional:
@Resource
public class MeuController {
@Autowired
public void init(Objeto1 um, Objeto2 dois) {
//public MeuController(Objeto1 um, Objeto2 dois) { //troque o construtor pelo init
this.um = um;
this.dois = dois;
}
}
pensando bem, acho que ja tenho as respostas das minhas dúvidas acima…
o VRaptor pode ter outros provides de IoC além do Spring, logo não poderia amarrar a @Transactional do Spring numa Controller
sobre os testes… dei uma viajada… os controllers, quando testados, são instanciados via operador ‘new’… ou seja, qualquer anotação no método será ignorada
estou correto nas minhas colocações?
agora uma sugestão: pra evitar amarrar a controller no Spring com a @Transactional, o VRaptor poderia ter uma anotação própria repassasse o gerenciamento da transação para o provider usado.
o spring consegue tratar a anotação dentro do controller. O q acontece é q qdo vc coloca a anotação no controller o Spring usa o AspectJ pra colocar as transações. E o AspectJ só consegue fazer isso se a classe tiver construtor sem argumentos ou vc usar interfaces. No caso do controller não tem como chamar via interface (pq é o vraptor que chama), então vc precisa do construtor sem argumentos mesmo.
não é por isso, é pelo motivo que eu citei acima. o Transactional não tem nada a ver com o VRaptor
nos seus testes vc vai precisar controlar a transação manualmente, ou mockar a session ou o dao pra não precisar disso
os outros containers não tem nada parecido com o @Transactional.
vc pode usar o do spring sim, desde que o seu controller tenha um construtor sem argumentos.
criei o Interceptor e a anotação própria exatamente do jeito que você falou.
mas tive o mesmo ClassCastException que o dbdbdb teve.
Ela aparece sempre que subo o VRaptor com alguma anotação @Transactional (do Spring)
Engraçado que é só tirar a anotação que a aplicação sobe perfeitamente.
foi exatamente esta classclastexception que tive…
mas acabei criando uma outra classe e colocando a lógica do método do controller nessa classe… essa classe sim tinha o método anotado com @Transactional
como isso resolveu, acabei esquecendo de postar a exception de ClassCast aqui… sorry…
enfim, então realmente não da pra anotar o intercept() com o @Transactional como vc postou acima?
valeu Lucas! um legítimo suporte técnico para o excelente VRaptor!
a anotação estava no Controller? ou no Interceptor?
com o código atual do VRaptor não dá pra anotar com @Transactional em alguns tipos de classes, talvez seja uma boa investigar se a gente está fazendo algo de errado ou se tem alguma solução boa pra isso…
na minha primeira tentativa (primeiro post do tópico) estava num método da controller
aí vc me explicou que não daria pois como a Controller nao tem interface, as dependencias nao poderiam ser setadas no construtor, e sim num método init().
ou então criando uma annotation própria e fazendo um Interceptor e colocando a @Transactional no intercepts()
entao a ClassCastException deu quando a @Transactional estava no intercepts() do Interceptor
amanha na empresa vou fazer um projetinho que simula o erro e vou incluí-la na issue que pediu pra criar
valeu mais uma vez!
as vezes acho que estou abusando da sua boa vontade! hehehe…
no que precisar de ajuda sobre este assunto, pode contar comigo!
teremos que retirar as @Transactional e as injeções de EntityManager do Spring e utilizar as injeções de EntityManager (ComponentFactory) do próprio VRaptor?