Externalising persistence.xml properties in Glassfish?

#1

Hi,

  I've run into a little bit of a wall with regards to persistence.xml and externalising the URL for the database. You see I'm trying to create a 'server' and be able to have the datasource 'javax.persistence.jdbc.url' be supplied by the server. Currently, I'm doing all sorts of tricks with maven and file copying to get around it but so far it hasn't been a good solution for me as I have many modules (hence, many persistence-units). I realise that it can be a limitation stemming from JPA itself and no formal standard for externalising properties (hence why they appear to be relying on JNDI lookups).

I am using Glassfish. Basically, what I am trying to get at:

E.g. persistence.xml

<persistence-unit name="invoicingTxUnit" transaction-type="JTA">

        <provider>x.y.z.ObjectDbJPAMockProvider</provider>
        <jta-data-source>jdbc/jpaProviderMockPool</jta-data-source>
        <properties>
         <!--
        
          TODO: I would like at all costs not to have any URL or AUTH info here - so that it will depend on my

          dev/test/production environments without me having to edit manually prior deployment or rely on build scripts
        
         -->
        </properties>       

</persistence-unit>

So, anyone encounter any tutorials for handling multi-environment (dev/test/prod), multi-module deployments with ObjectDB as the datastore either with Glassfish/JBoss and having environment specific datastore properties being build independent?

I can solve the issue for PostgreSQL/mySQL and traditional DB's through the container.

Thanks for your time!

#2

Hello,

Why dont you create multiple  presistance units in the persistance.xml and that way you can externalize the persistance unit name and you can easily get that to your ejb. That is the easiest solution.  Another way might be by setting a system variable with the url and another one with the creadentials. If i recall correctly the application should be able to pick them up if you give the place holder. I know I have tried this in the application.xml  and I dont see why it wont work for the persitance   unit.

 

Erick

#3

Could you please describe the exact way that you could use to solve this issue with PostgreSQL / MySQL?

It might be possible to add the same support to ObjectDB.

ObjectDB Support
#4

Well this should do the trick.

in your persistance.xml use placeholders for the data you want. In this example I have the place holder Source.

<persistence>
<persistence-unit name="PU">

<jta-data-source>${Source}</jta-data-source>

</persistence-unit>
</persistence>

Then in your server config you define every property as an argument to the JVM like this

 -dSource=someValue

I dont know what app server you are using  but you should easily be able to find the start up script. This is the same place where heap size ect gets set.

 

My other option is to have  your properties in a property file somewhere and have a method that will read in environment.

say for example  property pu=DEVPU  and I set a static string variable name PERSISTANCEUNIT with the property value.

In your persistance.xml define a persitance unit for every environment you want that has unique configuration and be sure to give it a name, this is a requirement if more than one persistance units exist.

Then in the code i can use

@PersistenceContext(unitName=PERSISTANCEUNIT)
private EntityManager em;

This way I can use the same code in any environment. The set up of the properties should be a one time deal.

 

I hope this answers your question. I am not sure how this is strictly PostgreSQL / MySQL question, it seemed more like a general question. Let me know if you need more clarification on what I am talking about I can write up an example if you still have problems.

 

Erick

#5

Hi again,

  Thanks for the replies. Sorry, I should have highlighted the fact that the only reason I solved the PG/mySQL one is because the app server provides the ability to have a connection pool setup to the database - aka a managed pool. In Glassfish, setting up this pool is like this (domain.xml):

 

    <jdbc-connection-pool driver-classname="" pool-resize-quantity="10" datasource-classname="org.postgresql.ds.PGSimpleDataSource" max-pool-size="20" res-type="javax.sql.DataSource" steady-pool-size="10" description="" name="pgsqlPool">
      <property name="User" value="inv_usr"></property>
      <property name="DatabaseName" value="invoice_db"></property>
      <property name="LogLevel" value="0"></property>
      <property name="Password" value="xx_yy_zz"></property>
      <property name="ServerName" value="localhost"></property>
      <property name="Ssl" value="false"></property>
      <property name="ProtocolVersion" value="0"></property>
      <property name="TcpKeepAlive" value="false"></property>
      <property name="SocketTimeout" value="0"></property>
      <property name="PortNumber" value="5432"></property>
      <property name="LoginTimeout" value="0"></property>
      <property name="PrepareThreshold" value="5"></property>
    </jdbc-connection-pool>
    <jdbc-resource pool-name="pgsqlPool" description="" jndi-name="jdbc/pgsqlPool"></jdbc-resource>

So, the persistence.xml (for postgres), would look as (using eclipse link)

    <persistence-unit name="invoicingTxUnit" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/pgsqlPool</jta-data-source>
        <properties>
            <property name="eclipselink.logging.level" value="INFO"/>
        </properties>
    </persistence-unit>

 

So, if ObjectDB had a 'PGSimpleDataSource' equivalent class that the whole issue could be delegated to the container?

I'm concurrently developing actively with ObjectDB but also using PostgreSQL warehousing bulk data that is perceived to be seldomly used. Also, I'm using it to ensure my domain model is also relevant in the relational world - as ObjectDB makes it so easy to progress quickly without getting bogged down without relational considerations (e.g. foreign keys and join column names etc etc). So, as I progress from testing locally to my test environment in Glassfish 3.1 - the environment already is set up with the Postgres jta-data-source, so the persistence.xml is environment agnostic (the persistence-unit just references the JNDI name for the pool). The only difference is that I have to modify my main persistence unit in persistence.xml which point to my shared object db development instance. I do this manually but I have a half-working maven script that I use to create my artifacts.

 

Erick, thanks for your suggestions. I'll look into that now. I'm using EJB3.1, JPA2 on Glassfish 3.1. The solution you mentioned is something I'll look into - my maven resource copying is a little flaky and I'd prefer a build independent way of resolving the DB instance. I didn't realise we could have placeholders in persistence.xml and have the container resolve these!

Thanks again.

 

Will

#6

Maybe ObjectDB can use JNDI to convert jdbc/pgsqlPool to a database url, user and password. i.e. to use the jta-data-source value when specified (currently it is ignored).

If you can provide a JNDI code that extracts these values in GlassFish - I can try integrating it into ObjectDB.

ObjectDB Support

Reply