Estou com uma dúvida na parte de injeção de dependências do VRaptor3 que surgiu devido a um problema que estou enfrentando.
Iniciei um projeto e estou utilizando o JPA para persistência, criei um EntityManagerProvider para poder fazer uso do EntityManagerCreator e o EntityManagerFactoryCreator fornecidos pelo próprio VRaptor.
Criei meu DaoFactory que recebe o EntityManager no construtor, que é injetado normalmente pelo VRaptor.
public class DaoFactory {
private EntityManager em;
public DaoFactory(EntityManager em) {
this.em = em;
}
//métodos omitidos
}
A partir do DaoFactory eu crios os daos
public ColaboradorDao getColaboradorDao() {
return new ColaboradorDao(em);
}
O meu problema é o seguinte, eu criei uma implementação minha do DaoFactoryInterceptor que não abre a transação, optei por abri-la pela factory apenas nos métodos que realmente precisam de uma trasação, assim não abro uma transação apenas em métodos que só fazem consulta.
Acontece que ao fazer um teste se o meu rollBack estava funcionando, criei um método que simularia uma inclusão no meu ColaboradorController:
public void adicionar(Colaborador colaborador) {
factory.beginTransaction();
factory.getColaboradorDao().adicionar(colaborador);
}
Deixei sem o commit propositadamente para simular uma possível exception onde o rollBack deveria ser executado.
Mas ao retornar para o interceptor, a factory ve que existe uma transação aberta, executa o rollBack mas mesmo assim o objeto é persistido no banco.
Será que como eu recebo o EntityManager no construtor do ColaboradorDao ao instancia-lo está sendo injetado um EntityManager diferente do que foi injetado no DaoFactory ao invéz de usar o que eu passei como parâmetro?
Acredito que não seja isso porque o EntityManager é RequestEscoped correto?
Alguma luz do que pode estar acontecendo?
Se você está usando um appserver, não seria interessante deixar isso a cargo do container? Ou então se você está usando Spring deixa-lo tomar conta disso, ao invés de ficar controlando manualmente.
Sim, como o único lugar que pega a instância do EntityTransaction é no beginTransaction do DaoFactory é a mesma instância sim.
Estou usando Tomcat.
Essa arquitetura eu ainda vou alterar, só fiz desse modo para testar os métodos do DaoFactory se estão se comportando da maneira que devem.
Se for, o default do linux é o mysql criar base de dados MyISAM, que sao supe velozes mas nao possuem suporte a transacao. Voce precisa criar o banco com tabellas inno (InnoDB). Pra isso, mude o dialect para MySQLInnoDBDialect (ou algo assim).
Se nao for assim, é algo de auto commit que está ocorrendo por aí! (E voce tem certeza que o rollback esta sendo chamado no itnerceptador? Ele loga isso?)
Chutou exatamente no ponto, realmente estou em ambiente Linux + MySql.
Alterei meu persistence.xml para o dialect MySQLInnoDBDialect, deletei e recriei o banco e funcionou na hora.
Falando com meu chefe antes de ir embora do escritório ele comentou comigo do autoCommit, variável que eu nem sabia se existia.
Mas engraçado que fiz um teste com o mesmo código no Vista, exportei o projeto do Eclipse no Linux e importei no Vista, e me foi apresentado o mesmo problema.
Bom… o importante é que funcionou.
Valeu.
Mas agora surge uma dúvida.
Esse projeto que estou desenvolvendo, quando estiver em produção vai rodar em um Oracle.
Iniciei aqui com o MySql porque é o que eu já tenho aqui instalado e a princípio seria só eu trocar o dialect no persistence que o mesmo código passa a funcionar em um banco diferente.
Vocês recomendariam que eu já desenvolva direto no Oracle para evitar possíveis problemas na hora de colocar no ar?
Ja fizemos mais de um projeto onde o ambiente de testes era o MySQL e o producao era o Oracle. Com o hibernate fica facil fazer essa migracao, e nos dois casos nao tivemos NENHUM problema. Mas sempre tinhamos um outro ambiente de testes em que faziamos os testes de integracao de tempo em tempo, pra garantir que nao haveria um problema maior.
[quote=guedes]Esse projeto que estou desenvolvendo, quando estiver em produção vai rodar em um Oracle.
Iniciei aqui com o MySql porque é o que eu já tenho aqui instalado e a princípio seria só eu trocar o dialect no persistence que o mesmo código passa a funcionar em um banco diferente.
Vocês recomendariam que eu já desenvolva direto no Oracle para evitar possíveis problemas na hora de colocar no ar?[/quote]
Tudo depende. Se você usar o banco de dados para armazenamento de dados apenas tudo funciona bem. Digo isso porque se você implementar muitas procedures e features proprietárias do banco você perde a portabilidade.
Eu tenho um projeto muito grande, aproximadamente 550 tabelas. No desenvolvimento usei pgsql, porém a versão final será em Oracle. Até o momento, onde já fiz 50% do software, tudo está funcionando bem. Tenho apenas as tabelas e algumas views. Nesse caso o mesmo script que uso no pgsql posso usar no Oracle. As tabelas eu uso a criação do próprio JPA.
Quando o projeto entrar em produção vou ter que fazer a importação dos dados do pgsql, porém já estou com um script planejado para fazer. A cada 10 dias faço um deploy no ambiente de QA com base oracle para testar se tudo funciona bem. Por enquanto tenho tudo sucesso nisso.
Beleza pessoal, então vou continuar sem medo a produzir com o MySql, na hora de colocar em produção se der algum problema eu me viro.
xD
garcia-jj, será sim um banco apenas para armazenamendo e consulta de dados, sem views, procedures é um projetinho bem simples o que estou desenvolvendo.
lucascs, com a ajuda do Paulo já consegui resolver o problema.
Mais uma vez muito obrigado a todo mundo que ajudou.