30

is there a way to reference a .properties file in a spring-context.xml and a JPA persistence.xml?

I think I've seen somewhere an example of this in spring context files, though I can't remember where that was. Maybe someone knows this? About the persistence.xml I am actually unsure if this works at all.

My aim is to change some properties between development and distribution configuration. The idea I have currently is to replace all properties manually in the files via ant from a template config. Though there should be a better way to do this. :)

Jason Gritman
  • 5,251
  • 4
  • 30
  • 38
subes
  • 1,832
  • 5
  • 22
  • 28

2 Answers2

39

Rather than using your build to create a prod or dev version of your persistence.xml, just move all property settings to your spring content.

My persistence.xml is

<?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="JPAService" transaction-type="RESOURCE_LOCAL">   
    </persistence-unit>
</persistence>

In my spring content, i then use the PropertyPlaceholderConfigurer to read dev/prod property values and set these into the entityManagerFactory bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
    <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>    
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

    <bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
        <property name="ignoreResourceNotFound" value="true"/>
        <property name="locations">
            <list>
                <value>classpath:dev.properties</value>
            </list>
        </property>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${datasource.driverClassName}"/>
        <property name="url" value="${datasource.url}"/>
        <property name="username" value="${datasource.username}"/>
        <property name="password" value="${datasource.password}"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
        <property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml"/>
        <property name="persistenceUnitName" value="JPAService"/>
        <property name="dataSource" ref="dataSource"/>

        <property name="jpaVendorAdapter"> 
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
                <property name="databasePlatform" value="org.hibernate.dialect.OracleDialect"/> 
                <property name="showSql" value="true" /> 
                <property name="generateDdl" value="true"/>
            </bean> 
        </property>
        <property name="jpaProperties">
                <!-- set extra properties here, e.g. for Hibernate: -->
            <props>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false"/>
</beans>
opyate
  • 5,388
  • 1
  • 37
  • 64
emeraldjava
  • 10,894
  • 26
  • 97
  • 170
  • 2
    Users might want to do a little research before using this example as-is. From the DriverManagerDataSource JavaDoc: "NOTE: This class is not an actual connection pool; it does not actually pool Connections. It just serves as simple replacement for a full-blown connection pool, implementing the same standard interface, but creating new Connections on every call." – spaaarky21 Jan 26 '13 at 07:11
17

You can reference external property files from a Spring bean definition file using a PropertyPlaceholderConfigurer. I don't think that will work for a JPA persistence.xml, although Spring's JPA support allows you to incorporate most, if not all, the content of persistence.xml into the beans file itself, in which case it would work fine.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 1
    Thanks, for my solution I now used the PropertyPlaceholderConfigurer in the context.xml with a jdbc.properties for the datasource. I moved the hibernate stuff out of both files into a hibernate.properties. Those two files get replaced with different versions for distribution and development. The hibernate.properties seems to be detected properly at runtime, though the hibernatetool ant task has to be told where the file is, even if it is in the classpath. So all is working now. :) – subes Dec 03 '09 at 09:10