sexta-feira, 7 de janeiro de 2011

Como externalizar o persistence.xml

Tags: Java 6 - JEE - Spring 2.5 - Hinernate 3.0

No persistence.xml é possível configurar, entre outras coisas, a conexão com a base de dados.

Quando o sistema é entregue ao cliente em um jar ou war, não existe uma maneira trivial de alterar as informações da base de dados, como a string de conexão, o username e o password.

Para fazer isso o cliente precisaria abrir o jar/war, alterar o persistence.xml e remontar o archive. Como nem sempre o cliente tem um time que saiba fazer isso, pode ser que você queira deixar o persistence.xml fora da pasta META-INF do seu projeto, por exemplo, em um folder de configuração do sistema em qualquer lugar do file system.

Abaixo segue o trecho a ser configurado no applicationContext.xml:


<beans ...>


    <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>file:///${CONF_FOLDER}/dataSource.properties</value>
            </list>
        </property>
    </bean>
    
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       <property name="persistenceXmlLocation" value="file:///${persistence.path}"/>
       <property name="persistenceUnitName" value="persistence-unit"/>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>    
    
    <tx:annotation-driven transaction-manager="transactionManager" />
    
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
    
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
 
    <context:annotation-config />
    
    <context:component-scan base-package="br.com.seupackage.*"/>


</beans>



O pulo do gato aqui é a propriedade persistenceXmlLocation do LocalContainerEntityManagerFactoryBean. Com ela você pode especificar que o persistence.xml estará em qualquer lugar do .jar ou do file system [1].

Para não deixar o caminho do persistence.xml hardcoded e como não é possível usar variável de ambiente nessa propriedade, é possível utilizar o PropertyPlaceholderConfigurer para configurar esse path.


O arquivo dataSource.properties, que está no folder reprensentado pela variável de ambiente ${CONF_FOLDER}, tem a propriedade persistence.path com o caminho absoluto do persistence.xml.


O problema estaria resolvido aqui se não fosse um efeito colateral de mudar o persistence.xml de lugar. Quando o persistence.xml não está dentro do jar, o PU root path muda para o jar que iniciou o sistema.

Se o ponto de entrada do sistema é o jar que possuía o persistence.xml (java -jar seuSistema.jar), não tem problemas.

Caso o jar ponto de entrada do sistema chame outro jar que é o que possuía o persistence.xml, aí você terá que fazer uma modificação no persistence.xml

Um exemplo dessa arquiterura é:
projeto_gui.jar       - ponto de entrada do sistema
projeto_model.jar  - possui o applicationContext e o persistence

Veja a modificação no persistence.xml:


<persistence ...>


<persistence-unit name='persistence-unit'>


<provider>org.hibernate.ejb.HibernatePersistence</provider>
        
        <jar-file>file:///C:/seusistema/lib/projeto_model.jar</jar-file>
         
<properties>
...


            <property name="hibernate.connection.provider_class"
                    value="org.hibernate.connection.C3P0ConnectionProvider" />            
...
            <property name="hibernate.connection.url" value="jdbc:oracle:thin:@192.168.0.2:1521:base" />
    <property name="hibernate.connection.username" value="user" />  
    <property name="hibernate.connection.password" value="password" />  
</properties>


</persistence-unit>


</persistence>


A tag <jar-file> foi adicionada para informar que o PU root path (o caminho que este persistence unit deve procurar as classes anotadas como Entity) é o jar que possuía o persistence.xml antes desta alteração.


Referência:

[1] LocalContainerEntityManagerFactoryBean: http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html#setPersistenceXmlLocation(java.lang.String)

Nenhum comentário:

Postar um comentário