Jenkins + maven + spring + different .properties file = no way to understand

1,859 views
Skip to first unread message

Miguel Almeida

unread,
Jun 17, 2011, 2:30:19 PM6/17/11
to Jenkins Users
Dear all,

I am starting with Jenkins and the matter of having different
properties for different environments (eg: devel, integration, test
have different database connections) is giving me nightmares.

The different environments we have in our MAVEN project are:
- DEV, for developers' machines, who use Eclipse. Developers run a
jetty server to fire up a development version of the webapp
- DEVTEST. This one is for database JUNIT tests on developers'
machines. Spring loads this environment's database details form a file
(see bellow).
- INTEGRATION. In Jenkins, the database for junit tests is different
- PROD. For production system

Using spring, I followed this approach to managing properties:
http://www.summa-tech.com/blog/2009/04/20/6-tips-for-managing-property-files-with-spring/

I ended up with a Spring configuration like so:
<jee:jndi-lookup jndi-name="java:comp/env/my.env"
id="currentEnvironment"/>

<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>#{'classpath:/iwrs-' + currentEnvironment +'.properties'}</
value>
</list>
</property>
</bean>

This works fine in containers - namely jetty, our development
container, and Tomcat, our production one. As long as we give the
container the JNDI property, the correct iwrs-ENV.properties file will
be loaded.

However, for junit tests this doesn't work, because junit tests
running in eclipse or tests running in a maven goal are not run inside
a JNDI-enabled container. And the problem is that we essentially need
two files, an iwrs-DEVTEST.properties for developers and an iwrs-
INTEGRATION.properties in Jenkins.

I then tried to use environment variables to sort this out. The Spring
file being picked up in tests has:
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/iwrs-${env.nameWTF}*.properties
</value>
</list>
</property>
In Eclipse, I changed the installed JRE's properties to add -
DnameWTF=DEVTEST. I was hoping that in Jenkins all I needed was to add
a String parameter to the build nmaed nameWTF and set it to
INTEGRATION to make it work.
I was out of luck. This property isn't being picked up by Jenkins'
maven run. It fails spectacularly with:
Caused by:
org.springframework.beans.factory.BeanDefinitionStoreException:
Invalid bean definition with name 'sessionFactory' defined in class
path resource [hibernate/spring-SF.xml]: Could not resolve placeholder
'hibernate.exposeTransactionAwareSessionFactory'

This is a property I set in the .properties file, so it isn't picking
my property up. What is strange is that, while it doesn't seem to be
picking the properties file, after the failing log I read:
[INFO] Executing tasks
[echo] ECHO XXX Displaying 3 environment variables
[echo] [BAR] ${env.name}
[echo] [WTF] INTEGRATION

Which comes from the following Maven snippet:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>ECHO XXX Displaying 3 environment variables</echo>
<echo>[BAR] ${env.name}</echo>
<echo>[WTF] ${env.nameWTF}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>

As you see in ${env.nameWTF}, this is the environment variable, so it
has been set correctly.


Do you have any idea where the problem might be? Do you have any
suggestion regarding a better way to use .properties files, spring,
maven in multiple environments?

Any help appreciated. I feel completely lost in my quest for making CI
work.

Regards,

Miguel Almeida

domi

unread,
Jun 17, 2011, 2:57:33 PM6/17/11
to jenkins...@googlegroups.com
thats probably more a question for a spring list, but anyway....
we do something very similar, but we just use system properties and not environment variable
so just add
-DmyEnv=DEV
to the JVM settings and use it like this:

<value>classpath:/iwrs-${myEnv}.properties</value>

we actualy even use it to import different spring files:
<import resource="classpath:context-${myEnv}.xml" />

/Domi

Miguel Almeida

unread,
Jun 20, 2011, 5:40:56 AM6/20/11
to jenkins...@googlegroups.com
Thanks for the input, Domi,

I have changed my setup according to your feedback and I was successful!

The current setup is:
Developers' machine:
- Inside Eclipse, in "installed JRE", I edited the JRE and added "-DenvName=DEV". This was the only way I was able to make maven runs to be aware of envName
- In Jenkins's "Configure system" option, I added envName to "Environment variables" in "Global Properties".

Just to optimise the current solution, what differences do you have to your own solution? Do your development machines only work with one environment? I ask you this because, while envName=DEV, there are actually two environments in use: the DEV (development database to run the web project) and DEVTEST (test environment with a different database for junit tests).


Regards,

Miguel Almeida

domi

unread,
Jun 20, 2011, 2:29:42 PM6/20/11
to jenkins...@googlegroups.com
Miguel,

I'm not so sure where you actually face the problem - is it during the unit tests? then this should help you: http://maven.apache.org/plugins/maven-surefire-plugin/examples/system-properties.html
If you follow this example, then you could also pass the value of the variable on the commandline to maven:

e.g. pom.xml:
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.9</version>
        <configuration>
          <systemPropertyVariables>
            <propertyName>envName</propertyName>
            <buildDirectory>${my.envName}</buildDirectory>
            [...]
          </systemPropertyVariables>
        </configuration>
      </plugin>

then start maven like this:
      $> mvn clean install -Dmy.envName=DEV
btw. you can use "my.envName" anywhere in your pom.xml - e.g. as token to filter some file content: http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html
But you should definitely not have to change your JRE installation! 

regards Domi
Reply all
Reply to author
Forward
0 new messages