1. Introduction
spring-boot magic…
Read github pages reference documentation
generated by generator-jvm yeoman generator (java-spring-boot)
2. Implementation
To create starter we need minimal projects structure:
-
service with functionality we wanna expose / integrate:
hello-service
-
module which will be automatically configure that service as far starter was added as a dependency:
hello-service-autoconfigure
-
starter module, containing everything needed (hello-service + auto-config + other dependencies):
spring-boot-starter-hello
we will be using and testing out starter in project: spring-boot-starter-hello-tests
|
2.1. hello-service
First, create service with functionality you wanna to share with the world
mkdir hello-service
touch hello-service/pom.xml
# ...
That module contains HelloService we wanna expose:
/**
* Super complex greeting service!
*/
public interface HelloService {
/**
* Some javadoc...
* @param whom who, we salute?
* @return greeting message
*/
String sayHello(final String whom);
}
@RequiredArgsConstructor
public class HelloServiceImpl implements HelloService {
final String prefix;
final String suffix;
@Override
public String sayHello(String whom) {
return format("%s %s%s", prefix, whom, suffix);
}
}
2.2. hello-service-autoconfigure
Next, crete auto-configuration module for hello-service
mkdir hello-service-autoconfigure
touch hello-service-autoconfigure/pom.xml
# ...
That module will depends on hello-service
module and spring-boot auto-configuration dependencies
hello-service-autoconfigure/pom.xml
: <dependencies>
<!-- compile -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<optional>true</optional>
<groupId>com.github.daggerok</groupId>
<artifactId>hello-service</artifactId>
</dependency>
<!-- optional -->
<dependency>
<optional>true</optional>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!-- test -->
<dependency>
<scope>test</scope>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
Here we are creating auto-configuration which is basically will be picked up if HelloService
class in classpath
./hello-service-autoconfigure/src/main/java/com/github/daggerok/hello/config/HelloServiceAutoConfiguration.java
:/**
* Apply auto configuration only if {@link HelloService} class is in classpath.
*/
@Configuration
@RequiredArgsConstructor
@ConditionalOnClass(HelloService.class)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public HelloService helloService(final HelloProperties properties) {
final Hello prop = properties.getHello();
return new HelloServiceImpl(prop.getPrefix(), prop.getSuffix());
}
}
To make it happens, we need provide spring.factories
file, which spring-boot will identify and create needed
auto-configurations for us if starter in classpath according to conditions
./hello-service-autoconfigure/src/main/java/com/github/daggerok/hello/config/HelloServiceAutoConfiguration.java
:org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.github.daggerok.hello.config.HelloServiceAutoConfiguration
2.3. spring-boot-starter-hello
Now we are ready to go create starter itself
mkdir spring-boot-starter-hello
touch spring-boot-starter-hello/pom.xml
# ...
That starter will define in dependencies everything needed
spring-boot-starter-hello/pom.xml
: <artifactId>spring-boot-starter-hello</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.daggerok</groupId>
<artifactId>hello-service</artifactId>
</dependency>
<dependency>
<groupId>com.github.daggerok</groupId>
<artifactId>hello-service-autoconfigure</artifactId>
</dependency>
</dependencies>
HelloStarterAutoConfiguration.java
:Unresolved directive in index.adoc - include::../spring-boot-starter-hello/src/main/java/com/github/daggerok/starter/HelloStarterAutoConfiguration.java[tags=content]
spring.factories
file:Unresolved directive in index.adoc - include::../spring-boot-starter-hello/src/main/resources/META-INF/spring.factories[]
Unresolved directive in index.adoc - include::../spring-boot-starter-hello/src/test/java/com/github/daggerok/starter/HelloStarterAutoConfigurationTests.java[tags=content]
Here we are testing that HelloService bean was properly instantiated and found in application context. |
3. Testing
To test starter, all you need to do is:
mkdir spring-boot-starter-hello-tests
touch spring-boot-starter-hello-tests/pom.xml
# ...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.daggerok</groupId>
<artifactId>spring-boot-starter-hello</artifactId>
</dependency>
</dependencies>
@Log4j2
@SpringBootApplication
public class HelloStarterTestApplication {
public static void main(String[] args) {
final ConfigurableApplicationContext context = SpringApplication.run(HelloStarterTestApplication.class, args);
final HelloService helloService = context.getBean(HelloService.class);
log.info(() -> helloService.sayHello("ololo-trololo"));
}
}