In the last post, I tried to describe the internal working of Spring Boot starter. It’s now time to develop our own!

As an example, we will use XStream, a no-fluff just-stuff XML/JSON (de)serializer offered by Thoughtworks. Readers who only use JAXB and Jackson are advised to have a look at XStream, it’s extremely efficient and its API is quite easy to use.

As seen in our last post, the entry-point of a starter lies in the META-INF/spring.factories file. Let’s create such a file, with the adequate content:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=ch.frankel.blog.xstream.XStreamAutoConfiguration

Now, let’s create the class referenced above. As we have seen previously, an auto-configuration class is just a regular configuration class. It’s ok to keep it empty for the time being.

@Configuration
public class XStreamAutoConfiguration {}

XStream is build around the aptly-named XStream class, which is an entry-point into its serialization features. Thoughtworks designed it to avoid static methods, so that you need an XStream instance. Creating an instance is a boring repetitive task with no value: it looks like it’s a perfect target for a Spring bean. Let’s create this instance in the auto-configuration class as a singleton bean so that client applications can use it. Our configuration class becomes:

@Configuration
public class XStreamAutoConfiguration {

    @Bean
    public XStream xstream() {
        return new XStream();
    }
}

There are other alternatives to the XStream no-args constructor documented on XStream’s website e.g. one for StaX, another for JSON, etc. Our starter should allow client applications to use their own instance, thus creating it only if there are none provided in the context. That sounds a lot like a conditional on missing bean:

@Configuration
public class XStreamAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(XStream.class)
    public XStream xstream() {
        return new XStream();
    }
}

XStream is based on converters, a way to convert from one typed value to a JSON/XML formatted string (and the other way around). There are a lot of out-of-the-box pre-registered converters but clients can register their own. In that case, it should be possible to provide them in the context so that they get registered with the provided instance.

To do that, create a @Bean method that takes both an XStream instance and a collection of converters as injected arguments. This method should only be called if there’s at least one Converter instance in the context. This can easily be configured with the @ConditionalOnBean annotation.

@Bean
@ConditionalOnBean(Converter.class)
public Collection<Converte> converters(XStream xstream, Collection<Converter> converters) {
    converters.forEach(xstream::registerConverter);
    return converters;
}

At this point, any custom converter provided in the Spring context by client applications will be registered in the XStream instance.

This concludes this post on creating Spring Boot starters. It’s quite easy and straightforward! Before going forward with your own, don’t forget to check existing starters, there are already quite a lot provided out-of-the-box and by the community.

The complete source code for this post can be found on Github.