Spring Boot Part 6: Auto Configuration and Starters

Spring Boot allows for the creation of “starters:” Convenient dependency descriptors that often provide some specific but complex functionality. Examples from Spring Boot discussed in this series of articles include spring-boot-starter-web, spring-boot-starter-thymeleaf, and spring-boot-starter-actuator.

This article describes some reusable code targeted for development and testing (a REST controller @ /jig/bean/{name}.json and /jig/bean/{name}.xml) and the steps necessary to create a Spring Boot starter. It also describes a starter for the embedded MySQL server process described in “Spring Embedded MySQL Server”.

Complete javadoc is provided.

Theory of Operation

As discussed in part 1, the spring-boot-starter-actuator may be configured. One of its sevices may be used to get the list (with attributes) of the configured beans. Sample partial output below:

$ curl -is -X GET http://localhost:5001/actuator/beans/
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Sun, 19 Jul 2020 20:22:10 GMT

  "contexts" : {
    "application" : {
      "beans" : {
        "discoveryService" : {
          "scope" : "singleton",
          "type" : "upnp.DiscoveryService",
          "resource" : "file [/Users/ball/upnp-media-server/target/classes/upnp/DiscoveryService.class]",
          "dependencies" : [ "mediaServer" ]
      "parentId" : null

The ball-spring-jig-starter will provide the following two REST APIs to retrieve a specific bean’s value and demonstrate serialization to JSON or XML as appropriate. JSON partial output:

$ curl -is -X GET http://localhost:5000/jig/bean/discoveryService.json
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 19 Jul 2020 20:23:38 GMT

  "uuid:00000000-0000-1010-8000-0024BEF18BCC" : {
    "expiration" : 1595191949391,
    "ssdpmessage" : {
      "params" : { },
      "entity" : null,
      "locale" : null,
      "inetAddress" : "",
      "st" : "uuid:00000000-0000-1010-8000-0024BEF18BCC",
      "location" : "",
      "usn" : "uuid:00000000-0000-1010-8000-0024BEF18BCC",
      "protocolVersion" : {
        "protocol" : "HTTP",
        "major" : 1,
        "minor" : 1

And corresponding XML output:

$ curl -is -X GET http://localhost:5000/jig/bean/discoveryService.xml
HTTP/1.1 200
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Sun, 19 Jul 2020 20:29:47 GMT


The implementation is described in the next section.


The steps to create the “jig” starter:

  1. Implement the REST controller

  2. Create a project and POM for the starter artifact

  3. Create the auto-configuration class(es)

  4. Link the auto-configuration class(es) into the starter’s META-INF/spring.factories resource1

The BeanRestController implementation is shown below.

@RequestMapping(value = { "/jig/bean/" })
@NoArgsConstructor @ToString @Log4j2
public class BeanRestController implements ApplicationContextAware {
    private ApplicationContext context = null;

    public void setApplicationContext(ApplicationContext context) {
        this.context = context;

    @RequestMapping(method = { GET }, value = { "{name}.json" }, produces = APPLICATION_JSON_VALUE)
    public Object json(@PathVariable String name) throws Exception {
        return context.getBean(name);

    @RequestMapping(method = { GET }, value = { "{name}.xml" }, produces = APPLICATION_XML_VALUE)
    public Object xml(@PathVariable String name) throws Exception {
        return context.getBean(name);

    @ExceptionHandler({ NoSuchBeanDefinitionException.class, NoSuchElementException.class })
    @ResponseStatus(value = NOT_FOUND, reason = "Resource not found")
    public void handleNOT_FOUND() { }

Its implementation is straightforward: A method each to look-up the requested bean and then serialize to JSON and XML.

In the project for the starter, add the AutoConfiguration class.

@ConditionalOnClass({ BeanRestController.class })
@Import({ BeanRestController.class })
@NoArgsConstructor @ToString @Log4j2
public class AutoConfiguration {

It is critical that @Configuration classes are added through @Import annotations and not @ComponentScan Neither the starter author nor the integrator will be able to predict what components will or will not be included in a scan.

It is a good practice to include a “conditional-on” annotation (e.g., @ConditionalOnClass to test any required dependency software has been configured and/or is on the class path.

Finally, META-INF/spring.factories must be configured in the starter JAR to notify Spring Boot to add the AutoConfiguration.

org.springframework.boot.autoconfigure.EnableAutoConfiguration: ball.spring.jig.autoconfigure.AutoConfiguration

Creating a starter for the embedded MySQL process described in “Spring Embedded MySQL Server” is equally straightforward. Its AutoConfiguration class is shown below:

@ConditionalOnClass({ MysqldConfiguration.class })
@Import({ EntityManagerFactoryComponent.class, MysqldConfiguration.class })
@NoArgsConstructor @ToString @Log4j2
public class AutoConfiguration {

With it corresponding META-INF/spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration: ball.spring.mysqld.autoconfigure.AutoConfiguration


Creating a Spring Boot starter is straightfoward: Create a project/POM to host the starter’s dependencies and auto-configuration class(es), add the annotated auto-configuration class(es), and configure the starter JAR’s META-INF/spring.factories with the auto-configuration class(es). That starter’s functionality can then be added to a Spring Boot application simply by including a single dependency in the application POM.

[1] Many Spring Boot components provide separate auto-configuration and starter artifacts to support all use cases. The author feels these example implementations do not benefit from separate auto-configuration artifacts.