12

Edit: not duplicate but almost

I would like to have my app persistence.xml to be something like

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
                http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
                version="1.0">
   <persistence-unit name="appName" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="hibernate.dialect" value="${db.dialect'}"/>
            <property name="javax.persistence.jdbc.driver" value="${db.driver}"/>
            <property name="javax.persistence.jdbc.user" value="${db.user}"/>
            <property name="javax.persistence.jdbc.password" value="${db.password}"/>
            <property name="javax.persistence.jdbc.url" value="${db.url}"/>
        </properties>
    </persistence-unit>
</persistence>

getting these placeholder values from a simple text file somewhere in my source folders.

I read about that it's possible when using Spring doing like

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <value>classpath:com/foo/jdbc.properties</value>
    </property>
</bean>

but here we are not using Spring, just Hibernate and some Primefaces.

Is it possible?

Thanks!

Edit: I didn't mention some things, but for reference, I'm also using Shiro Security and Ant to do some stuff. I'll post the solution as an answer. This makes my project have 3 different files with database parameters:

  • persistence.xml (Hibernate)
  • context.xml (Shiro)
  • database.properties (for Flyway tasks in Ant)
Community
  • 1
  • 1
paulochf
  • 690
  • 2
  • 11
  • 21

3 Answers3

28

Instead of defining the properties inside persistence.xml you can define them in a standard properties file (key=value) and pass a Properties object to the createEntityManagerFactory() method, e.g.:

Properties props = new Properties();
props.load(new FileInputStream("/some/path/persistence.properties"));
EntityManagerFactory factory = Persistence.createEntityManagerFactory("appName", props);
David Levesque
  • 22,181
  • 8
  • 67
  • 82
1

If you are using Maven as the build system, you can use Maven filters to replace the values during build time.

Or you can write a simple property placeholder replacement (which is internally used by spring itself)

Reference: https://stackoverflow.com/a/14724719/477435

Community
  • 1
  • 1
Gireesh
  • 677
  • 7
  • 14
  • Actually we are using Ant to build it. Sorry, but I think I misunderstood... Are you suggesting to use a Java class to put values on some placeholders? – paulochf Oct 04 '13 at 00:21
  • I was actually referring to use a Java class which can replace the placeholder values by reading from properties file. But he below answer suggested is much better where you can eliminate the use of persistence.xml and just use a properties file. – Gireesh Oct 04 '13 at 01:06
1

I edited to mention I'm using Shiro Security, that also needs some database parameters. I made it need just 1 database parameters location doing these stay in context.xml and referencing it in the others.

1) Ant read context.xml

Context.xml having

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <!-- Other stuff... -->

    <!-- Shiro's -->
    <Resource name="jdbc/postgres" auth="Container"
        type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
        url="jdbc:postgresql://url-to-db/database"
        username="user" password="pass" />
</Context>

did using in Ant build.xml

<xmlproperty file="/path/to/context.xml" keepRoot="false" semanticAttributes="true" includeSemanticAttribute="true" />

and then accessing it using

<target name="init-flyway">
    <property name="flyway.url" value="${Resource.url}" />
    <property name="flyway.user" value="${Resource.username}" />
    <property name="flyway.password" value="${Resource.password}" />
    <!-- stuff stuff stuff -->
</target>

2) persistence.xml read context.xml

It is possible to use context's datastore using this

<non-jta-data-source>java:/comp/env/jdbc/postgres</non-jta-data-source>

So, I killed 3 database parameters to just 1.

Thanks for the help!

paulochf
  • 690
  • 2
  • 11
  • 21