Bom dia a todos do GUJ,
Estou com uma questão de estrutural nas mãos. Estou com um projeto nas mãos que tem a seguinte estrutura: Um projeto (DAO.jar) que use JPA para encapsular os objetos de banco; um projeto (Negocio.jar) que use o (DAO.Jar) para encapsular a regra de negocio; e para finalizar a 1ª etapa, um projeto (WEB.jar) que é um sistema JSF2+primefaces, o (WEB.jar) usa o negocio para realizar as suas funções.
Uma informação importante é que após a 1ª leva de implementações será criado um novo projeto (Local.jar) que é sistema swing que usa o projeto (Negocio.jar).
Meu problema esta na criação e utilização do EntityManager. Estou preocupado com a utilização por parte do sistema web (execução em threads).
Em um contexto static eu crio o meu EntityManagerFactory.
static {
emf = Persistence.createEntityManagerFactory(“BANCO_DAO”);
}
Através dele todas as sessões (threads) podem criar um EntityManager. A questão em vogo é a armazenagem e reutilização por todos os objetos do DAO. A primeira ideia seria injetar o EntityManager mais esbarro no problema que a injeção só funcionar para mesmo projeto e para projeto web. Pensei também em colocar na sessão do usuário mais ai amaria o DAO.jar a utilização somente por sistemas WEB inviabilizando o reuso do DAO.jar e Negocio.jar.
A minha pergunta é como eu compartilho o EntityManager para os objetos que estão na mesma sessão (thread) de modo que eu possa controlar coisas como transações para gravações de vários DAOs tanto para o mundo web como o local?
Grato a todos por qualquer ajuda.
Você está querendo utilizar o Dao.jar de dentro do Local.jar? É isso?
O Local.jar vai usar o Negocio.jar que por sua vez usa o DAO.jar.
A ideia seria trabalhar em camadas que possam ser reutilizadas na plataforma web como também na local (swing).
No final das contas o que queremos é poder ter a mesma funcionalidade tanto na web quanto local. Logicamente usando as mesmas regras de negocio.
[quote=lucaonoforum]O Local.jar vai usar o Negocio.jar que por sua vez usa o DAO.jar.
A ideia seria trabalhar em camadas que possam ser reutilizadas na plataforma web como também na local (swing).
No final das contas o que queremos é poder ter a mesma funcionalidade tanto na web quanto local. Logicamente usando as mesmas regras de negocio.
[/quote]Para isso o melhor seria utilizar ou EJB ou Spring para realizar isso.
Eu poderia te falar como fazer isso com EJB. Bastaria criar os métodos e realizar um Lookup JNDI. Desse modo a Injeção funcionaria numa boa e quem tomaria conta do EM seria o próprio servidor e não um controle na mão.
Será que não tem nenhuma maneira de fazer isso com JPA nem que seja codificando um controlador.
Pensando sobre isso esbarrei no problema de encontrar um identificador para a sessão da web e do programa local.
Pensei no Thread.currentThread().getId(), porem a cada requisição web usa uma thread diferente.
O que você acha?
[quote=lucaonoforum]Será que não tem nenhuma maneira de fazer isso com JPA nem que seja codificando um controlador.
Pensando sobre isso esbarrei no problema de encontrar um identificador para a sessão da web e do programa local.
Pensei no Thread.currentThread().getId(), porem a cada requisição web usa uma thread diferente.
O que você acha?
[/quote]Não acho seguro.
Se você sempre pegar um entityManager de um entityManagerFactory, é thread safe.
Arriscado é passar entityManager entre aplicações, camadas, etc…
EJB eu vejo como melhor saída.
Bom saber que é thread safe mais a questão não é a criação e sim a disponibilização para os outros objetos.
Por exemplo, dois façades criados por uma classe de negocio que ao executar um método qualquer deve gravar os dois na mesma transação.
Os dois façades teria que usar o mesmo EntityManager. Esse seria conseguido pegando no controlador que através do um IDENTIFICADOR (que eu não sei qual) passaria o mesmo EntityManager para os dois façades. Assim o negócio controlaria o inicio e termino da transação sabendo que os dois objetos estão dento da transação que ele iniciou.
Deu para entender? No final das contas uma maneira de fazer a conexão com o banco ser única para cara usuário das classes do DAO.jar e do Negocio.jar.
Me faz grande um favor me diz que tem como fazer isso.
Por favor, hehe
O jeito seria fazer algo do tipo:
dentro do facadeA
em = Controlador.getEM(); // aqui pegaria um EntityManager
em // começa a transação
facabeB.criarCarro(carro, em); // envia o entityManager para o facadeB que poderia ser feito também de outro modo, facadeB.setEM(em);
em // finaliza transação
É o modo que eu consigo pensar agora. Acho feio, mas funciona. ^^
Pois é a ideia seria mais ou menos essa mais sem a necessidade de ter que passar por parâmetro os façades já conheceriam o EntityManager através do controlador.
O controlador no método get EntityManager () iria pegar o Identificador para ir na lista dele e pegar o EntityManager correto. Assim não precisaria passar por parâmetro e o negocio só ira iniciar e commitar a transação.
A volta a questão, qual o identificador usar nesse caso?
[quote=lucaonoforum]Pois é a ideia seria mais ou menos essa mais sem a necessidade de ter que passar por parâmetro os façades já conheceriam o EntityManager através do controlador.
O controlador no método get EntityManager () iria pegar o Identificador para ir na lista dele e pegar o EntityManager correto. Assim não precisaria passar por parâmetro e o negocio só ira iniciar e commitar a transação.
A volta a questão, qual o identificador usar nesse caso?
[/quote]Aí eu volto a te falar, não acho seguro e nem aconselho.
Bem, caso tenha alguma saída, alguém de Swing deveria te ajudar pois eu não sei falar. Boa sorte. [=
Esquecendo um pouco o swing, teria algum identificador para JSF ou do próprio JPA?
[quote=lucaonoforum]Esquecendo um pouco o swing, teria algum identificador para JSF ou do próprio JPA?[/quote]Nunca ouvi falar de tal feature.
[quote=Hebert Coelho][quote=lucaonoforum]Esquecendo um pouco o swing, teria algum identificador para JSF ou do próprio JPA?[/quote]Nunca ouvi falar de tal feature. [/quote]Pode ser que exista, mas nunca ouvi falar.
Então se eu gerasse um identificador.
Dentro do controlar tivesse uma propriedade que seria uma interface que teria um único método para retornar um id para o controlador.
No caso da web eu criaria um objeto que pegasse algo como o id da sessão do JSF e no caso do local eu retornaria um valor default.
Qual a sua impressão desta solução do problema?
[quote=lucaonoforum]Então se eu gerasse um identificador.
Dentro do controlar tivesse uma propriedade que seria uma interface que teria um único método para retornar um id para o controlador.
No caso da web eu criaria um objeto que pegasse algo como o id da sessão do JSF e no caso do local eu retornaria um valor default.
Qual a sua impressão desta solução do problema?[/quote]Funciona. Você teria apenas que controlar isso na unha para fazer thread safe. Mas esse identificador teria que ser passado entre um facade e outro. O que daria o mesmo que passar o EM.
Pensei em um atributo do controlador assim:
public static IGeneratorId gerado;
static para só exitir um no sistema e que possa ser
preenchido por qualquer sistema. Evita a passagem de objetos.
o que vc acha?
[quote=lucaonoforum]Pensei em um atributo do controlador assim:
public static IGeneratorId gerado;
static para só exitir um no sistema e que possa ser
preenchido por qualquer sistema. Evita a passagem de objetos.
o que vc acha?
[/quote]E dois usuários teriam o mesmo cara estático?
O atributo seria do controlador. Assim faria algo assim:
Controlador.gerador = new GeradorIDWeb;
ou
Controlador.gerador = new GeradorIDSwing;
Isso no carramento da aplicação ou no init do servidor.
Existem uma ideia na minha equipe de controlar o EntityManager e as transações através de um Filter.
Eu particularmente não gostei da ideia de a cada requisição criar um EntityManager e iniciar uma transação mesmo que ela não seja usada.
Alguém comunga da minha opinião?
Isso é chamado de OpenSessionInView ou TransactionInView.
Tem suas vantagens e desvantagens.
Mas como a parte Swing iria disparar o View?