tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Blevins <david.blev...@visi.com>
Subject Re: Obtaining EntityManager programatically for test purposes
Date Sat, 07 Feb 2009 01:16:40 GMT

On Feb 3, 2009, at 5:56 AM, <Thomas.TH.Hamacher@partner.bmw.ch> <Thomas.TH.Hamacher@partner.bmw.ch

 > wrote:

> Hi @all,
>
> as a lot of folks I am not really satisfied with how JBoss currently  
> cares about their embedded application server.
> So I finally decided not to struggle around anymore, but to move to  
> openEJB as this seems a lot smoother and people speak very good  
> about it.
>
> So far everything works fine with openEJB, the only point I have is  
> to obtain an EntityManager programatically and not through  
> dependency injection for test purposes.
> I am trying to migrate the following function, which worked on JBoss:
>
> ------------------------------------
> public EntityManager getEntityManager(String persistenceUnitName)  
> throws ResourceNotFoundException {
>    LOG.info("getEntityManager " + persistenceUnitName);
>    EntityManager em = null;
>
>    String lookupString = "java:/EntityManagers/" +  
> persistenceUnitName;
>
>    try {
>        LOG.trace(String.format("Looking for EntityManager at %s",  
> lookupString));
>        em = (EntityManager) lookup(lookupString);
>    } catch (NamingException ex) {
>        LOG.error(String.format("An error occured while looking for  
> EntityManager at %s", lookupString), ex);
>        throw new ResourceNotFoundException("An error occured while  
> looking for EntityManager at %s", lookupString);
>    }
>
>    LOG.trace(String.format("Returning EntityManager %s", em));
>    return em;
> }
> ------------------------------------
>
> So as you can see, I could lookup different entityManagers by their  
> persistenceUnitName through JNDI.
> Is there anything similar, how this can be done using openEJB?
>
> I saw solutions how the entityManager is obtained through a  
> SessionBean after it has been deployed and the EM has been injected.
> But this can only be a work-around to me, as I see no chance with  
> handling different entityManagers with different persistence-units.

Hi Thomas,

We actually do have something similar internally, but the trick is  
that persistence unit names are not required to be unique outside the  
persistence.xml file (i.e. it's legal to have multiple persistence.xml  
files in various modules in your app all with the same name despite  
that they are different persistence units).  So currently we generate  
an id for the persistence.xml file itself and tack that on to the end  
of the persistence unit name before registering it in JNDI. The format  
is:

  "java:openejb/PersistenceUnit/" + unitName + " " + id

The id is a hashCode we generate to identify the exact persistence.xml  
file.

This is more for our purposes internally, but it is possible to get a  
list of them outside an EJB or Servlet.  Inside a Servlet or EJB you  
don't currently have access to java:openejb though we plan to add that.

Here's a small example:

The persistence.xml file

   <persistence xmlns="http://java.sun.com/xml/ns/persistence"  
version="1.0">
     <persistence-unit name="orange-unit">
       <jta-data-source>Orange</jta-data-source>
       <non-jta-data-source>OrangeUnmanagedamanged</non-jta-data-source>
     </persistence-unit>
     <persistence-unit name="lime-unit">
       <jta-data-source>Lime</jta-data-source>
       <non-jta-data-source>LimeUnmanagedamanged</non-jta-data-source>
     </persistence-unit>
   </persistence>

If you executed code like this in your test case:

     // Do not pass in LocalInitialContextFactory
     Context context = new InitialContext();

     context = (Context) context.lookup("java:openejb/PersistenceUnit");

     Map<String,Object> map = Debug.contextToMap(context);
     for (String key : map.keySet()) {
         System.out.println(key);
     }

You see this in the output:

    "lime-unit 3506402"
    "orange-unit 3506402"

Looking up these will give you the internal EntityManagerFactory we  
use to create the various EntityManager instances at runtime (i.e.  
transaction start for TRANSACTION scope or stateful session bean  
creation for EXTENDED scope).

Note the "Debug.contextToMap" call is just you standard iterate over  
JNDI code. Here it is if you want it:

     public static Map<String,Object> contextToMap(Context context)  
throws NamingException {
         Map<String, Object> map = new TreeMap<String,  
Object>(String.CASE_INSENSITIVE_ORDER);
         contextToMap(context, "", map);
         return map;
     }

     public static void contextToMap(Context context, String baseName,  
Map<String,Object> results) throws NamingException {
         NamingEnumeration<Binding> namingEnumeration =  
context.listBindings("");
         while (namingEnumeration.hasMoreElements()) {
             Binding binding = namingEnumeration.nextElement();
             String name = binding.getName();
             String fullName = baseName + name;
             Object object = binding.getObject();
             results.put(fullName, object);
             if (object instanceof Context) {
                 contextToMap((Context) object, fullName + "/",  
results);
             }
         }
     }

Further note to future readers who might want to iterate over the  
entire java:openejb tree.  Caution should be used with the  
java:openejb/ejb/, java:openejb/Deployment/, and java:openejb/client/  
sections of the tree as they will contain any Stateful session bean's  
you have in your platform and calling "binding.getObject()" on those  
will cause stateful session bean instances to be created.

In terms of future functionality, we would like to provide an  
alternate JNDI view of the persistence units that doesn't involve the  
unique ID and simply is "unit name".

-David




Mime
View raw message