1 2 3 Previous Next 33 Replies Latest reply on Jan 6, 2006 3:50 AM by boby

    Multiple databases - one entity bean class

    pesalomo

      I need to solve the following scenario:

      I have a web server hosting several web sites with seperate databases. Each database has however the same structure (exactly the same tables and fields) - and therefore it makes sense to use the same entity bean for each database.

      In my session beans I would prefer writing my code like this to choose the right entitymanager for the database:

      HashMap<String,EntityManager> entityManagers;

      WebPage page = new WebPage();
      page.setHtml("blablabla");
      entityManager(hostName).persist(page);

      In this example WebPage is the entity bean, and the hostName is the current www-hostname from the servlet/ejb-context.

      By doing it this way, I don´t have to hardcode references between databases and websites in my ejb source code. I would also have only one set of entity bean source code to access multiple databases of the same structure.

      I cannot see that this approach is described in the EJB3 tutorial. Maybe by creating an EntityManagerFactory, but the tutorial don´t really promote that way. You don´t want to end up having several .par archives holding the same entity bean classes. Is it possible to do this? Will it be, at least in a similar fashion? If not, I would strongly request this as a new feature.. This scenario with these needs I see over and over again.

      Regards,

      Peter Salomonsen

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

          I have the exact same issue. I have several databases with the exact same structures, and have ended up with several entity beans that does the exact same thing in different .pars which i find very clumpsy.
          In my case i want to code a service pojo or similar (singleton) which i can have a @Management interface that administrates a collection of enittymanagers within a hashmap with a string as key.
          Then I could have a session bean that got a entitymanager from the service bean by string - hence solving the same issue as described above.
          But again i cant see a way doing it with the use of

           @PersistenceContext(unitName="mymanager") EntityManager manager;
          

          or similiar. And as said before the use of EntityManagerFactory is discouraged to be used in this way by the tutorial.


          • 2. Re: Multiple databases - one entity bean class
            epbernard

            Create several pars and use
            my.entuty.Bean to reference your *external* entities.
            This way no need to dupe your entities.

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

              To be sure I got your point - do you mean that I create for instance one archive where the entity bean definition classes are - and then several .pars which all references to the same entity bean?

              How would you actually to the reference the beans from the par files? By creating "wrapper" classes extending the entity bean classes? I didn´t quite understand this.

              Thanks,

              Peter

              "epbernard" wrote:
              Create several pars and use
              <class>my.entuty.Bean</class> to reference your *external* entities.
              This way no need to dupe your entities.


              • 4. Re: Multiple databases - one entity bean class
                kabirkhan

                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

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

                  You mean, that how it´s supposed to be - is that I should be able to deploy my entity beans in a EJB jar - without persistence.xml - and then I could deploy several pars with persistence.xml mapping to different databases - and then one and the same entity bean will map to all these databases?

                  Peter

                  • 6. Re: Multiple databases - one entity bean class
                    epbernard

                    Do n .par let's say empty (ie no class)
                    and in each persistence.xml use
                    my.shared.EntityBean1
                    my.shared.EntityBean2
                    to explicitly declare your classes. No need for any wrapper class.

                    It's more convinient with <jar-file>, but you can achieve that already.

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

                      Ok I see...
                      That should solve the part of the issue that involves having one entity bean match several identic tables, but I can't see how it solves my inital posts issue on how to actually choose an entity manager without hardcoding?

                      What I want to achieve there is to be able to choose one of the registered enity managers at runtime, without using the UnitManagerFactory which is discouraged by the tutorial in this kind of usage.

                      Best Regards
                      Jon Åkerström

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

                         

                        "donniedarko" wrote:
                        Ok I see...
                        That should solve the part of the issue that involves having one entity bean match several identic tables, but I can't see how it solves my inital posts issue on how to actually choose an entity manager without hardcoding?



                        Look up an EntityManager within JNDI. Is you specify the name() attribute in the PersistenceContext annotation, the EntityManager is available under the EJB's ENC. (if you don't specify a name() it is under the name of the field or setter method). Unfortunately, there is no XML yet defined in the EJB3 schema to inject an entity manager from a deployment descriptor. So you could do this instead:

                        
                        @PersistenceContexts({
                         @PersistenceContext(name="em1", unitName="cust1DB"),
                         @PersistenceContext(name="em2", unitName="cust2DB")
                        })
                        @Stateless
                        public class MyDAOBean implements MyDAO {
                         @Resource SessionContext ctx;
                        
                         private EntityManager getEntityManager(String unit) {
                         String enc = org.jboss.ejb3.Container.ENC_CTX_NAME + "/env/" + unit;
                         return (EntityManager)ctx.lookup(enc);
                         }
                        
                         public Customer getCustomer(int id, String unitName) {
                         return getEntityManager(unitName).find(Customer.class, id);
                         }
                        }
                        


                        You have to use the ENC context stated above because we still have to integrate the new ENC refactoring we did in JBoss Head into JB4. Otherwise the constant would be "java:comp" rather than "java:comp.ejb3". Get me?

                        Another pattern you could use is the following.

                        public abstract class MyBaseDAO {
                        
                         public abstract EntityManager getEntityManager();
                        
                         public Customer getCustomer(int id) {
                         return getEntityManager().find(Customer.class, id);
                         }
                        ...
                        }
                        
                        @Stateless
                        public class Cust1DAO extends MyBaseDAO implements MyDAO {
                        
                         @PersistenceContext(name="em1", unitName="cust1DB")
                         private EntityManager em1;
                        
                         public EntityManager getEntityManager() { return em1; }
                        
                        }
                        
                        
                        @Stateless
                        public class Cust2DAO extends MyBaseDAO implements MyDAO {
                        
                         @PersistenceContext(name="em2", unitName="cust2DB")
                         private EntityManager em2;
                        
                         public EntityManager getEntityManager() { return em2; }
                        
                        }
                        
                        


                        Following me?


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

                          Yes I think I follow, and it solves again most of the issues i asume, but if I have not misunderstood your excellent examples I still would have to have
                          definitions of the enitity managers in the code like this one, wouldn't I?

                          @PersistenceContext(name="em1", unitName="cust1DB")
                          


                          What I really would like to do is to the declare the "linkage" to the enitymanagers defined in the persistence.xml's on the fly.
                          But maybe I can do that with your example by looking them up via JNDI since you are saying:



                          (if you don't specify a name() it is under the name of the field or setter method)


                          I.E I could declare just one "unnamed" entitymanager in the session bean

                          @PersistenceContext
                          EntityManager enitymanager;
                          

                          ???

                          And still use your concept of

                           private EntityManager getEntityManager(String unit) {
                           String enc = org.jboss.ejb3.Container.ENC_CTX_NAME + "/env/" + unit;
                           return (EntityManager)ctx.lookup(enc);
                           }
                          


                          getting the correct one? Is that possible?

                          My concern is that each time i register a new database and datasource (quite often in my case) I would have to edit the code in all the session beans and recompile my project and deploy.
                          I really want to be able to register new databases and datasources without having to change the code and recompile / deploy. Many of our customers have their own database, and having to add each new entitymanager in the code of virtually every session bean each time we get a new customer wouldn't really be a smooth operation.

                          Best regards
                          Jon Åkerström
                          http://www.lightminds.com

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

                            Hasn't anybody actually assigned entitymanagers "on the fly"?

                            I have encountered this issue twice already and I see several more cases when I will need to have a solution for this.

                            I did not manage to "find" the managers through the SessionContext lookup as you described when I used an "unnamed" entitymanager... Is that even possible?

                            Best regards
                            Jon Åkerström
                            http://www.lightminds.com

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

                              I answer my question myself. No it's not possible, since you can't even deploy if you have several entitymanagers declared and no unitName in your @PersistenceContext.

                              My suggestion is that this issue is addressed - since as far as I can see there is no way to have the code "clean" from hardcoded name or unitName parameters unless you only have one entitymanager - forcing us to modify/ recompile / deploy the code each time we want to add another entitymanager in our persistence.xml or datasource to our solution - even though its structure is the exact same?

                              I believe that many others will encounter the same issues, think of an ISP which has a phone sales department that want's to be able to set up web site customers on the fly. In this example each customer have their own database. Even though the database structure is the exact same for each customer one would have to go into the code and add the new unit managers in the session beans, then test it then deploy it etc...making the whole idea fall at once.
                              I can come up with a lot of other examples that will have to be able to reference to different entitymanagers based on a value that dynamically changes during runtime , rather than declared in the code.

                              Or is there a way?

                              Best regards
                              Jon Åkerström
                              http://www.lightminds.com

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

                                Will providing a global JNDI lookup of a container-managed EntityManager help for now until the spec defines the XML to inject EntityManagers into the EJB's ENC? I'll add this to JIRA.

                                Bill

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

                                  Anything that does not require one to declare the "link" between the session bean and the managers defined in the persistence.xml's as hardcoded values (as the @PersistenceContext requires today) in the session beans code would do it.

                                  Also a a global JNDI lookup of a container-managed EntityManager would mean that the JNDI entries would have to be registered by the persistence.xml's intepreter at deployment time wouldn't it? rather than with the @PersistenceContext(name="blah blah")?

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

                                    the name() attribute only specifies the ENC name of the EM/EMF.

                                    java:comp/"the name"

                                    1 2 3 Previous Next