persistence@glassfish.java.net

Re: can you set the persistence-unit data-source at runtime?

From: Nitin Nahata <nitin.nahata_at_gmail.com>
Date: Tue, 24 Oct 2006 00:08:08 -0700

Hi Sahoo,

thanks for the detailed response.

The user would/could know the JNDI data-source name at deployment
time. But having to unjar the application war, edit persistence.xml
and re-jar before deploying, is a complicated cycle which users would
not want to go through. Atleast not in my case.

> An emf is bound to one data-source because an emf produces homogeneous
> entity managers. When the factory is created, it is already configured
> with a data-source.

agreed. But does this binding have to mandatorily happen at
deploy/start time only? Wouldn't the following be more flexible (and
therefore more powerful):

If the data-source is set in persistence.xml, fine, create the emf
bound to that data-source while application is getting started. If
not, delay the data-source binding until a call to setDataSource(ds)
is made. After a ds is successfully bound, fail any future calls to
setDataSource(ds) with an exception. That way the emf would still
return homogenous entity-managers bound to the same data-source. And
the programmer would have more choice.

Thanks,
Nitin

On 10/20/06, Sanjeeb Kumar Sahoo <Sanjeeb.Sahoo_at_sun.com> wrote:
> data-source name is not needed at compile time. You can edit it just
> before deployment step. If you don't know the data-source name until run
> time, then too late. It's a different matter that some appserver may not
> have a deployment tool to edit the persistence.xml.
>
> By the way, even if there were an API to set DataSource in
> EntityManagerFactory, how would you have called that API with a
> data-source? To call that API, you need a data-source which you can
> obtain only by looking up JNDI tree. Are you saying that your
> application gets the JNDI name from user at runtime. Why can't you know
> the JDNI name at deployment time?
>
> Now coming to the rational behind why data-source is used in
> persistence.xml:
> Unlike web app or EJB, a persistence unit is not a component by itself
> and hence it does not have a naming environment of its own. More over,
> since some persistence units can be shared by multiple components, they
> can't assume that they have a unique naming environment. So, you have to
> use the actual JNDI name of the datasource in persistence.xml. But,
> actually, that is not that bad. Even if you were allowed to specify a
> resource-ref-name as opposed to specifying the actual resource-name, you
> any way had to bind the resource-ref to an actual resource at deployment
> time, right? So, I don't understand how any dependency injection would
> have helped because injected resource is resolved at application
> deployment/load time.
>
> An emf is bound to one data-source because an emf produces homogeneous
> entity managers. When the factory is created, it is already configured
> with a data-source. After that each em produced by the emf will connect
> to the same data-source. Hence, user is not be allowed to call
> emf.setDataSource() or emf.createEntityManager(DataSource ds).
>
> I don't understand why you can't know the data source name at deployment
> time. If you really want to decide which database to connect at runtime,
> then explore the option of creating EMF using
> Persistence.createEntityManagerfactory(emfName, properties). You can
> specify the JDBC connection URL in the properties, but your app will
> have to rely on vendor specific property.
>
> Thanks,
> Sahoo
>
> Nitin Nahata wrote:
> > I have a web application that needs to talk to a particular JDBC
> > data-source registered in the appserver JNDI tree. But my application
> > does not know the JNDI-name of this data-source until after the app
> > has been deployed and started.
> >
> > So I cannot set the correct value for the <jta-data-source> element in
> > persistence.xml while building the application. I would like to be
> > able to "inject" it at runtime.
> >
> > I am not aware of the implementation details but I guess one way to do
> > this could have been to have below methods in
> > javax.persistence.EntityManagerFactory:
> >
> > 1. setDataSource( javax.sql.DataSource ds ) or
> > 2. createEntityManager( javax.sql.DataSource ds )
> > 3. or both 1 and 2
> >
> > Which would let you have code like below:
> >
> > public class AController {
> >
> > @PersistenceUnit(unitName = "myPU")
> > private EntityManagerFactory emf;
> >
> > //constructor
> > AController( javax.sql.DataSource ds ) {
> > emf.setDataSource( javax.sql.DataSource ds );
> > }
> >
> > private EntityManager getEntityManager( ) {
> > return emf.createEntityManager();
> > }
> >
> > public List<A> getAll() {
> > EntityManager em = getEntityManager();
> > ....
> > ....
> > }
> >
> > }
> >
> > But since I dont see the above methods in the api, I was wondering if
> > there is some other way to achieve this?
> >
> > Thanks
> > Nitin
> >
> >
> >
> >
> > On 10/20/06, Marina Vatkina <Marina.Vatkina_at_sun.com> wrote:
> >> Hi Nitin,
> >>
> >> Can you be a bit more specific at what are you trying to accomplish?
> >>
> >> thanks,
> >> -marina
> >>
> >> Nitin Nahata wrote:
> >> > data-source for a persistence-unit is set in the persistence.xml file.
> >> > Which means that it should be known at compile time.
> >> >
> >> > Is there a way to set the data-source at runtime instead?
> >> >
> >> > Thanks
> >> > Nitin
> >>
> >>
>