The Culture of Code
  1. Posts/

Spring Boot Configuration Best Practices

Spring Boot comes with very neat configuration mechanism. You may have one default application configuration defined in application.yml and set of environment specific configuration files, e.g. application-prod.yml, application-test.yml, application-dev.yml. Inside configuration files it is possible to use expressions to evaluate parameters values based on over parameters.

Even if this mechanism allows to write pretty concise configurations, it is often misused.

Let’s take an example configuration file for zuul proxy:

application.yml:

zuul:
  routes:
    foos:
      path: /foos/**
      url: http://localhost:8081/spring-zuul-foos-resource/foos
    baas:
      path: /baas/**
      url: http://localhost:8081/spring-zuul-baas-resource/foos

When it comes to make it ready for production the naive approach would be to override urls in profile configurations:

application-prod.yml:

zuul:
  routes:
    foos:
      url: http://cloud-prod:8081/spring-zuul-foos-resource/foos
    baas:
      url: http://cloud-prod:8081/spring-zuul-baas-resource/foos

and application-uat.yml:

zuul:
  routes:
    foos:
      url: http://cloud-uat:8081/spring-zuul-foos-resource/foos
    baas:
      url: http://cloud-uat:8081/spring-zuul-baas-resource/foos

This is very Copy&Paste approach and I highly recommend to avoid it.

Refactoring Configuration Files #

How we can refactor it?

TL;DR: Extract host names or base urls and use naming conventions as much as possible

1. Extract backend base url property #

application.yml:

backend.url: http://localhost:8081
zuul:
  routes:
    foos:
      path: /foos/**
      url: ${backend.url}/spring-zuul-foos-resource/foos
    baas:
      path: /baas/**
      url: ${backend.url}/spring-zuul-baas-resource/foos

application-prod.yml:

backend.url: http://cloud-prod:8081

and application-uat.yml:

backend.url: http://cloud-uat:8081/

2. Use naming convention #

application.yml:

backend.url: http://cloud-${spring.profile.active}:8081
zuul:
  routes:
    foos:
      path: /foos/**
      url: ${backend.url}/spring-zuul-foos-resource/foos
    baas:
      path: /baas/**
      url: ${backend.url}/spring-zuul-baas-resource/foos

Files application-prod.yml and application-uat.yml can be removed now. For local development we may want to create file application-local.yml:

backend.url: http://localhost:8081

3. Follow naming convention even in local environment #

If you don’t have a lot of services to run you may define alias for your local machine in your /etcs/hosts file:

127.0.0.1 cloud-local

If you’re developing a lot of interconnected services then docker-compose may be your way to go.

Next Steps #

  1. Instead of creating environment-specific files use Spring Cloud Config.
  2. Use Spring Cloud Vault to access secrets. You may still need to define configuration file to run application locally and in CI server.
  3. Use service discovery instead of static host names or utilise Kubernetes namespaces to unify naming.