Search results
Implementing a custom Spring Boot starter for CXF and Swagger
Automating Service Provisioning Series
Subscribe to my newsletter to receive updates when content like this is published.
- Implementing APIs using Spring Boot, CXF and Swagger
- Implementing a custom Spring Boot starter for CXF and Swagger (you are here)
- Implementing a custom Maven Archetype to generate Spring Boot-based services
- Automating service provisioning and CI/CD using AWS Pipeline, Bitbucket and Terraform (work in progress)
1. OVERVIEW
Consider this scenario, the development team has increased over the last few years, software releases and deployment takes more time, that quick fix or feature couldn’t be delivered this Sprint because the deliverable now includes many changes that haven’t been signed off by QA and it might take another month to do so.
This seems like a good opportunity to break up the big Java monolithic application into multiple services or for that legacy set of applications in which business logic is duplicated to be refactored or rewritten, each by a small team benefiting from more frequent releases, easier to understand a small piece of functionality, having a low impact on other services, promoting ownership and accountability, etc..
Assuming for instance, it has been decided to implement the APIs using Spring Boot, Apache CXF and Swagger along with logging, metrics, security, etc. and maybe packaging the service in a Docker image, how do you setup this up for a dozen or more services? Do you create a baseline project to be copied and pasted for each service? Do you create a custom Maven archetype? What are other options?
This post covers how to create a custom Spring Boot starter for Apache CXF 3.1.x and Swagger 2 as the starting point to create services with a common set of dependencies and functionality also providing Spring beans auto-configuration to reduce explicit beans definition.
We are going to create two projects, asimio-api-springboot-starter, the custom Spring Boot starter which will auto-configure CXF and Swagger-related beans and asimio-api-starter-demo, a demo using asimio-api-springboot-starter.
2. REQUIREMENTS
- Java 7+.
- Maven 3.2+.
- Familiarity with Spring Framework.
3. CREATE asimio-api-springboot-starter, A SPRING BOOT STARTER FOR CXF AND SWAGGER
asimio-api-springboot-starter will be setup as a multi-module Maven project where the modules artifactIds follow Spring’s suggested naming convention:
- asimio-api-springboot-starter-parent: Manages dependencies version.
- asimio-cxf-swagger-springboot-autoconfigure: Manages the dependencies this starter provides and defines, auto-configures beans.
- asimio-cxf-swagger-springboot-starter: Brings in asimio-cxf-swagger-springboot-autoconfigure, Spring Boot(web, actuator, log4j2), CXF and Swagger dependencies.
3.1. CREATE asimio-api-springboot-starter-parent PARENT POM MAVEN MODULE
A regular parent pom.xml
defining its modules and dependencies management to ease artifacts upgrade.
3.2. CREATE asimio-cxf-swagger-springboot-autoconfigure MAVEN MODULE
This Maven child module is the main artifact of the asimio-api-springboot-starter Spring Boot starter, where all the beans are defined and auto-configured. Here is a snippet of its pom.xml
:
Most of the dependencies are optional because they will only get included when asimio-cxf-swagger-springboot-starter is added to a project, for example, asimio-api-starter-demo in this blog post.
Next comes AsimioApiAutoConfiguration.java
, the meat and potatoes of this module, where the beans are defined and auto-configured depending on some auto-configuration criteria, more on this later.
AsimioApiAutoConfiguration.java
:
As explained in Microservices using Spring Boot, Jersey, Swagger and Docker, @Configuration annotation marks this class will provide beans managed by the Spring container, swagger2Feature and jsonProvider in this case.
@EnableConfigurationProperties enables support for @ConfigurationProperties-annotated beans, AsimioApiProperties.java in this case, allowing an instance of AsimioApiProperties to be injected in other beans.
@ConditionalOnClass, @ConditionalOnMissingBean and other @Conditional annotations are used to constrain when the auto-configuration should be applied. In the case of AsimioApiAutoConfiguration.java, swagger2Feature and jsonProvider beans will be auto-configured if Swagger2Feature.class and JacksonJsonProvider.class are found in the classpath (remember the artifacts where these classes reside were included as optional) and the consumer of this starter didn’t explicitly define such beans.
Frequently used conditional annotations:
Condition | Matches when the annotation args |
ConditionalOnClass | Classes are in the classpath. |
ConditionalOnMissingClass | Classes are not in the classpath. |
ConditionalOnBean | Bean classes and/or names are included contained in the bean factory. |
ConditionalOnMissingBean | Bean classes and/or names are not included contained in the bean factory. |
ConditionalOnProperty | Properties have a specific value or the property is not in the environment. |
ConditionalOnExpression | SpEL evaluates to true. |
Then AsimioApiProperties.java
, which allows setting custom properties in files like application.yml
, application.properties
, etc.. A usage example is included in asimio-api-starter-demo:
AsimioApiProperties.java
:
The last part of this Maven module is to enable auto-configuration of the Spring context, this is done in resources/META-INF/spring.factories
:
3.3. CREATE asimio-cxf-swagger-springboot-starter MAVEN MODULE
This is an extract of the third Maven child module’s pom.xml
:
It’s including the dependencies this starter provides, artifacts that were included in asimio-cxf-swagger-springboot-autoconfigure but now they are not optional, meaning whoever uses this starter will have these artifacts in the classpath and will meet one of the conditions for the beans to be auto-configured.
We can also optionally define which dependencies this starter provides via resources/META-INF/spring.provides
:
4. PACKAGE asimio-api-springboot-starter modules
For asimio-api-starter-demo to be able to use this custom Spring Boot starter we first need to make it available to the local .m2
folder or have a Continuous Integration server to build it and deploy it to a Maven repository manager or S3 bucket:
5. CREATE asimio-api-starter-demo DEMO SERVICE
A demo application using asimio-cxf-swagger-springboot-starter custom Spring Boot starter gets simpler than the one described in Implementing APIs using Spring Boot, Apache CXF and Swagger:
pom.xml
:
The only important dependency that needs to be included, it would pull all the dependencies provided by asimio-cxf-swagger-springboot-starter.
Demo starter main class AsimioApiStarterDemoApp.java
:
The resource interface with JAX-RS and Swagger annotations HelloResource.java
:
The resource implementation HelloResourceImpl.java
:
Notice HelloResource.java
and HelloResourceImpl.java
classes are being scanned at application startup via @SpringBootApplication annotation.
A demo starter properties file, application.yml
:
What’s interesting here is the asimioApi-related properties, those are the properties that get converted into a AsimioApiProperties bean and injected in a AsimioApiAutoConfiguration bean to auto-configure CXF and Swagger.
6. RUN asimio-api-starter-demo DEMO SERVICE
This application can be run from your IDE as a regular Java application or from command line:
or
Sending a request to the /api/v1/hello
endpoint:
Available endpoints:
Description | Endpoint |
info actuator | /info |
WADL | /api/?_wadl |
Hello API version in URL (GET method) | /api/v1/hello/<name> |
Hello API version in Access header (GET method) | /api/hello/<name> |
Swagger JSON doc | /api/swagger.json |
Swagger UI | /api/api-docs?url=/api/swagger.json |
And that’s it for this Spring Boot custom starter for CXF and Swagger, a similar starter could be enhanced with logging, metrics, profiling, etc., anything that services might have in common.
Earlier this month this blog covered Implementing APIs using Spring Boot, Apache CXF and Swagger and this post details the benefits of using a custom Spring Boot starter to provide a common set of dependencies and functionality, beans auto-configuration and more. Definitely an improvement, but we would still need to create a new Spring Boot project and manually include the starter dependency and add configuration properties.
Wouldn’t it be better to also provide a Maven archetype that would take care of the service generation? Or better yet, wouldn’t it be really productive to not only generate the new service including the custom Spring Boot starter but also add it to a Git repo, create a CI pipeline, etc. through a shell command or clicking a button?
Thanks for reading and as always, feedback is very much appreciated. If you found this post helpful and would like to receive updates when content like this gets published, sign up to the newsletter.
7. SOURCE CODE
Accompanying source code for this blog post can be found at: