Complicou. Qual a necessidade de bindar JNDI para o DAO ? Ele não pode estar em um jar a parte, utilizado pelo EJB ? ( A outra aplicação que é stand alone, nao pegará os DAOs do AS, pois será construida para rodar sem o mesmo )
Ume breve explicação do motivo:
Minha aplicação é de varejo, e nem todos os meus clientes ( alias, a minoria deles ) terão uma estrutura física que permita um aplication server. A maioria das lojas de shopping possui apenas uma máquina, e nao tem sentido instalar um AS para rodar a aplicação. Por outro lado, não posso ignorar os clientes que precisarão de integração entre lojas, loja virtual, load balancing, centralização dos dados, etc…
Minha estrutura é a seguinte:
Extasy-Enterprise-EJB.jar --> Contem as interfaces e implementações dos Facades ( Meus Session Beans ), configurações do AS e a Persistence unit.
Extasy-Core.jar —> Contém as entiaddes anotadas e os DAOs ( Comum tanto a aplicação Enterprise quanto a Stand Alone )
Para a aplicação Stand-alone funcionar, o EntityManager deve estar nos DAOs. Os Session Beans seguem o formato de CrUDe, mas que simplesmente fazem chamadas aos metodos CrUDe do DAO.
Quando fazia da forma convencional ( com o EM dentro do Session Bean ), o EM era injetado corretamente. Resolvi então fazer a mudança para a estrutura que citei acima. Aí começaram meus problemas:
1- A injeção nao funcionava no DAO
Solução: Utilizar EntityManagerFactory
2- Na geração inicial dos dados, feita logo que o módulo ejb era instalado, dava tudo certo ( pois o deployer sabia como obter o entity manager a partir do Persistence unit ), mas quando eu tentava criar o EntityManagerFactory a partir do PU não mão ( já que este não era injetado ) para utilizá-lo com o DAO, tinha diversos problemas com o JTA… (Ex: “The chosen transaction strategy requires access to the JTA TransactionManager”)
Solução: Bindar o EM e o EM Factory via JNDI pelo PU
3- Agora funciona. Só não sei o que está fazendo a diferença entre criar o EntityManagerFactory passando como parâmetro a PU e bindá-lo na PU, pegando por JNDI. Parece quando que o EMF é criado passando como parâmetro a PU, o container “esquece” de setar algumas propriedades ou de bindar alguma coisa. O problema agora é que não fica compatível com Stand Alone, principalmente pelo fato de ter aquelas referencias aos JNDI do JBOSS ( De repente até fique compatível, pois a aplicação stand alone com Hibernate Entity Manager utiliza tanta coisa do JBoss, que dá a impressão de que roda dentro de um microkernel do mesmo, só que embarcado - Até os logs são iguais ).
Agora que expliquei tudo, lá vão as perguntas:
Tem alguma outra alternativa sem ser bindar o EMF e o EM por JNDI ?
Em ultimo caso: O Spring resolveria meu problema ( tanto no AS quanto Stand alone ), sem ser mais um monte de jars, com um monte de configurações para dificultar ainda mais a programação ?
Aqui vão alguns dos fontes:
Persistence Unit
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="Extasy-Enterprise-ejbPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MySqlDS</jta-data-source>
<class>com.highlands.model.inventario.Modelo</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="jboss.entity.manager.jndi.name" value="java:/Manager1"/>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/Manager1Factory"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
Classe anotada
/*
* Modelo.java
*
* Created on 27 de Agosto de 2007, 21:30
*/
package com.highlands.model.inventario;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* Classe de entidade Modelo
*
* @author macleod
*/
@Entity
public class Modelo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(length=60, unique=true, nullable=false)
private String descricao;
/** Creates a new instance of Modelo */
public Modelo() {
}
/**
* Define o id deste Modelo.
* @return o id
*/
public Integer getId() {
return this.id;
}
/**
* Define o id deste Modelo para o valor especificado.
* @param id o novo id
*/
protected void setId(Integer id) {
this.id = id;
}
public String getDescricao() {
return descricao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
/**
* Retorna um valor de c�digo hash para o objeto. Esta implementa��o computa
* um valor de c�digo hash baseado nos campos id deste objeto.
* @return um valor de c�digo hash para este objeto.
*/
@Override
public int hashCode() {
int hash = 0;
hash += (this.id != null ? this.id.hashCode() : 0);
return hash;
}
/**
* Determina se outro objeto � igual a este Modelo. O resultado �
* <code>true</code> se e somente se o argumento n�o for nulo e for um objeto Modelo o qual
* tem o mesmo valor para o campo id como este objeto.
* @param object o objeto de refer�ncia com o qual comparar
* @return <code>true</code> se este objeto é o mesmo como o argumento;
* <code>false</code> caso contr�rio.
*/
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Modelo)) {
return false;
}
Modelo other = (Modelo)object;
if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) return false;
return true;
}
/**
* Retorna uma representação literal deste objeto. Esta implementação cria
* uma representação baseada nos campos id.
* @return uma representação literal deste objeto.
*/
@Override
public String toString() {
return "com.highlands.model.inventario.Modelo[id=" + id + "]";
}
}
Session Bean Stateless
/*
* ModeloFacade.java
*
* Created on 27 de Agosto de 2007, 21:31
*
*/
package com.highlands.model.inventario;
import com.highlands.persistence.DAOFactory;
import com.highlands.persistence.IGenericDAO;
import java.util.List;
import javax.ejb.Stateless;
/**
*
* @author macleod
*/
@Stateless
public class ModeloFacade implements ModeloFacadeLocal, ModeloFacadeRemote {
/** Creates a new instance of ModeloFacade */
public ModeloFacade() {
}
@SuppressWarnings("unchecked")
public void create(Modelo modelo) {
IGenericDAO dao = DAOFactory.getDAO();
dao.create(modelo);
}
public void edit(Modelo modelo) {
@SuppressWarnings("unchecked")
IGenericDAO<Modelo> dao = DAOFactory.getDAO();
dao.edit(modelo);
}
public void destroy(Modelo modelo) {
@SuppressWarnings("unchecked")
IGenericDAO<Modelo> dao = DAOFactory.getDAO();
dao.destroy(modelo);
}
public Modelo find(Object pk) {
@SuppressWarnings("unchecked")
IGenericDAO<Modelo> dao = DAOFactory.getDAO();
return dao.find(Modelo.class, pk);
}
public List findAll() {
@SuppressWarnings("unchecked")
IGenericDAO<Modelo> dao = DAOFactory.getDAO();
return dao.findAll();
}
}
Remote
/*
* ModeloFacadeRemote.java
*
* Created on 27 de Agosto de 2007, 21:31
*
*/
package com.highlands.model.inventario;
import java.util.List;
import javax.ejb.Remote;
/**
*
* @author macleod
*/
@Remote
public interface ModeloFacadeRemote {
void create(Modelo modelo);
void edit(Modelo modelo);
void destroy(Modelo modelo);
Modelo find(Object pk);
List findAll();
}
Interface DAO
/*
* IGenericDAO.java
*
* Created on 28 de Agosto de 2007, 03:37
*
*/
package com.highlands.persistence;
import java.util.List;
/**
*
* @author macleod
*/
public interface IGenericDAO <E> {
public void create(E e);
public void edit(E e);
public void destroy(E e);
public E find(Class<E> c, Object pk);
public List <E> findAll();
}
Implementação de DAO para trabalhar com JPA / Entity manager
/*
* EJB3DAO.java
*
* Created on 28 de Agosto de 2007, 03:55
*
*/
package com.highlands.persistence;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
/**
*
* @author macleod
*/
public class EJB3DAO <E> implements IGenericDAO <E> {
private EntityManager em;
/** Creates a new instance of EJB3DAO */
public EJB3DAO() {
em = buscaEntityManager();
}
public void create(E e) {
em.persist(e);
}
public void edit(E e) {
em.merge(e);
}
public void destroy(E e) {
em.merge(e);
em.remove(e);
}
public E find(Class<E> c, Object pk) {
return em.find(c, pk);
}
public List<E> findAll() {
return null;
}
private EntityManager buscaEntityManager(){
EntityManager result = null;
try {
javax.naming.InitialContext ic = new javax.naming.InitialContext();
EntityManagerFactory emf = (EntityManagerFactory)ic.lookup("java:/Manager1Factory");
result = emf.createEntityManager();
} catch (Exception ex) {
Logger.getLogger("global").log(Level.SEVERE, null, ex);
}
return result;
}
}
DAO Factory
/*
* DAOFactory.java
*
* Created on 28 de Agosto de 2007, 03:53
*
*/
package com.highlands.persistence;
/**
*
* @author macleod
*/
public class DAOFactory {
private static IGenericDAO instance = null;
private DAOFactory(){
}
public static IGenericDAO getDAO(){
if (instance == null){
instance = new EJB3DAO<Object>();
}
return instance;
}
}
Aplicação cliente de Teste
/*
* Main.java
*
* Created on 30/08/2007, 01:06:23
*
*/
package extasyenterprise;
import com.highlands.model.inventario.Modelo;
import com.highlands.model.inventario.ModeloFacadeRemote;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.NamingException;
/**
*
* @author macleod
*/
public class Main {
/** Creates a new instance of Main */
public Main() {
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
ModeloFacadeRemote f = null;
try {
javax.naming.InitialContext ic = new javax.naming.InitialContext();
f = (ModeloFacadeRemote)(ic.lookup("Extasy-Enterprise/ModeloFacade/remote"));
} catch (NamingException ex) {
Logger.getLogger("global").log(Level.INFO, null, ex);
}
Modelo m = new Modelo();
m.setDescricao("Glórias a Deus !!! " + new Date());
f.create(m);
}
}
Abraços e obrigado pela atenção,
Carlos MacLeod