Spring Boot with Groovy config

While¬†working on converting a Grails application to a SpringBoot based application, I was trying to understand how the auto configurations and custom configurations work under the hood. Just like CoC of Groovy/Grails, there seems to be a lot of hide-and-seek going on under the Spring boot hood. Admittedly its been a while for me with good ol’ raw Spring, so the many different ways of skinning the configuration felt a bit overwhelming. I counted several concepts around configurations – application.properties, application.yaml, PropertySource, PropertyPlaceHolder, @Value, @EnableConfiguration, @EnableConfigurationProperties, @EnableAutoConfiguration, @Configuration, @ConfigurationProperties, pre-defined property name prefixes, creating classes specifically for holding configuration values – so much information just for accessing key-value pairs? Compare to Grails – one Config.groovy (or multiple externalized) and a simple grailsApplication injection takes care of making configuration available anywhere. When I read Spring Boot support for Groovy, I somehow assumed that support for a groovy config is automatically enabled.

My Grails application already had a groovy config, and I was not in a mood to convert them to .properties or .yaml. Groovy configs are DSLs in essence – it provides many advantages over the traditional properties file: key=value (like .properties), a structured format like .yaml – sans the indent-erasure-phobia, type-enriched config values like list/map etc, functions via closures and more.

So, here is a very simple way to expose the groovy config to your Spring Boot apps:

Create a Config.groovy in the same folder as the ConfigProperties class.

/** Config.groovy **/

//simple key-value
spring.boot.guide = 'https://github.com/spring-guides?page=1'
//formatted structure
google {
searchurl = 'http://www.google.com'
apiKey = '1234'
}

/** ConfigProperties.groovy **/

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class ConfigProperties {

@Bean(name="configObject")
ConfigObject configObject() {
return new ConfigSlurper().parse(Config)
}

}
/** HelloController.groovy **/

import ConfigProperties
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class HelloController {
@Autowired
ConfigObject configObject

@RequestMapping("/")
String home() {
return "Hello World! " + configObject.spring.boot.guide
}

}

/** Application.groovy **/

@EnableAutoConfiguration
@ComponentScan
class Application {
static void main(String[] args) {
Object[] sources = [Application.class, ConfigProperties.class]
SpringApplication.run(sources, args)
}
}

Note: @Bean returns must be typed. Habitually, I wrote def configObject() { return new ConfigSlurper().parse(Config) } and the @Autowired did not wire it up.

Advertisements