1

I'm new to Java and Jenkins but have a strong C# MVC, TFSBuild, and Octopus Deploy background. In Octopus Deploy it is possible to read the MVC Web.Config XML file and replace database connection strings - this makes it easy to take a built artefact and promote to a different internal VM environment. I want to achieve the same net effect with Java and Jenkins.

Am I correct in thinking that Java connection strings for databases could/should be set in environment variables per VM environment? Is there a Jenkins plugin that can achieve this for me or will I need to write a PowerShell script?

I have found several links such as CloudBees but they all seem to be spefic to cloud providers; I just want to target internal Virtual Machines.

Using SpringBatch, Maven, DB connection to Oracle.

Paul
  • 1,483
  • 14
  • 32
  • How do you set your db connection? in which file does it exists? Do you need at build stage a DB connection. If not why do you not use jndi for DB connection string which you can set for each server seperately. Do you use maven or something else to build your web application? – sgpalit Mar 29 '16 at 14:42
  • I'm new to Java and where is good practice to store the DB connection, so I'm open to suggestions – Paul Mar 29 '16 at 14:51
  • 1
    It depends a lot on what frameworks you're using and whether you deploy to an application server or not. – andrepnh Mar 29 '16 at 15:01
  • @andrepnh that's a good point, I've been reading http://stackoverflow.com/questions/8967558/config-file-for-holding-connection-string-parameters-in-java for more info about the options for storing connection details – Paul Mar 30 '16 at 08:14
  • @sgpalit I'm using Maven for building and Spring framework. – Paul Mar 30 '16 at 08:16
  • Ok @Paul, I've updated my answer with more details. – andrepnh Mar 30 '16 at 13:27

2 Answers2

1

You could also try using different maven profiles to build a specific artifact suitable for tests, but that's not recommended. You should test a version of your system that is as close as possible to the one in production.

So, yes, environment variables are the most portable way to do this. A powerful Jenkins plugin to control them is EnvInject. You can define specific variables as simple key-value pairs that will be injected in the build process.


Edit

Since you're using Spring Batch, you're able to setup database connection using xml files or programmatic configuration. Configuration files support only system properties, so you would do:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.user}" />
    <property name="password" value="${db.password}" />
    <!-- drivers and other stuff -->
</bean>

For programmatic configuration (which you can see a thorough example here) you may use system properties too:

@Bean
public DataSource someDataSource() throws SQLException {
    final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
    dataSource.setUrl(System.getProperty("db.url"));
    dataSource.setUsername(System.getProperty("db.user"));
    dataSource.setPassword(System.getProperty("db.password"));
    // Driver, connection properties, if any, and other stuff
    return dataSource;
}

And also environment variables:

dataSource.setUrl(System.getenv("db.url"));
dataSource.setUsername(System.getenv("db.user"));
dataSource.setPassword(System.getenv("db.password"));

You would set environment variables using the EnvInject plugin, but if you use system properties the simplest way to pass them is as command line arguments: java ... -Ddb.url=something -Ddb.user=foo -Ddb.password=bar. Notice, however, that anyone capable of listing that java process will have access to the db credentials. If you stick to properties, you can also pass them using properties files, which Spring seems to support. The problem is you would have to maintain separate configuration files for each environment, something I believe adds to much overhead to a build process that could be simpler.

Community
  • 1
  • 1
andrepnh
  • 933
  • 8
  • 21
1

Since you did not specify exactly what your DB is and what your server is I will give an example for tomcat, mysql and spring configuration. For more information on tomcat jndi-datasource-examples, you schould add your sql driver to the lib of tomcat.

In your server.xml which you can find under your tomcat_root/conf folder add your connection string in context

<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
           maxActive="100" maxIdle="30" maxWait="10000"
           username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
           url="jdbc:mysql://localhost:3306/javatest"/>

In your web.xml add following resource referentie

<resource-ref>
  <description>DB Connection</description>
  <res-ref-name>jdbc/TestDB</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

In your spring configuration add following

<beans:bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <beans:property name="jndiName" value="java:comp/env/jdbc/TestDB"/>
</beans:bean>

Now you can Autowire or add datasource bean as referentie to your other data service beans.

@Autowired
private DataSource dataSource;
sgpalit
  • 2,676
  • 2
  • 16
  • 22