title: Spring Boot: How to externalize JDBC datasource configuration?
body: <p>I have following Spring Boot controller code that works. (Some sensitive text was replaced)</p>
  
  <pre><code>package com.sample.server;
  
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.util.List;
  
  import org.apache.commons.dbcp.BasicDataSource;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.jdbc.core.RowMapper;
  import org.springframework.web.bind.annotation.RequestMethod;
  import org.springframework.web.bind.annotation.RestController;
  import org.springframework.web.bind.annotation.RequestMapping;
  
  @RestController
  public class DetailReportController
  {
      @RequestMapping(value="/report/detail", method=RequestMethod.GET)
      public List&lt;UFGroup&gt; detailReport()
      {
          BasicDataSource dataSource = new BasicDataSource();
          dataSource.setDriverClassName("net.sourceforge.jtds.jdbc.Driver");
          dataSource.setUrl("jdbc:jtds:sqlserver://111.11.11.11/DataBaseName;user=sa;password=password");
  
          JdbcTemplate jt = new JdbcTemplate(dataSource);
  
          List&lt;UFGroup&gt; results = jt.query(
              "select NID, SCode, SName from UFGroup",
              new RowMapper&lt;UFGroup&gt;()
              {
                  @Override
                  public UFGroup mapRow(ResultSet rs, int rowNum) throws SQLException
                  {
                      return new UFGroup(rs.getInt("NID"), rs.getString("SCode"),
                              rs.getString("SName"));
                  }
              });
  
          return results;
      }
  
      private static class UFGroup
      {
          public int nid;
          public String scode;
          public String sname;
  
          public UFGroup(int nid, String scode, String sname)
          {
              this.nid = nid;
              this.scode = scode;
              this.sname = sname;
          }
      }
  }
  </code></pre>
  
  <p>Now I want to externalize the configuration of the datasource.
  That is, BasicDataSource class, driver class name, datasource URL should be placed into application.properties.
  How can I do that?</p>
  
  <p>BTW, I am a newbie of Spring, Spring Boot and even Java Beans. All I have is some Java programming experience, mainly for mobile devices. I've spent a few days to study Spring Boot environment, but I was literally overwhelmed.
  So please, give me the exact instruction with concrete example.</p>
  
  <p><strong>UPDATE</strong>:
  when I applied the answer of M. Deinum, following error occured when I ran the application:</p>
  
  <pre><code>2013-11-18 19:37:54.789  INFO 6868 --- [           main] com.logicplant.uflow.server.Application  : Starting Application on zeo-PC with PID 6868 (C:\Projects\uFlow\Dev\Server\Spring\uFlowServer\build\libs\uFlowServer-1.0.0.jar started by zeo)
  2013-11-18 19:37:54.830  INFO 6868 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7f83698f: startup date [Mon Nov 18 19:37:54 KST 2013]; root of context hierarchy
  2013-11-18 19:37:55.931  INFO 6868 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
  2013-11-18 19:37:55.932  INFO 6868 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.42
  2013-11-18 19:37:56.009  INFO 6868 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
  2013-11-18 19:37:56.010  INFO 6868 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1183 ms
  2013-11-18 19:37:56.165  INFO 6868 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
  2013-11-18 19:37:56.165  INFO 6868 --- [ost-startStop-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
  2013-11-18 19:37:56.242  INFO 6868 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
  2013-11-18 19:37:56.388  INFO 6868 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/report/detail],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.List&lt;com.logicplant.uflow.server.DetailReportController$UFGroup&gt; com.logicplant.uflow.server.DetailReportController.detailReport()
  2013-11-18 19:37:56.438  INFO 6868 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
  2013-11-18 19:37:56.439  INFO 6868 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
  2013-11-18 19:37:56.788  INFO 6868 --- [ost-startStop-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 622 ms
  2013-11-18 19:37:56.881  INFO 6868 --- [           main] o.apache.catalina.core.StandardService   : Stopping service Tomcat
  java.lang.reflect.InvocationTargetException
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
      at java.lang.Thread.run(Unknown Source)
  Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'detailReportController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.logicplant.uflow.server.DetailReportController.jt; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1139)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:299)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:295)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:665)
      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
      at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
      at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:509)
      at org.springframework.boot.SpringApplication.run(SpringApplication.java:278)
      at com.logicplant.uflow.server.Application.main(Application.java:17)
      ... 6 more
  Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.logicplant.uflow.server.DetailReportController.jt; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:505)
      at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
      ... 20 more
  Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1051)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:919)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:820)
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:477)
      ... 22 more
  </code></pre>
  
  <p>For reference, the content of build.grade file (I use Gradle) is as follows: (following M. Deinum's suggestion, I removed the dependency for org.apache.commons.dbcp.)</p>
  
  <pre><code>buildscript {
      repositories {
          maven { url "http://repo.spring.io/libs-snapshot" }
          mavenLocal()
      }
      dependencies {
          classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M5")
      }
  }
  
  apply plugin: 'java'
  apply plugin: 'eclipse'
  apply plugin: 'idea'
  apply plugin: 'spring-boot'
  
  jar {
      baseName = 'uFlowServer'
      version = '1.0.0'
  }
  
  repositories {
      mavenCentral()
      maven { url "http://repo.spring.io/libs-snapshot" }
  }
  
  dependencies {
      compile("org.springframework.boot:spring-boot-starter-web:0.5.0.M5")
      compile("com.fasterxml.jackson.core:jackson-databind")
      compile("org.springframework:spring-jdbc:4.0.0.M3")
      runtime("net.sourceforge.jtds:jtds:1.3.1")
      testCompile("junit:junit:4.11")
  }
  
  task wrapper(type: Wrapper) {
      gradleVersion = '1.8'
  }
  </code></pre>
  
  <p>And this is Application.java file, which is the main source file.</p>
  
  <pre><code>package com.sample.server;
  
  import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
  import org.springframework.boot.SpringApplication;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  
  @Configuration
  @EnableAutoConfiguration
  @ComponentScan
  public class Application
  {
      public static void main(String args[])
      {
          SpringApplication app = new SpringApplication(Application.class);
          app.setShowBanner(false);
          app.run(args);
      }
  }
  </code></pre>
  
  <p>What can be done for the error?</p>
  
  <p><strong>UPDATE</strong>:
  As M. Deinum suggested, when I changed build.gradle file as follows, the application worked!</p>
  
  <pre><code>buildscript {
      repositories {
          maven { url "http://repo.spring.io/libs-snapshot" }
          mavenLocal()
      }
      dependencies {
          classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M6")
      }
  }
  
  apply plugin: 'java'
  apply plugin: 'eclipse'
  apply plugin: 'idea'
  apply plugin: 'spring-boot'
  
  jar {
      baseName = 'uFlowServer'
      version = '1.0.0'
  }
  
  repositories {
      mavenCentral()
      maven { url "http://repo.spring.io/libs-snapshot" }
  }
  
  dependencies {
      compile("org.springframework.boot:spring-boot-starter-web:0.5.0.M6")
      compile("org.springframework.boot:spring-boot-starter-jdbc:0.5.0.M6")
      compile("com.fasterxml.jackson.core:jackson-databind")
      runtime("net.sourceforge.jtds:jtds:1.3.1")
      testCompile("junit:junit:4.11")
  }
  
  task wrapper(type: Wrapper) {
      gradleVersion = '1.8'
  }
  </code></pre>