1 2 3 Previous Next 33 Replies Latest reply on Jan 6, 2006 3:50 AM by boby Go to original post
      • 15. Re: Multiple databases - one entity bean class
        donniedarko

        Yes but when would this JNDI entry be registered?

        Sorry for bothering you time after time but if I havent misunderstood it's the actual @PersistenceContext annotation that does the registration of the JNDI entry?
        And one cannot use a attribute-less @PersistenceContext when using multiple EM's - hence the JNDi entry must be registered by something else (my wild guess the persistence.xml interpreter at doploy time)?
        And then in the code one could do a JNDI lookup without the use of @PersistenceContext annotation to find the EM based on a name supplied by the caller or some other smart enhancement that does not make it nessesary to hard code the attributes to @PersistenceContext.

        • 16. Re: Multiple databases - one entity bean class
          elkner

           

          "kabir.khan@jboss.com" wrote:
          I think this is the (missing) bit of functionality you're after. http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3883141#3883141

          Should be there in the final release


          I think, we miss something like http://www.jboss.org/index.html?module=bb&op=viewtopic&t=66013

          • 17. Re: Multiple databases - one entity bean class
            donniedarko

            We need that as well...but that won't solve the issue of this thread since one still cannot specify "name" of the EM dynamically for a container managed app.

            I've studied the spec thoroughly now to see if I could use the EntityManagerFactory and pass the "name" to it at runtime, but all the examples (se chapter 5.5.1 to 5.5.6) and all the descriptions only shows this approach for application managed persistence outside of the app server :-(

            All the container managed persistence examples that uses the EntityManagerFactory uses injection with annotations and hence - impossible to send in name as a variable.

            I even tried coding an app which has a service that during startup loads mappings between the names declared in the persistence.xml's and user defined names into a hashmap. One can after that always on the fly get the apropriate entity manager name from that service based on what the caller sends in. I then used the "out of container"

             EntityManagerFactory emf = Persistence.createEntityManagerFactory(strCallerPassedNameOfEntityManager);
            
             EntityManager em = emf.createEntityManager();
            

            from within my session bean which actually finds the entitymanager but throws an exception about that one must specify all values explicitly in the xml - an error I believe is related to that this approach is not ment to be used within the container since I get the error even if I specify class values in persistence.xml.

            I believe the spec actually is not covering this issue today - the possibility to create an EM based on a name specified at runtime. It covers the fact that one should be able to get it through JNDI lookup and this would solve it if one wouldn't have to specify @PersistenceContext with unitName / name to make it availbale in the JNDI i.e the JNDI entries would have to be available at deployment time of the persistence.xml's.

            Anyone that knows of a smart workaround?

            • 18. Re: Multiple databases - one entity bean class
              bill.burke

              Eventually we'll have a global JNDI lookup and/or XML injection. So why do you keep harping on this? It is not that big of a deal....

              In the meantime, why don't you just create a Session bean that implements the locator pattern?

              @Stateless
              public class EMLocatorBean implements EMLocatorLocal {
               @PersistenceContext(...)
               EntityManager em1;
              
               @PersistenceContext(...)
               EntityManager em2;
              
               public EntityManager getEntityManager(String name) {
               if (name.equals("EM1")) return em1;
               ...etc...
               }
              }
              


              Then, when the global JNDI lookup is done, you can just rewrite the EMLocatorBean to be more generic.

              • 19. Re: Multiple databases - one entity bean class
                donniedarko

                Sorry but I was "harping" because this is a forum and because I wanted to have a discussion that got me the following answer:

                http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3884496#3884496

                which actually solved the "select entity manager at runtime" issue.

                When the next release comes with the persistence.xml's "reference" (<jar-file> and ) functionality implemented - the issue that one must have the same entity bean within several .par archives are also covered :-)

                Best regards

                • 20. Re: Multiple databases - one entity bean class
                  zorzella

                  Jon,

                  thanks for pointing me to this post. I also have the same need: add DataSources at runtime (rather than at compilation, like the examples show), and also not have to repackage my ear file for that.

                  If you come accross a good (or any!) solution to this, please post!!!!

                  Also let me know if there's a bug opened (that I can vote for) to have this on the radar screen...

                  Zorzella

                  • 21. Re: Multiple databases - one entity bean class
                    zorzella

                    Sorry for my prior reply: I somehow missed the last post which seems to have a solution for runtime-selecting the EM.

                    As for the procedure to deploy, does one need to repackage the .par file with all the same beans and a new persistence.xml that points to different data source, and declares an entity manager with a different name? And then one would use that code snippet to choose the EM based on the name?

                    Is that it?

                    Thanks,

                    Zorzella

                    • 22. Re: Multiple databases - one entity bean class
                      donniedarko

                      Well yes...In my case. I coded a service bean (clustered singleton) which sort of "loads" my own xml mapping file of sitenames (key) and entitymanager names (value) into a thread safe Properties object in memory.
                      This service bean is accessible from all my session beans.
                      Each time I want to add a new site (read database) I do that in the service beans management interface through the JMX console at runtime (it stores another key/value in my xml mapping file and in the in memory Properties object).

                      Then for each table I have an entitybean. Although it is actually the same bean for all the corresponding tables within the different site's databases.

                      The session bean that calls the entity bean has no @PersistanceContext or similar code , but it calls the service bean with the callers sitename to get the entitymanager name from its in memory "mapping".
                      Then it calls a method similar to the one posted by triathlon98 to lookup the actual entity manager based on the name recived from the service bean at runtime.

                      This way the only thing I have to do to add a new database and make my solution work without any coding / recompiling etc is that i deploy a .par with a new persistence.xml (could also be programmaticly automated) and then I register it in JMX console through my service bean.

                      The only thing that is still a bit clumpsy is that it seems to me that until the "jar-file" and "class" functionalities of the persistence.xml files are implemented, there is no way to have the single entity bean packaged and deployed only once. Hence, one has to copy the entity class file into all the .pars that is about to use it rather than just referencing to it which in the future will be possible.
                      Let me know if you find a better solution for this.

                      Good luck.


                      • 23. Re: Multiple databases - one entity bean class
                        zorzella

                        I had pretty much the same design in mind, though I'm thinking on having a "master" datasource, with a single table doing the job of your Properties file.

                        Anyway, thanks for all the info. Let us know when/if you ever get the jar ref working (i.e. after it's implemented, of course).

                        Zorzella

                        • 24. Re: Multiple databases - one entity bean class
                          pesalomo

                          OK, there's been a lot to this thread - and I think most of us have managed to find a way of doing this. Just want to wrap things up, and come with some design proposals before the public review closes:

                          According to the spec - this is the way to do dynamic entitymanager lookup:

                          @Stateless
                          @PersistenceContexts({
                          @PersistenceContext(name="db1",unitName="entitymanager1")
                          @PersistenceContext(name="db2",unitName="entitymanager2")
                          })
                          public class EntityManagerStoreBean implements EntityManagerStore {
                           @Resource
                           SessionContext ctx;
                          
                           public EntityManager getEntityManager(String entityManagerName)
                           {
                           return (EntityManager)ctx.lookup(entityManagerName);
                           }
                          }
                          


                          This works ok, but in addition to declaring your entitymanagers in persistence.xml, you'll have to redeclare a reference using the PersistenceContext annotation. A JBoss specific hack to avoid this is the following:

                          public EntityManager getEntityManager(String unit)
                          {
                           Object obj = ctx.lookup( "java:managedEntityFactory." + unit );
                           return ( (org.jboss.ejb3.entity.ManagedEntityManagerFactory) obj ).getSession();
                          }
                          
                          
                          But this is not platform independent, and you're outside the spec - but it's a pure dynamic way to get your entitymanager.

                          Some would say that declaring references (as done using the spec way), is neccesary for dependency injection, and will also indicate reference errors on deploy time. However the entitymanagers are already registered by the deployment of par files - and should therefore be accessible without this reference. And secondly, why should we have to use JNDI lookup?

                          I'd propose adding a static method to the EntityManager class, so that we could dynamically get entitymanagers like this:

                          EntityManager em = EntityManager.getEntityManager("MyEntityManager");


                          That's for the lookup issue. As for the packaging issue - the spec is ok, a nice feature though would be if you could specify multiple entitymanagers in one persistence.xml file (one par archive). It would be very useful for the scenario when you're using the same entity-bean set for multiple datasources:

                          <entity-managers>
                           <jar-file>myEntities.jar</jar-file>
                           <entity-manager>
                           <name>MyDB</name>
                           <jta-data-source>java:MyDBDS</jta-data-source>
                           </entity-manager>
                           <entity-manager>
                           <name>MyDB2</name>
                           <jta-data-source>java:MyDBDS2</jta-data-source>
                           </entity-manager>
                          </entity-managers>
                          


                          I'll copy Sun on this as these are specification design issues. Think it is important to at least bring this up before the review closes.

                          Peter

                          • 25. Re: Multiple databases - one entity bean class
                            bill.burke

                            I will be adding a global jndi lookup for managed EntityManagers, managed EntityManagerFactory's. This should solve your problems.

                            The EntityManager.xxx is non viable as EntityManager is and should stay an interface.

                            the javax.persistence.Persistence class gives that capability but it really should only be used outside of the container as the EntityManager's created will not be managed by the app server.

                            • 26. Re: Multiple databases - one entity bean class
                              ryoung2504

                              I can obtain an EntityManager dynamically using the above techniques but whichever technique I use I can't cast the resultant EntityManager to a org.jboss.ejb3.entity.HibernateSession.

                              Is there a way to get hold of an EntityManager dynamically that will cast to a HibernateSession (as described in the Hibernate Integration document (chap 2))?

                              • 27. Re: Multiple databases - one entity bean class
                                bill.burke

                                Look in the docbook.

                                http://docs.jboss.com/ejb3/reference/build/reference/en/html/hibernate.html

                                The next release I will allow the direct injection of Hibernate Session and SessionFactory. These will be proxies to the real deal and work the same way as container managed EntityManagers and ENtityManagerFactories.

                                • 28. Re: Multiple databases - one entity bean class
                                  ryoung2504

                                  Unfortunately when obtaining an EntityManager using

                                  Object obj = ctx.lookup("java:managedEntityFactory." + unit);
                                  the object doesnt cast to a HibernateSession whereas
                                  @PersistenceContext
                                  private EntityManager manager;
                                  does



                                  • 29. Re: Multiple databases - one entity bean class
                                    bill.burke

                                    That's because "java:/managedEntityFactory...." is for INTERNAL USE ONLY!

                                    The next release will provide a way to lookup ENtityManager, ENtityManagerFactory in global JNDI.