Spring Boot Configuration Best Practices

How to write concise and unambiguous application configurations.


Jul 5, 2019 2 minutes read
thumbnail for this post

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.

See Also

Customizing REST API Error Response in Spring Boot / Spring-Security-OAuth2

Defining error format is important part of REST API design.

Spring-Boot and Spring Security provide pretty nice error handling for RESTful APIs out of the box. Although it has to be documented, especially when contract-first approach to API design is used.

It is good idea to follow some common format for error responses. But OAuth2 specification and Spring Boot format may not satisfy those requirements.

Spring+Freemarker Tips

I hope you will find following tips useful when developing Spring Boot application with Freemarker.

Booting Spring Webapp

Spring Boot is an excellent tool to bootstrap java application. Most of the references mention how to create a standalone java application, optionally with embedded web server (tomcat or jetty). But Spring Boot supports also creating web applications intended to run within servlet container.

logo   Never miss a story, subscribe to our newsletter