title: Spring boot config server
body: <p>I have been trying to get a grip on the spring boot config server that is located Here: <a href="https://github.com/spring-cloud/spring-cloud-config" rel="noreferrer">https://github.com/spring-cloud/spring-cloud-config</a> and after reading the documentation more thoroughly I was able to work through most of my issues.  I did however have to write an additional class for a file based PropertySourceLocator</p>
  
  <pre><code>/*
   * Copyright 2013-2014 the original author or authors.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
  
  
  * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.springframework.cloud.config.client;
  
  import java.io.File;
  import java.io.IOException;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.nio.file.Paths;
  import java.util.Iterator;
  import java.util.Properties;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.annotation.Value;
  import org.springframework.boot.context.properties.ConfigurationProperties;
  import org.springframework.core.env.PropertiesPropertySource;
  import org.springframework.core.env.PropertySource;
  import org.springframework.util.StringUtils;
  
  /**
   * @author Al Dispennette
   *
   */
  @ConfigurationProperties("spring.cloud.config")
  public class ConfigServiceFilePropertySourceLocator implements PropertySourceLocator {
      private Logger logger = LoggerFactory.getLogger(ConfigServiceFilePropertySourceLocator.class);
  
      private String env = "default";
  
      @Value("${spring.application.name:'application'}")
      private String name;
  
      private String label = name;
  
      private String basedir = System.getProperty("user.home");
  
      @Override
      public PropertySource&lt;?&gt; locate() {
          try {
              return getPropertySource();
          } catch (IOException e) {
              logger.error("An error ocurred while loading the properties.",e);
          }
  
          return null;
      }
  
      /**
       * @throws IOException
       */
      private PropertySource getPropertySource() throws IOException {
          Properties source = new Properties();
          Path path = Paths.get(getUri());
          if(Files.isDirectory(path)){
              Iterator&lt;Path&gt; itr = Files.newDirectoryStream(path).iterator();
              String fileName = null!=label||StringUtils.hasText(label)?label:name+".properties";
              logger.info("Searching for {}",fileName);
              while(itr.hasNext()){
                  Path tmpPath = itr.next();
                  if(tmpPath.getFileName().getName(0).toString().equals(fileName)){
                      logger.info("Found file: {}",fileName);
                      source.load(Files.newInputStream(tmpPath));
                  }
              }
          }
          return new PropertiesPropertySource("configService",source);
      }
  
      public String getUri() {
          StringBuilder bldr = new StringBuilder(basedir)
          .append(File.separator)
          .append(env)
          .append(File.separator)
          .append(name);
  
          logger.info("loading properties directory: {}",bldr.toString());
          return bldr.toString();
      }
  
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      public String getEnv() {
          return env;
      }
  
      public void setEnv(String env) {
          this.env = env;
      }
  
      public String getLabel() {
          return label;
      }
  
      public void setLabel(String label) {
          this.label = label;
      }
  
      public String getBasedir() {
          return basedir;
      }
  
      public void setBasedir(String basedir) {
          this.basedir = basedir;
      }
  
  }
  </code></pre>
  
  <p>Then I added this to the ConfigServiceBootstrapConfiguration.java</p>
  
  <pre><code>@Bean
  public PropertySourceLocator configServiceFilePropertySource(
          ConfigurableEnvironment environment) {
      ConfigServiceFilePropertySourceLocator locator = new ConfigServiceFilePropertySourceLocator();
      String[] profiles = environment.getActiveProfiles();
      if (profiles.length==0) {
          profiles = environment.getDefaultProfiles();
      }
      locator.setEnv(StringUtils.arrayToCommaDelimitedString(profiles));
      return locator;
  }
  </code></pre>
  
  <p>In the end this did what I wanted. 
  Now I'm curious to know if this is what I should have done or if I am still missing something and this was already handled and I just missed it.</p>
  
  <p>*****Edit for info asked for by Dave******</p>
  
  <p>If I take out the file property source loader and update the bootstrap.yml with </p>
  
  <pre><code>uri: file://${user.home}/resources
  </code></pre>
  
  <p>the sample application throws the following error on start up:</p>
  
  <pre><code>ConfigServiceBootstrapConfiguration : Could not locate PropertySource: Object of class [sun.net.www.protocol.file.FileURLConnection] must be an instance of class java.net.HttpURLConnection
  </code></pre>
  
  <p>This is why I thought the additional class would be needed.  As far as the test case goes I believe you are talking about the SpringApplicationEnvironmentRepositoryTests.java and I agree creating the environment works but as a whole the application does not seem to be opertaing as expected when the uri protocol is 'file'.</p>
  
  <p>******Additional Edits*******</p>
  
  <p>This is how I understanding this is working:
  The sample project has a dependency on the spring-cloud-config-client artifact so therefore has a transitive dependency on the spring-cloud-config-server artifact.
  The ConfigServiceBootstrapConfiguration.java in the client artifact creates a property source locator bean of type ConfigServicePropertySourceLocator.
  The ConfigServicePropertySourceLocator.java in the config client artifact has the annotation @ConfigurationProperties("spring.cloud.config")
  And the property uri exists in said class, hence the setting of spring.cloud.config.uri in the bootstrap.yml file.</p>
  
  <p>I believe this is reenforced up by the following statement in the quickstart.adoc:</p>
  
  <blockquote>
    <p>When it runs it will pick up the external configuration from the
    default local config server on port 8888 if it is running. To modify
    the startup behaviour you can change the location of the config server
    using <code>bootstrap.properties</code> (like <code>application.properties</code> but for
    the bootstrap phase of an application context), e.g.</p>
    
    <h2>---- spring.cloud.config.uri: <a href="http://myconfigserver.com" rel="noreferrer">http://myconfigserver.com</a></h2>
  </blockquote>
  
  <p>At this point, some how the JGitEnvironmentRepository bean is getting used and looking for a connection to github.
  I assumed that since uri was the property being set in the ConfigServicePropertySourceLocator then any valid uri protocol would work for pointing to a location.
  That is why I used the 'file://' protocol thinking that the server would pick up the NativeEnvironmentRepository.</p>
  
  <p>So at this point I'm sure I'm either missing some step or the file system property source locator needs to be added.</p>
  
  <p>I hope that is a little clearer.</p>
  
  <p>the Full Stack:</p>
  
  <pre><code>java.lang.IllegalArgumentException: Object of class [sun.net.www.protocol.file.FileURLConnection] must be an instance of class java.net.HttpURLConnection
      at org.springframework.util.Assert.isInstanceOf(Assert.java:339)
      at org.springframework.util.Assert.isInstanceOf(Assert.java:319)
      at org.springframework.http.client.SimpleClientHttpRequestFactory.openConnection(SimpleClientHttpRequestFactory.java:182)
      at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:140)
      at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:76)
      at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:541)
      at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:506)
      at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:448)
      at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:68)
      at org.springframework.cloud.bootstrap.config.ConfigServiceBootstrapConfiguration.initialize(ConfigServiceBootstrapConfiguration.java:70)
      at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:572)
      at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
      at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
      at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
      at sample.Application.main(Application.java:20)
  </code></pre>