[JPA_SPEC-17] Dynamic persistence unit Created: 01/Apr/12  Updated: 11/Nov/13

Status: Open
Project: jpa-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: likenootherufo Assignee: ldemichiel
Resolution: Unresolved Votes: 7
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: JavaEE, dynamicaly, persistence

 Description   

Without changing code and redeploying my application, I need to be able to switch persistence units in some of my EJBs based on client connected to system.
It is similar to multitenancy, but whereas there a single DB is divided into equal shares and shared between multiple tenants, here a single tenant wants multiple DBs appearing as a single one.
During runtime based on the client connected to the EJB, the specific database should be selected.
Currently I achieve this using JDBC connections and just changing the database connection details based on client connected.
The database connection details are stored in the main system database and retrieved when the client connects.
This allows the system to grow with ease as new client databases can be created on the fly and simply linked to the client
in the database.
Ideally I would like to dynamically add new persistence units to the system (persistence.xml) and then in my database
link these persistence units to a given client. When the client connects, the system loads the required persistence unit.



 Comments   
Comment by ldemichiel [ 22/Feb/13 ]

I think you are really asking for multitenancy support in Java EE, which is something that we don't yet support. This is a candidate item for Java EE 8, at which point we should revisit this issue for JPA.

Comment by c.beikov [ 24/Apr/13 ]

This would be something really nice to have but I also think that this is already possible.
You coud have e.g. a CDI producer for the EntityManager which returns a proxy that is actually capable of that switching.
This is really nice, I think I will implement this in my application too

public class EnvironmentAwareEntityManager implements EntityManager {

  @Inject
  @Any
  private Instance<EntityManager> ems;

  private EntityManager select(){
    for(EntityManager em : ems) {
      if(!(em instanceof EnvironmentAwareEntityManager)) {
        // Do your selection based on your needs
      }
    }
  }

  // ... delegate all calls to the result of select()
}
Comment by arjan tijms [ 24/Apr/13 ]

@c.beikov

With that method, how would you actually add a new persistence unit at runtime, or alternatively let an existing persistence unit point to a different database?

Comment by c.beikov [ 24/Apr/13 ]

Adding a new persistence unit is kind of tricky with the current state of the API. This is currently only possible my managing the EMFs within the application but you probably also have to depend on some code of the underlying persistence provider to do the dynamic configuration of the EMF. Transaction Management and so on could be handeled by using the new transaction interceptors of Java EE 7(at least I think that it would be possible, not sure about that). It is possible but not entirely with the standards provided by JPA.

The requirement was to switch PUs but not the underlying datasource of a PU. So when you know at deployment time what PUs you have you can do it like that.

I could still think of something else, but this is probably the worst solution. You could set a comment hint on every query you execute, let the address of the PUs database point to a proxy that does the selection by inspecting the comments.

Comment by jbsmathers [ 11/Nov/13 ]

This would allow the end user to make new db connections, and that would add a variety of functionalities not currently available in jee without redeployment. I have wondered about this since JEE5 and unless there are excellent reasons not to do it, I hope its in jee8.

Generated at Mon Aug 31 23:23:18 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.