Question

We're building a Spring-based application which will be delivered to end users as a distribution package. Users are responsible for properly configuring whatever needs to be configured (it's mostly about various filesystem locations, folder access permissions, etc). There's a good idea to make the app help users understand what is not configured or which parts of configuration are invalid.

Our current approach is a custom ApplicationContextInitializer which does all the environment validation "manually" and then registers few "low level" beans in the application context explicitly. If something is wrong, initializer throws, exception is caught somewhere in main(), interpreted (converted into plain English) and then displayed.

While this approach works fine, I'm wondering if there are any best practices to minimize hand-written code and use Spring whenever possible.

Here's an illustrative example. The application requires a folder for file uploads. This means:

  1. There should be a configuration file
  2. This file should be accessible by the app
  3. This file should have no syntax errors
  4. This file should explicitly define some specific property (let it be app.uploads.folder)
  5. This property should describe the existing filesystem entity
  6. This entity should be a folder
  7. The app should have read/write access to this folder

Does Spring provide any tools to implement this sort of validation easily?

Was it helpful?

Solution

Spring Boot has a nice feature for context and external configuration validation. If you define a POJO class and declare it as @ConfigurationProperties then Spring will bind the Environment (external properties and System/OS typically) to its properties using a DataBinder. E.g.

@ConfigurationProperties(name="app.uploads")
public class FileUploadProperties {
    private File folder;
    // getters and setters ommitted
}

will bind to app.uploads.folder and ensure that it is a File. For extra validation you can do it manually in the setter, or you can implement Validator in your FileUploadProperties or you can use JSR-303 annotations on the fields. By default an external property in app.uploads.* that doesn't bind will throw an exception (e.g. a mis-spelled property name, or a conversion/format error).

If you use Spring Boot Autoconfigure @EnableAutoConfigure you don't have to do anything else, but if it's just vanilla Spring (Boot) you need to say @EnableConfigurationProperties in your @Configuration somewhere as well.

A bonus feature: if you also use the Spring Boot Actuator you will also get JMX and HTTP support (in a webapp) for inspecting the bindable and bound properties of @ConfigurationProperties beans. The HTTP endpoint is "/configprops".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top