Compartilhamento de EntityManager para web e para swing

26 respostas
L

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.

26 Respostas

Hebert_Coelho

Você está querendo utilizar o Dao.jar de dentro do Local.jar? É isso?

L

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.

Hebert_Coelho

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.

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.

L

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?

Hebert_Coelho

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?

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.

L

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. :cry: Por favor, hehe

Hebert_Coelho

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. ^^

L

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?

Hebert_Coelho

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?

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. [=

L

Esquecendo um pouco o swing, teria algum identificador para JSF ou do próprio JPA?

Hebert_Coelho

lucaonoforum:
Esquecendo um pouco o swing, teria algum identificador para JSF ou do próprio JPA?
Nunca ouvi falar de tal feature.

Hebert_Coelho

Hebert Coelho:
lucaonoforum:
Esquecendo um pouco o swing, teria algum identificador para JSF ou do próprio JPA?
Nunca ouvi falar de tal feature.
Pode ser que exista, mas nunca ouvi falar.

L

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?

Hebert_Coelho

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?

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.

L

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?

Hebert_Coelho

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?

E dois usuários teriam o mesmo cara estático?

L

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.

L

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?

Hebert_Coelho

Isso é chamado de OpenSessionInView ou TransactionInView.

Tem suas vantagens e desvantagens.

Mas como a parte Swing iria disparar o View?

L

Foi exatamente essa pergunta que eu fiz a quem deu ideia.

Hebert_Coelho

lucaonoforum:
Foi exatamente essa pergunta que eu fiz a quem deu ideia.
E o que ele respondeu?

AmauriSpPoa

lucaonoforum:
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?

Eu não usaria.

L

Eu só ouvi o som do grilo ao longe.

L

Pessoal eu acabei fazendo assim, Se alguem tive algo há contribuir.

public interface GeneratorId {
	public String getValorId();
}
public class Controlador implements Serializable {

	private static final long serialVersionUID = 1L;
	
	public static GeneratorId gerador; 

	/** */
	private static final EntityManagerFactory emf;
	private static HashMap<String, EntityManager> map = new HashMap<String, EntityManager>();

	static {
		emf = Persistence.createEntityManagerFactory("DAOPU");
	}

	public EntityManager getEntityManager() {
		
		String idAtual = null;
		if (gerador != null){
			idAtual = gerador.getValorId();
		}
		EntityManager em = map.get( idAtual );
		
		if (em == null) {
			em = emf.createEntityManager();
			map.put(idAtual, em);
		}
		return em;
	}
}
public class GeneratorIdControler implements GeneratorId {
	@Override
	public String getValorId() {
		HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
		return request.getSession().getId();
	}
}

e para usar no JSF, coloquei no Bean Inicial.

static{
	Controlador.gerador = new GeneratorIdControler();
}
L

Agora me veio a seguinte questão na mente, quando a sessão for finalizada por inatividade o EntityManager vai ficar no hash.

Tem alguma forma algum evento, listener ou alguma anotação que eu saiba que a sessão vai morrer para poder retirar o EntityManager do hash.

Alguem tem alguma ideia?

L

Alguem tem alguma ideia? Hebert?

Criado 14 de novembro de 2012
Ultima resposta 19 de nov. de 2012
Respostas 26
Participantes 3