[jboss-user] [EJB 3.0] - Accessing EntityManagerFactory/SessionFactory via JNDI serve

matt10 do-not-reply at jboss.com
Mon Sep 1 07:11:18 EDT 2008


I have an application framework which scans the EAR it is contained in for EJB3 entity bean classes and persistence units, to auto-detect them, in order to provide access to data through a facade SLSB.

I need to obtain the following programmatically:
1. A list of all Persistence Units
2. A list of all Entity Bean classes
3. The container-managed EntityManager for each Persistence Unit

Injecting the EntityManagers using annotations on beans is no good here because the PUs and Entity Bean classes will not be known by the application framework I am writing.
I want the facade to access data given only the simple class name of the entity bean.

I have a working theory of how to get the above but I've hit a blocking problem I can't get over during implementation.

In theory:
- I can get a list of all PUs from JNDI, as well as references to the SessionFactory or EntityManagerFactory objects.
- I can get a list of all entity classes in each PU by calling SessionFactory.getAllClassMetadata() on the SessionFactory for each persistence unit.
- I can get a SessionFactory from an EntityManagerFactory if I need to.
- I can get an EntityManagerFactory from an EntityManager if I need to.

I have tried to get a list of Persistence Unit names by scanning JNDI; either looking for the standard signature:

.. or by explicitly registering all PUs in a JNDI folder e.g.
  | persistence-units/PU2

Both JNDI entries should provide access to SessionFactory or EntityManagerFactory objects as per specs and documentation I've read, but the bound object is always an instance of javax.naming.Reference instead of the className I expect: org.jboss.ejb3.entity.InjectedEntityManagerFactory, org.hibernate.impl.SessionFactoryImpl, or the interfaces; javax.persistence.EntityManager, EntityManagerFactory or SessionFactory. Any of these objects from JNDI would do, I've tried looking up them all.

I've looked all over the place for a solution to this javax.naming.Reference problem. I figured it might be due to the class loader isolation I have configured with this snippet in jboss-app.xml:
  | 			java2ParentDelegation=false
  |     	</loader-repository-config> 
  | 	</loader-repository>

I need this isolation because I use a different version of BeanShell in my EAR than the one that ships with Jboss (using Jboss AS 4.2.0 at present; I have issues with most other versions except for 4.2.1). I have tried removing it, and verifying that isolation is not the default in ear-deployer.xml, but I still get javax.naming.Reference.

Other posts I've found refer to classpath problems with the client jar. However this code is running on the server so (if I understand how things work correctly) access to all the jboss classes is already available.

I'm currently working with a simple test case: TestBean.java that tries to look up EntityManagerFactories in JNDI:

  | @Service
  | @Management(IServiceManagement.class)
  | public class TestBean implements IServiceManagement {
  | 	public void create() throws Exception {}
  | 	public void destroy() {}
  | 	public void start() throws Exception {
  | 		logger.info("Starting TestBean service");
  | 		listAllPersistenceUnits();
  | 	}
  | 	public static void listAllPersistenceUnits() throws Exception {
  | 		InitialContext ctx = new InitialContext();
  | 		NamingEnumeration<Binding> list = ctx.listBindings("persistence-units");
  | 		while (list.hasMore()) {
  | 			Binding nc = (Binding)list.next();
  | 			logger.info("Persistence Unit EMF: "+nc.getName()+" [class: "+nc.getClassName()+"]");
  | 			Object o = nc.getObject();
  | 			if(!(o instanceof EntityManagerFactory))
  | 				logger.warn("No good; o instance of "+o.getClass().getName());  // javax.naming.Reference
  | 		}
  | 	}
  | 	public void stop() {}
  | 	protected static final Logger logger = Logger.getLogger(TestBean.class.getName());
  | }

persistence.xml for the test looks like this:

  |   <persistence-unit name="default" transaction-type="JTA">
  |     <jta-data-source>java:/ApplicationDS</jta-data-source>
  |     <properties>
  | 	   <property name="hibernate.hbm2ddl.auto" value="none"/>
  |        <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
  |        <property name="jboss.entity.manager.factory.jndi.name" value="persistence-units/default"/>
  |        <!-- testing:
  |        <property name="jboss.entity.manager.jndi.name" value="persistence-units/default"/>
  |              <property name="hibernate.session_factory_name" value="java:/session-factories/" /> -->
  |     </properties>
  |     </persistence-unit>

The output looks like this:

  | 11:44:38,846 INFO  [EJBContainer] STARTED EJB: org.foo.test.TestBean ejbName: TestBean
  | 11:44:38,886 INFO  [TestBean] Starting TestBean service
  | 11:44:38,900 INFO  [TestBean] Persistence Unit EMF: default [class: org.jboss.ejb3.entity.InjectedEntityManagerFactory]
  | 11:44:38,901 WARN  [TestBean] No good; o instance of javax.naming.Reference

I've been struggling with this problem for weeks.

Can anybody help me fix JNDI access, or indicate another solution for getting the container-managed EntityManager for a persistence unit programmatically?


View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4173578#4173578

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4173578

More information about the jboss-user mailing list