4 Replies Latest reply on Jul 4, 2013 3:48 PM by Edilmar Alves

    Is it possible to have a "dynamic" @PersistenceContext?

    Edilmar Alves Expert

      Hi,

       

      I have a webapp using GlassFish3.1.1 + JSF2.1 + RichFaces4.3.2 + CDI/Weld + CODI + JPA2 + Hibernate4.2.2 + Firebird.

      I use also JTA (database connection injection from GlassFish).

       

      I need to install many clients with separate databases in a cloud server. My actual solution is to deploy 1 webapp per client.

      Each webapp consumes +/- 300 Mb of RAM. Then, if I have a cloud server with 2 Gb, I get to deploy 5 webapps.

       

      I would like to deploy just one webapp, and, after "an analysis of the user to log on", to use the database of his enterprise.

      Then, I would have much more clients than actual 5.

       

      My solution can't use some kind of multitenancy, because each client must have a separate database, it's a major pre-requisite.

       

      My big problem is @PersistenceContext(unitName="XXX"), because XXX is defined statically, I don't get to change XXX after

      "an analysis of the user to log on".

       

      Is there some way to do this?

        • 1. Re: Is it possible to have a "dynamic" @PersistenceContext?
          Andrei Tognolo Newbie

          Hi Edilmar,

          My solution can't use some kind of multitenancy, because each client must have a separate database, it's a major pre-requisite.

           

          If I'm not wrong, you can use the "Separate Database" approach of Hibernate Multi-tenancy (http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch16.html#d5e4570). What do you think about use this approach?

           

          My big problem is @PersistenceContext(unitName="XXX"), because XXX is defined statically, I don't get to change XXX after

          "an analysis of the user to log on".

           

          I believe that there's no way to do it. But, even if you had a way to dynamic define, you still have the problem of dynamic configure multiples persistence-unit in your persistence.xml, and I don't know how to solve without Hibernate Multi-tenancy.

          • 2. Re: Is it possible to have a "dynamic" @PersistenceContext?
            Rafael Pestano Novice

            Never used Hibernate multitenancy but if you cant use it there is always the brute force way, maybe it helps:

             

            public class EntityManagerProvider {

             

                @PersistenceContext(unitName = "unit1")

                EntityManager em1;

             

                @PersistenceContext(unitName = "unit2")

                EntityManager em2;

             

                @PersistenceContext(unitName = "unit3")

                EntityManager em3;

             

                @Inject User user;

             

             

                public EntityManager getCurrentEntityManager(){

                    if(user.somePropertyThatIdentifiesItsDatabase == 'database1'){

                      return em1;

                    }

                    else if(user.somePropertyThatIdentifiesItsDatabase == 'database2'){

                         return em2;

                    }

                    //and so on

                }

            }

             

             

            @Stateless

            public class MyService{

                @Inject EntityManagerProvider entityManagerProvider;

             

                EntityManager em;

             

                @PostContruct

                public void initEntityManager(){

                    this.em = entityManagerProvider.getCurrentEntityManager();

                }

            }

            • 3. Re: Is it possible to have a "dynamic" @PersistenceContext?
              Edilmar Alves Expert

              Andrei,

               

              I think the unique alternative for this is to create many EntityManagers injected just commented by Rafael.

              This is a very ugly solution, because each time a new database is created for a client, I have to change the code and persistence.xml.

              Multitenancy with separate databases also doesn't work because I have the same problem to inject the databases.

               

              I would like something like this in my DAO but I know today CDI/Weld doesn't have a way to inject an object into a method:

               

              public class MyDAO implements MyInterfaceDAO {

                EntityManager em;

                @PostConstruct

                public void initDAO() {

                  User user = getUserFromSessionAttribute(); // a method to access the session

                  if(user.somePropertyThatIdentifiesItsDatabase == 'database1') {

                    @PersistenceContext(unitName = "pu1") EntityManager em1;

                    em = em1;

                  }

                  else if(user.somePropertyThatIdentifiesItsDatabase == 'database2') {

                    @PersistenceContext(unitName = "pu2") EntityManager em2;

                    em = em2;

                  }
                  // etc...

                }

              }