persistence@glassfish.java.net

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

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Tue, 24 Oct 2006 19:19:42 -0700

Hi Nitin,

You can choose the datasource name and then create a resource later on
with this name. But the application is getting started when it's loaded
into an app server, so the datasource needs to be registered before
you deploy your app.

Does it make sense? If not, what is the exact problem that you are trying
to solve?

thanks,
-marina

Nitin Nahata wrote:
> 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
>> >>
>> >>
>>