10

I want to read environment variables inside persistence.xml file.

Idea is that i don't want my database details to be read from properties file as there is a change of getting properties file override.Instead i want to read details from environment variables.

Is there any way to achieve this criteria.

Iam using Spring 3 my standalone application will be deployed in unix machine.

Prathap
  • 1,023
  • 7
  • 19
  • 33
  • 2
    Database details like hostname shouldn't be defined in your persistence.xml. Use JNDI lookups and define concrete database parameters in your application server... – home Jan 12 '12 at 14:41
  • Hi,Sorry to mention that I am not using any application server here , i am running standalone application that's why i need to hard code database details in persistence.xml file. – Prathap Jan 12 '12 at 14:49
  • Do you want to get the database details from environment variables or from persistence.xml? It kind of looks like you're saying you want to get them from both but it's not totally clear... – Zack Macomber Jan 12 '12 at 14:56
  • 1
    @Rana: How exactly are you using EJB 3.0 in a standalone application (without any application server)? – Bhesh Gurung Jan 12 '12 at 14:58
  • 1
    @Rana: Ups, sorry, you should have mentioned that. EJB 3.0 w/o an application server is not that common... – home Jan 12 '12 at 15:00
  • @Zack : Hi, I want database details to be fetched from environment variables and those should be used in persistence.xml. For Ex:We use PropertyPlaceHolder to read properties file and use values directly $someKey} in our spring xml file like wise i want to read env variables in persistence.xml – Prathap Jan 12 '12 at 15:23
  • @ βнɛƨн Ǥʋяʋиɢ ,@home : Sorry iam not using EJB 3.0..its by mistake typo error. – Prathap Jan 12 '12 at 15:24

3 Answers3

20

You can update properties in a persistence unit by supplying a Map (see this).

Conveniently, environment variables can be retrieved as a Map (see this).

Put the two together and you can dynamically update properties in your persistence unit with environment variables.

EDIT: simple example...

persistence.xml...

<persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
    <provider>
        oracle.toplink.essentials.PersistenceProvider
    </provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="toplink.logging.level" value="INFO"/>
        <property name="toplink.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
        <property name="toplink.jdbc.url" value="jdbc:oracle:thin:@myhost:l521:MYSID"/>
        <property name="toplink.jdbc.password" value="tiger"/>
        <property name="toplink.jdbc.user" value="scott"/>
    </properties>
</persistence-unit>

code that updates persistence.xml "default" unit with environment variables...

Map<String, String> env = System.getenv();
Map<String, Object> configOverrides = new HashMap<String, Object>();
for (String envName : env.keySet()) {
    if (envName.contains("DB_USER")) {
        configOverrides.put("toplink.jdbc.user", env.get(envName)));    
    }
    // You can put more code in here to populate configOverrides...
}

EntityManagerFactory emf =
    Persistence.createEntityManagerFactory("default", configOverrides);
Zack Macomber
  • 6,682
  • 14
  • 57
  • 104
  • Hi Zack, Iam not sure how can i provide Map to persistence.xml .Can you provide some sample code for this. – Prathap Jan 13 '12 at 07:00
  • Example uploaded - i've been finding some good info by googling "persistence.xml" – Zack Macomber Jan 13 '12 at 10:48
  • Hi Zack, the above code requires me to override the env variables every time i create the the EntityManagerFactory object.In that case if i am using this EntityManagerFactory in 10 classes every where i need to change. – Prathap Jan 13 '12 at 11:46
  • In that case, you should use a single class that does the overriding. You could return an EntityManagerFactory from that one class to the 10 classes and only need to maintain one class for the override. – Zack Macomber Jan 13 '12 at 13:06
  • Thanks!I have implemented in the same way by overriding the properties. – Prathap Jan 18 '12 at 07:29
3

I don't think this will cover EMs created via injection. Worse, I think EMs created through EMF can only be EXTENDED (eg equivalent to the annotation @PersistenceContext(type = PersistenceContextType.TRANSACTION) opposed to EXTENDED) so that if one requires a transaction EM, one must use injection.

I'm wondering if its possible to physically rewrite the persistence.xml file at runtime. Problem one being, ability to rewrite the file (permissions, being able to get to it in META-INF etc), and second, rewriting it before its opened for the first time by JPA (which I thinking happens the first time an injected EM field is actually referenced by application code)

ajr
  • 31
  • 1
0

You could use this working example.

It gets all properties defined in the persistence.xml from the PersistenceUnitInfo instance which is obtained from the EntityManagerFactory (by using eclipseLink specific implementations). These properties get replaced with the values defined in environment variables.

baumato
  • 358
  • 3
  • 13