Implementing a Maven Archetype to Generate Spring Boot-Based Services
Want to learn more about implementing a Maven archetype? Check out this post on how to implement and generate Spring Boot-based services.
Join the DZone community and get the full member experience.
Join For Freeintroduction
let’s say your organization is splitting a big, monolithic application into multiple, smaller, and more specialized microservices. for instance, some of them will interact with a relational database and a message broker, while others will communicate with a nosql database.
this is a great opportunity to standardize the new deliverables in your company. you might want to develop some custom spring boot starters responsible for providing common java application components , logging, tracing, metrics, monitoring, resilience, rdbms, and apis implementation support, helping with the application bootstrapping process and reducing common boilerplate code in each spring boot-based service.
once you are using these spring boot starters in an application, how would you use them in a new service? could you copy, paste, and change the artifact id? or, could you remove unused dependencies and clean up properties files and java classes? although this process works, it involves manual labor that is tedious and error-prone.
in this guide, i will describe how to implement and use a custom maven archetype, which uses a custom spring boot starter, integrated into a multi-module maven setup to automate new projects generation.
requirements
- java 7 or 8
- maven 3.2+
create asimio-api-archetype maven module
first, let’s add a new module to the maven parent pom found at custom spring boot starter’s parent module :
parent
pom.xml
:
this is done so that the maven archetype gets built as part of any change to any module of the custom spring boot starter .
now, let’s create the new maven module asimio-api-archetype:
i would suggest implementing a proof of concept or demo application like asimio-api-starter-demo , discussed while creating an application using a custom spring boot starter , and use some of its java classes and other files as the prototype for this archetype. the resulting folder structure should be similar to:
creating a custom maven archetype to generate spring boot applications with a common set of components
its pom file looks very simple.
pom.xml
:
this archetype gets built as part of a maven multi-module setup, where the modules version, dependencies, etc. are handled in the parent pom.
next comes the archetype descriptor file:
src/main/resources/meta-inf/maven/archetype.xml
:
according to the
documentation
, the
id
should match the
artifactid,
as found in
pom.xml
.
in the archetype metadata file, you describe the properties and file sets that this maven archetype uses and processes:
src/main/resources/meta-inf/maven/archetype-metadata.xml
:
in this specific case, default values will be used, if they are not specified in the command to generating a project:
archetype property | description |
archetypeversion
|
the version of the archetype to use a prototype to generate a maven project, defaulting to release |
groupid
|
the group id of the maven project to be generated, defaulting to com.asimio.api |
artifactid
|
the artifact id of the maven project to be generated, without a default value |
version
|
the version of the maven project to be generated, defaulting to 0-snapshot |
a
packaged
fileset means that the included files will be generated into a folder structure prepended by the
package
property (defaulting to the
groupid
). for instance, if you use
-dgroupid=com.acme
to create a project from this archetype, the java files will be generated in
src/main/java/com/acme/
.
a
filtered
fileset means that the included files will be processed as
velocity
templates, expressions will be evaluated, variables will be replaced, etc.. if
filtered
is false, files will be copied as is.
archetype resources files
src/main/resources/archetype-resources
is where you put the prototype files used as the source to generate a new application. they include pom.xml, java classes, properties files, test classes, etc.
let’s take a look at:
src/main/resources/archetype-resources/src/main/java/rest/v1/impl/helloresourceimpl.java
:
notice a
${groupid}
velocity variable? that’s the why
filtered
was set to true for the fileset, including
src/main/java
in the
archetype metadata file
. once this folder is processed during application generation, assuming the
groupid
property was
com.acme
, the generated java class should look like:
building the archetype
lets build and install this maven archetype locally so that it could be found in (
~/.m2/repository
) when generating a new spring boot-based service:
now, let's install version
1.0.4
:
a better choice would be to deploy the archetype artifact to a maven repository manager like nexusor artifactory or to an aws s3 bucket for the archetype to be reused outside of your development station.
i can’t stress the importance of generating an application using this archeype as part of your ci / cd pipeline enough. i strongly believe a change to the archetype or any maven module included as a dependency, triggering a new build, should also trigger generating an application using said archetype. this will be done by and building it using the
mvn clean package
to be sure generated services won’t fail. if you don’t do so, it’s very likely that, at some point, the archetype is going to generate applications that either can't compile or tests that will fail.
generating a service from a maven archetype
let’s generate a project named
asimio-api-demo
:
some vm arguments are explained below:
archetypegroupid
|
the group id as defined in the archetype’s pom.xml . |
archetypeartifactid
|
the artifact id as defined in the archetype’s pom.xml . |
archetypeversion
|
the version of the archetype to use, optional in this case because it was set to release in archetype-metadata.xml . |
groupid
|
the group id of the new project, optional in this case because it was set to com.asimio.api in archetype-metadata.xml . |
dartifactid
|
the artifact id of the new project. |
interactivemode
|
setting it to false prevents maven from prompting to user to enter values to the previously described archetype properties , reading them instead from the command line or properties file. |
now, lets build it:
now, you have a new spring boot-based application, generated from a custom maven archetype , integrating spring boot, apache cxf and swagger via a custom spring boot starter with a handful of passing unit and integration tests. but, it could have included a common set of components, such as servlets, filters, listeners , support for fault tolerance, logging, tracing, exception handling, etc.
use "release" with caution
if you look at the newly created application
asimio-api-demo
’s
pom.xml
:
it includes one release dependency to keep this guide and series short, but it’s expected to include many in-house release artifacts. a change to any of these dependencies will impact the applications that use them.
if the asimio-cxf-swagger-springboot-starter artifact is updated, the next time asimio-api-demo gets built, even without any modification, it will bundle a new version. there is a risk in doing so, — it’s a trade-off.
with a release version, applications get new functionality and bug fixes without any change to its pom file. but, a change to the signature of a public method in the dependency will also break the applications.
on the other hand, if an application uses a specific version, such as
1.0.4
, there is no risk in it failing. this is because the library keeps getting updated, but the application won’t get new functionality from this library either. there might be a reluctance to uplift a dependency to
5.0.16
two years after
1.0.4
was released.
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 is published, sign up to the newsletter .
source code
accompanying source code for this blog post can be found at:
references
Published at DZone with permission of Orlando Otero, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments