Table of Contents
This section provides a brief overview of the Spring Initializr reference documentation: think of it as map for the rest of the document. Some sections are targeted to a specific audience so this reference guide is not meant to be read in a linear fashion.
Spring Initializr provides a simple web UI to configure the project to generate and endpoints that you can use via plain HTTP: you can see our default instance at start.spring.io. The service allows you to customize the project to generate: the build system and its coordinates, the language and version, the packaging and finally the dependencies to add to the project. The latter is a core concept: based on the chosen Spring Boot version, a set of dependencies can be chosen, usually Spring Boot starters, that will have a concrete impact on your application. More details in the Part II, “User Guide” section.
You can easily create your own instance of the Initializr, by using the jars as libraries in your own app. There is minimal code involved and the service has a very rich configuration structure, allowing you to define not only the values of various project attributes but also the list of dependencies and the constraints to apply to them. If that sounds interesting, then Part III, “Configuration Guide” has all the details you need. You might only want to modify an existing instance of the Initializr, e.g. to add a new dependency type, or update the version of an existing one. For those and other simple and common use cases check out Chapter 8, ‘How-to’ guides.
The Initializr also provides an extensible API to generate quickstart projects, and to inspect the metadata used to generate projects, for instance to list the available dependencies and versions. The API can be used standalone or embedded in other tools (e.g. it is used in Spring Tool Suite, and in the IntelliJ IDEA and Netbeans plugins for Spring Boot). These features are covered in Part IV, “API Guide”.
The Spring Initializr reference guide is available as html. The latest copy is available at docs.spring.io/initializr/docs/current/reference.
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
Having trouble with Spring Initializr, We’d like to help!
Note | |
---|---|
All of Spring Initializr is open source, including the documentation! If you find problems with the docs; or if you just want to improve them, please get involved. |
If you’re wondering how to use start.spring.io or what features are available, this section is for you! You’ll find the various way you can interact with the service and get a better insight at what you can do with it.
Let’s create a first project and discover the various options that you can use to tune it.
Go to start.spring.io, change the Group
field from "com.example" to "org.acme"
and put the focus in the Dependencies
field on the right hand side. If you type "web",
you will see a list of matching choices with that simple criteria. Use the mouse or the
arrow keys and Enter
to select the "Web" starter.
Your browser should now be in this state:
Note | |
---|---|
The Spring Boot version above probably doesn’t match the one you have. As we will see later, start.spring.io is continuously updated as new Spring Boot versions are published and the service uses the latest version by default. |
Click on Generate Project
, this downloads a zip file containing a Maven project with
the following structure:
mvnw mvnw.cmd pom.xml src ├── main │ ├── java │ │ └── org │ │ └── acme │ │ └── DemoApplication.java │ └── resources │ ├── application.properties │ ├── static │ └── templates └── test └── java └── org └── acme └── DemoApplicationTests.java
A typical project generated by Spring Initializr contains a Spring Boot application
(DemoApplication
), a test and an empty configuration. If you run the main
method
of DemoApplication
, you’ll see an "empty" spring boot app starting on localhost:8080.
Because Spring Initializr has detected it is a web application, a static
and templates
directories have been created to hold your static resources and ui templates.
Also, a Maven wrapper is automatically included so that you don’t have to install Maven to
run this project (you can build it with ./mvnw install
). If you prefer, you can select
Gradle instead in the first drop down list at the top of the screen. This will generate a
Gradle-based project instead that also contains a wrapper if you don’t have Gradle
installed (build it with ./gradlew build
).
Next to the Generate Project
you’ll find a "Switch to the full version" link. If you
click on that, you’ll see all the available options. Let’s browse through them quickly:
groupId
attribute in Apache Maven). Also infers the root package name to use.artifactId
attribute in Apache Maven). Also infers the name of the projectmy-app
, the generated project
will have a MyAppApplication
classIf you keep on scrolling, you’ll discover all the dependencies that you can find using the search box on the right. You’ll probably notice that some dependencies are greyed out in the UI, meaning that they aren’t available because they require a specific Spring Boot version. We’ll tackle that in the next section.
The UI allows you to select the Spring Boot version you want to use. You may want to be conservative and keep the default which corresponds at all times to the latest stable release. Or you may want to chose a milestone or snapshot of the next major version. Either way, you’ll notice that certain dependencies become available and others aren’t anymore when you change the version.
If you are searching for a dependency that you know to be available and you get no result, it’s worth looking in the advanced section if that dependency is available in the Spring Boot version that is currently selected.
You may find it is not the case with a message that looks like the following:
requires Spring Boot >=1.0.0.RELEASE and <1.5.0.RC1
Concretely, this defines a "version range" that states the dependency is deprecated and is no longer available as of Spring Boot 1.5. You may want to check the release notes of the related project to understand what your migration path can be. Alternatively, the message could be:
requires Spring Boot >=2.0.0.RELEASE
That version range means the dependency is not available with the current Spring Boot generation. Obviously, if you select Spring Boot 2.0 (or later if available), you’ll be able to select that dependency.
The Initializr service is configured to offer default values so that you can generate a new project with minimum fuss. Maybe you are a Kotlin fan? Or a Gradle fan? Currently start.spring.io defaults to Java and Maven but it also allows you to tune these defaults easily.
You can share or bookmark URLs that will automatically customize form inputs. For instance, the following URL changes the default to use Kotlin and Gradle:
https://start.spring.io/#!language=kotlin&type=gradle-project
The following attributes are supported:
language
(java
, groovy
or kotlin
)javaVersion
(1.6
, 1.7
, 1.8
)type
(maven-project
, gradle-project
)packaging
(jar
, war
)groupId
artifactId
name
description
packageName
Tip | |
---|---|
The same default rules will apply if a property is overridden. For instance, if the Group is customized, it will automatically customize the root package as well. |
Note | |
---|---|
The Spring Boot version and the list of dependencies cannot be customized that way as they evolve quite frequently. |
You can also generate a project in a shell using cURL
or HTTPie
. To discover the
available options of a particular instance, simply "curl it", i.e. if you have curl
installed invoke curl start.spring.io
on the command-line (or alternatively
http start.spring.io
if you prefer to use HTTPie
).
The result is a textual representation of the capabilities of the service that are split in three sections:
First, a table that describes the available project’s types. On the default instance,
you’ll find the maven-project
and gradle-project
we’ve discussed above but you’ll
also be able to generate only a build script rather than an entire project.
Then, a table that describes the available parameters. For the most part, these are the same options as the ones available in the web UI. There are, however, a few additional ones:
applicationName
can be used to define the name of the application, disabling the
algorithm that infer it based on the name
parameterbaseDir
can be used to create a base directory in the archive so that you can extract
the generated zip without creating a directory for it firstFinally, the list of dependencies are defined. Each entry provides the identifier that you’ll have to use if you want to select the dependency, a description and the Spring Boot version range, if any.
Alongside the capabilities of the service, you’ll also find a few examples that help you understand how you can generate a project. These are obviously tailored to the client that you are using.
Let’s assume that you want to generate a "my-project.zip" project based on Spring Boot
1.5.2.RELEASE
, using the web
and devtools
dependencies (remember, those two ids are
displayed in the capabilities of the service):
$ curl https://start.spring.io/starter.zip -d dependencies=web,devtools \ -d bootVersion=1.5.2.RELEASE -o my-project.zip
If you extract my-project.zip
, you’ll notice a few differences compared to what happens
with the web UI:
my-project
(the -o
parameter has no impact on the
name of the project)The exact same project can be generated using the http
command as well:
$ http https://start.spring.io/starter.zip dependencies==web,devtools \ bootVersion==1.5.1.RELEASE -d
Note | |
---|---|
|
Spring Initializr is also integrated in all major Java IDEs and allows you to create and import a new project without having to leave the IDE for the command-line or the web UI.
The following IDEs have dedicated support:
Refer to the documentation of your favorite IDE for more details.
The spring
command line tool defines an init
command that allows you to create a
project using Spring Initializr.
This section describes how you can create your own instance of the service and tune it for your needs, and also how you can configure an existing instance. You’ll also find some advanced tips to make sure the available options are consistent with the chosen Spring Boot generation.
Spring Initializr is split across three main modules:
initializr-generator
: standalone project generation library that can be reused in
many environments (including embedded in your own project)initializr-web
: API endpoints and web interfaceinitializr-actuator
: optional module to provide statistics and metrics on project
generationBecause it contains several auto-configurations, creating your own instance is quite easy, actually you could get started using Spring Initializr itself to generate a starting point!
Create a new project with the web
dependency and add the following dependency:
<dependency> <groupId>io.spring.initializr</groupId> <artifactId>initializr-web</artifactId> <version>0.4.0.RELEASE</version> </dependency>
Or if you are using Gradle:
compile("io.spring.initializr:initializr-web:0.4.0.RELEASE")
If you start the application, you’ll see the familiar interface but none of the drop down lists have values (except the one for the Spring Boot version, we will come back to that later). In the rest of this section, we will configure those basic settings.
Tip | |
---|---|
Most of the settings are configured via |
Most of the drop-down lists are configured via a simple list-based structure where each
entry has an id
, a name
and whether that entry is the default or not. If no name
is
provided, the id
is used instead.
Let’s configure the languages and the Java versions we want to support:
initializr: javaVersions: - id: 9 default: false - id: 1.8 default: true languages: - name: Java id: java default: true - name: Kotlin id: kotlin default: false
If you click on the "Switch to the full version" link, the two drop down lists now offer the options and default values defined above.
Spring Initializr supports java
, groovy
and kotlin
and additional languages can be
added in your own customization.
The available packagings are also configurable that way:
initializr: packagings: - name: Jar id: jar default: true - name: War id: war default: false
These two packaging types are the only one explicitly supported at the moment.
If you look at the project home page for Spring Boot, the latest versions are displayed. And you’ve probably noticed that they match the drop down list that you automatically get with a default instance of the Initializr. The reason for that is that Spring Initializr calls an API on spring.io to retrieve the latest versions automatically. This makes sure that you always get the latest available versions.
If you are behind a proxy, or need to customize the RestTemplate
that is used behind the
scenes, you can define a RestTemplateCustomizer
bean in your configuration. For more
details, check the
documentation.
If you don’t want the version to be upgraded automatically, you need to override the
InitializrMetadataProvider
bean to provide your own metadata for the service. For
instance, you could swap to an implementation that always returns the contents of static
application.yml
:
@Bean public InitializrMetadataProvider initializrMetadataProvider( InitializrProperties properties) { InitializrMetadata metadata = InitializrMetadataBuilder .fromInitializrProperties(properties).build(); return new SimpleInitializrMetadataProvider(metadata); }
The thing to remember is that, by default, you don’t have to worry about upgrading your instance when a new Spring Boot version is released. However, you may need to configure caching to avoid requesting that service too often.
The available project types mostly define the structure of the generated project and its build system. Once a project type is selected, the related action is invoked to generate the project.
By default, Spring Initializr exposes the following resources (all accessed via HTTP GET):
/pom.xml
generate a Maven pom.xml
/build.gradle
generate a Gradle build/starter.zip
generate a complete project structure archived in a zip/starter.tgz
generate a complete project structure archived in a tgzEach type also defines one or more tags that provides additional metadata entries to qualify the entry. The following standard tags exist:
build
: the name of the build system to use (e.g. maven
, gradle
)format
: the format of the project (e.g. project
for a full project, build
for just
a build file).By default, the HTML UI filters all the available types to only display the ones that have
a format
tag with value project
.
You can of course implement additional endpoints that generate whatever project structure you need but, for now, we’ll simply configure our instance to generate a Gradle or a Maven project:
initializr: types: - name: Maven Project id: maven-project description: Generate a Maven based project archive tags: build: maven format: project default: true action: /starter.zip - name: Gradle Project id: gradle-project description: Generate a Gradle based project archive tags: build: gradle format: project default: false action: /starter.zip
Note | |
---|---|
If you intend to build a custom client against your service, you can add as many tags as you want, and process them in the client in a way that makes sense for your users. |
For instance, the spring boot CLI uses them as a shortcut to the full type id. So rather than having to create a Gradle project as follows:
$ spring init --type=gradle-project my-project.zip
You can simply define a more convenient build parameter:
$ spring init --build=gradle my-project.zip
With that configuration, you should be able to generate your first project, congratulations! Let’s now add dependencies so that you can start searching for them.
The most basic dependency
is composed of:
id
used in clients to refer to itgroupId
and artifactId
)name
(used in the UI and the search results)description
can (and should) be added to provide more information about the
dependencySpring Initializr automatically considers that a dependency without maven coordinates
defines an official Spring Boot starter. In such a case, the id
is used to infer the
artifactId
.
For instance, the following configures the spring-boot-starter-web
Starter:
initializr: dependencies: - name: Web content: - name: Web id: web description: Full-stack web development with Tomcat and Spring MVC
Each dependency is contained in a group that gathers dependencies sharing a common
surface area or any other form of grouping. In the example above, a Web
group holds our
unique dependency. A group can also provide default values for various settings, see the
dedicated how-to for more details.
In our spring-boot-starter-web
example above, the dependency is managed by Spring
Boot so there is no need to provide a version
attribute for it. You’ll surely need to
define additional dependencies that are not provided by Spring Boot and we strongly
recommend you to use a Bill Of Materials (or BOM).
If no BOM is available you can specify a version directly:
initializr: dependencies: - name: Tech content: - name: Acme id: acme groupId: com.example.acme artifactId: acme version: 1.2.0.RELEASE description: A solid description for this dependency
If you add this configuration and search for "acme" (or "solid"), you’ll find this extra entry; generating a maven project with it should add the following to the pom:
<dependency> <groupId>com.example.acme</groupId> <artifactId>acme</artifactId> <version>1.2.0.RELEASE</version> </dependency>
The rest of this section will detail the other configuration options.
By default, a dependency is available regardless of the Spring Boot version you have
selected. If you need to restrict a dependency to a certain Spring Boot generation you
can add a versionRange
attribute to its definition. A version range is a range of
versions of Spring Boot which are valid in combination with it. The versions are not
applied to the dependency itself, but rather used to filter out the dependency, or modify
it, when different versions of Spring Boot are selected for the generated project.
A typical version is composed of four parts: a major revision, a minor revision, a patch revision and a qualifier. Qualifiers are ordered as follows:
M
for milestones (e.g. 2.0.0.M1
is the first milestone of the upcoming 2.0.0
release): can be seen as "beta" releaseRC
for release candidates (e.g. 2.0.0.RC2
is the second release candidate of
upcoming 2.0.0 release)RELEASE
for general availability (e.g. 2.0.0.RELEASE
is 2.0.0 proper)BUILD-SNAPSHOT
for development build (2.1.0.BUILD-SNAPSHOT
represents the latest
available development build of the upcoming 2.1.0 release).Tip | |
---|---|
snapshots are in a bit special in that scheme as they always represents the "latest
state" of a release. |
A version range has a lower and an upper bound, and if the bound is inclusive it is
denoted as a square bracket ([
or ]
), otherwise it is exclusive and denoted by a
parenthesis ((
or )
). For instance [1.1.6.RELEASE,1.3.0.M1)
means from all versions
from 1.1.6.RELEASE
up to but not including 1.3.0.M1
(concretely no including the
1.3.x
line and after).
A version range can be a single value, e.g. 1.2.0.RELEASE
, which is short for "this
version or greater". It is an inclusive lower bound with an implied infinite upper bound.
If you need to specify "the latest release" in a given line, you can use a x
rather than
an hard-coded version. For instance, 1.4.x.BUILD-SNAPSHOT
is the latest snapshot build
of the 1.4.x line. For instance, if you want to restrict a dependency from 1.1.0.RELEASE
to the latest stable release of the 1.3.x line, you’d use [1.1.0.RELEASE,1.3.x.RELEASE]
.
Snapshots are naturally ordered higher than released versions, so if you are looking to
match a dependency to only the latest snapshots of Spring Boot, you could use a version
range of 1.5.x.BUILD-SNAPSHOT
(assuming 1.5 was the latest).
Tip | |
---|---|
Remember to quote the values of a version range in YAML configuration files (with double quotes ""). |
See below in the section on linking versions for more examples and idioms.
If the dependency is not available on Maven Central (or whatever default repository that
is configured on your end), you can also add a reference to a repository. A repository is
declared at the top level (under env
) and given an id via the key in the configuration:
initializr: env: repositories: my-api-repo-1: name: repo1 url: http://example.com/repo1
Once defined, the repository can then be referred back to in a dependency
initializr: dependencies: - name: Other content: - name: Foo groupId: org.acme artifactId: foo version: 1.3.5 repository: my-api-repo-1
It is usually preferable to have a BOM for every dependency, and attach the repository to the BOM instead.
Tip | |
---|---|
The snapshots and milestones repositories on |
A Bill of Materials (BOM) is a special pom.xml
, deployed to a Maven repository, and used
to control dependency management for a set of related artifacts. In the Spring Boot
ecosystem we usually use the suffix -dependencies
on the artifact id of a BOM. In other
projects we see -bom
. It is recommended that all dependencies are included in a BOM of
some sort, since they provide nice high level features for users of the dependency. It is
also important that 2 BOMs used in a project do not contain conflicting versions for the
same dependency, so the best practice is to look at the existing BOMs in the Initializr
before you add a new one, and make sure that you aren’t adding a conflict.
In the Initializr a BOM is declared at the env
level, and given an id through the
configuration key. Example:
initializr: env: boms: my-api-bom: groupId: org.acme artifactId: my-api-dependencies version: 1.0.0.RELEASE repositories: my-api-repo-1
If a BOM requires a special, non-default repository, then it can be referred to here, instead of having to explicitly list the repository again for each dependency. A dependency, or a dependency group, can declare that it requires the use of one or more BOMs by referring to the id:
initializr: dependencies: - name: Other content: - name: My API id : my-api groupId: org.acme artifactId: my-api bom: my-api-bom
In addition to a Spring Boot version range for the dependency or a BOM, you can configure the version relationships at a finer grained level using version mappings. A dependency or BOM has a list of "mappings", each of which consists of a version range, and a set of one or more dependency properties to override for those versions of Spring Boot. You can use a mapping to switch the version of a dependency, or (better) the BOM, or to change its artifact id (if the project changed its packaging) for instance.
Here’s an example of a BOM with mappings:
initializr: env: boms: cloud-bom: groupId: com.example.foo artifactId: acme-foo-dependencies mappings: - versionRange: "[1.2.3.RELEASE,1.3.0.RELEASE)" version: Arcturus.SR6 - versionRange: "[1.3.0.RELEASE,1.4.0.RELEASE)" version: Botein.SR7 - versionRange: "[1.4.0.RELEASE,1.5.x.RELEASE)" version: Castor.SR6 - versionRange: "[1.5.0.RELEASE,1.5.x.BUILD-SNAPSHOT)" version: Diadem.RC1 repositories: spring-milestones - versionRange: "1.5.x.BUILD-SNAPSHOT" version: Diadem.BUILD-SNAPSHOT repositories: spring-snapshots,spring-milestones
The primary use case here is to map Spring Boot versions to the preferred or supported versions of the Foo project. You can also see that for the milestone and snapshot BOMs, additional repositories are declared because those artifacts are not in the default repository.
Tip | |
---|---|
We also use the |
See below in the section on linking versions for more examples.
A dependency has an id (e.g. "web-services"), but it could be necessary to provide a new id and still be able to serve request from client using the now deprecated id. To do so, an alias can be defined for ths dependency;
initializr: dependencies: - name: Other content: - name: Web Services id: web-services aliases: - ws
The same project can now be generated with dependencies=ws
or
dependencies=web-services
.
A "facet" is a label on a dependency which is used to drive a code modification in the
generated project. In the standard Initializr generator, there is only one facet that is
actually used (web
), but custom installations might choose to use it for their own
purposes. The web
facet is used to drive the inclusion of spring-boot-starter-web
if
any other dependency with that facet is included. The value of the "facets" property of a
dependency is a list of strings.
Links can be used to provide descriptive and hyperlink data to guide to user on how to
learn more about a dependency. A dependency has a "links" property which is a list of
Link
. Each link has a rel
label to identify it, an href
and an optional (but
recommended) description
.
The following rel
value are currently officially supported:
guide
: the link points to a guide describing how to use the related dependency. It
can be a tutorial, a how-to or typically a guide available on spring.io/guidesThe url can be templated if its actual value can change according to the environment. An
URL parameter is specified with curly braces, something like
example.com/doc/{bootVersion}/section
defines a bootVersion
parameter.
The following attributes are currently supported:
bootVersion
: the Spring Boot version that is currently activeHere is an example that adds two links to the acme
dependency:
initializr: dependencies: - name: Tech content: - name: Acme id: acme groupId: com.example.acme artifactId: acme version: 1.2.0.RELEASE description: A solid description for this dependency links: - rel: guide href: https://com.example/guides/acme/ description: Getting started with Acme - rel: reference href: http://docs.example.com/acme/html
Each dependency can have a weight
(a number >=0) and also keywords
(list of string)
that are used to prioritize them in the search feature in the web UI. If you type one of
the keywords into the "Dependencies" box in the UI, those dependencies will be listed
below, in order of decreasing weight, if they have one (unweighted dependencies come
last).
This section provides answers to some common ‘how do I do that…’ type of questions that often arise when configuring Spring Initializr.
To add a new dependency, first identify the Maven co-ordinates of the dependency you want
to add (groupId:artifactId:version
) and then check which versions of Spring Boot it works
with. If there are multiple versions that work with different versions of Spring Boot,
then that’s fine too.
env
section (see Section 7.5, “Configuring Bill of Materials”).Sometimes it happens that the BOM that normally manages your dependency version is in
conflict with the newest version. Or maybe this is the case for only a range of Spring
Boot versions. Or maybe there just is no BOM, or it’s not worth creating one for just one
dependency. In these cases you can specify the version manually for a dependency either
at the top level, or in a
version mapping. At the top level it looks like this (just
a version
property in a dependency):
initializr: dependencies: - name: Tech content: - name: Acme id: acme groupId: com.example.acme artifactId: acme version: 1.2.0.RELEASE description: A solid description for this dependency
If your dependency requires a specific version of Spring Boot, ot different versions of Spring Boot require different versions of your dependency there are a couple of mechanisms to configure that.
The simplest is to put a versionRange
in the dependency declaration. This is a range of
versions of Spring Boot, not of your dependency. For example:
initializr: dependencies: - name: Stuff content: - name: Foo id: foo ... versionRange: 1.2.0.M1 - name: Bar id: bar ... versionRange: "[1.5.0.RC1,2.0.0.M1)"
In this example Foo
is available for Spring Boot 1.2.0 (or any milestone of 1.2.0) or
greater, and Bar
is available for Spring Boot 1.5.0 up to, but not including 2.0.0.
If different versions of your dependency work with different versions of Spring Boot,
that’s when you need the mappings
property. A mapping is a combination of a
versionRange
and some or all of the other properties of the dependency, overriding
the values defined at the top level. For example:
initializr: dependencies: - name: Stuff content: - name: Foo id: foo groupId: org.acme.foo artifactId: foo-spring-boot-starter versionRange: 1.3.0.RELEASE bom: cloud-task-bom mappings: - versionRange: "[1.3.0.RELEASE,1.3.x.RELEASE]" artifactId: foo-starter - versionRange: "1.4.0.RELEASE"
In this example, The artifact of foo
was changed to foo-spring-boot-starter
as of the
version that is compatible with Spring Boot 1.4. This mapping instruct that if Spring Boot
1.3.x is selected, the artifact Id should be set to foo-starter
.
A mapping can also be applied to a BOM declaration. For example:
initializr: env: boms: my-api-bom: groupId: org.acme artifactId: my-api-bom additionalBoms: ['my-api-dependencies-bom'] mappings: - versionRange: "[1.0.0.RELEASE,1.1.6.RELEASE)" version: 1.0.0.RELEASE repositories: my-api-repo-1 - versionRange: "1.2.1.RELEASE" version: 2.0.0.RELEASE repositories: my-api-repo-2
In this example Spring Boot versions up to 1.1.6 select version 1.0.0 of the BOM, and set a different repository. Spring Boot versions 1.2.1 and above select 2.0.0 of the BOM and yet another repository.
A dependency, or a BOM, might require the use of a specific repository, if the default one (usually Maven Central) does not contain the artifacts. Normally, the best place to declare that is in the BOM configuration, but if there isn’t a BOM then you can put it in the dependency itself. You can also use a Spring Boot version mapping to override the default repository for a dependency or BOM.
If a dependency does not stand on its own (and specifically if it does not depend on an existing Spring Boot starter) you can flag it as a "non starter":
initializr: dependencies: - name: Stuff content: - name: Lib id: lib groupId: com.acme artifactId: lib starter:false
When a project is generated that only has dependencies with this flag set, then the base Spring Boot starter is added as well.
A dependency group is a hint for user interface implementations, to group things together
for users when they are selecting dependencies. It is also a convenient way to share
settings between dependencies because every dependency inherits all the settings. The most
common settings in a group are the groupId
, versionRange
and bom
:
initializr: dependencies: - name: Stuff bom: stuff-bom versionRange: "[1.3.0.RELEASE,2.0.0.M1)" content: ...
These dependencies, by default, will be available only for Spring Boot versions 1.3 up to
2.0 (excluded) and will bring in the stuff-bom
BOM.
If you use the service, you’ll notice that the logs have lots of entries with the message
Fetching boot metadata from spring.io/project_metadata/spring-boot
. To avoid
checking for the latest Spring Boot versions too often, you should enable caching on your
service. Spring Initializr has some auto-configuration to apply the proper caches if you
are willing to use a JCache (JSR-107) implementation.
Add the javax.cache:cache-api
and your favorite JCache implementation and simply enable
caching by adding @EnableCaching
to your @SpringBootApplication
. For instance, you
could use ehcache
by adding the following:
<dependency> <groupId>javax.cache</groupId> <artifactId>cache-api</artifactId> </dependency> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency>
Or if you are using Gradle:
compile("javax.cache:cache-api") compile("org.ehcache:ehcache")
You’ll notice that the log entry is much more rare. If you do not want to use JSR-107, you should configure the cache yourselves. Here are the caches used by the application (each one will require some configuration to get it working):
Table 9.1. Cache configuration
cache name | Description |
---|---|
| Cache the full metadata of the service. When the metadata expires, it is fully resolved again (including a check on spring.io for the latest Spring Boot versions). Adapt the expiration settings accordingly. |
| Cache dependency-specific metadata. |
| Cache resources that are used to generate projects. |
This section describes the hal/json structure of the metadata exposed by the initializr. Such metadata can be used by third party clients to provide a list of options and default settings that can be used to request the creation of a project.
A third-party client is advised to set a User-Agent
header for each request
sent to the service. A good structure for a user agent is clientId/clientVersion
(i.e. foo/1.2.0
for the "foo" client and version 1.2.0
).
Any third party client can retrieve the capabilities of the service by issuing a
GET
on the root URL using the following Accept
header:
application/vnd.initializr.v2.1+json
. Please note that the metadata may evolve in a
non backward compatible way in the future so adding this header ensures the service
returns the metadata format you expect.
This is an example output for a service running at start.spring.io
:
request.
GET / HTTP/1.1 Accept: application/vnd.initializr.v2.1+json Host: start.spring.io
response.
HTTP/1.1 200 OK ETag: "ecf44f6b0b52a89b89fda507cb5848bd" Content-Type: application/vnd.initializr.v2.1+json Cache-Control: max-age=604800 Content-Length: 4877 { "bootVersion" : { "default" : "1.1.4.RELEASE", "values" : [ { "name" : "Latest SNAPSHOT", "id" : "1.2.0.BUILD-SNAPSHOT" }, { "name" : "1.1.4", "id" : "1.1.4.RELEASE" }, { "name" : "1.0.2", "id" : "1.0.2.RELEASE" } ], "type" : "single-select" }, "_links" : { "gradle-build" : { "templated" : true, "href" : "https://start.spring.io/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}" }, "maven-build" : { "templated" : true, "href" : "https://start.spring.io/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}" }, "gradle-project" : { "templated" : true, "href" : "https://start.spring.io/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}" }, "maven-project" : { "templated" : true, "href" : "https://start.spring.io/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}" }, "dependencies" : { "templated" : true, "href" : "https://start.spring.io/dependencies{?bootVersion}" } }, "javaVersion" : { "default" : "1.8", "values" : [ { "name" : "1.6", "id" : "1.6" }, { "name" : "1.7", "id" : "1.7" }, { "name" : "1.8", "id" : "1.8" } ], "type" : "single-select" }, "groupId" : { "default" : "com.example", "type" : "text" }, "description" : { "default" : "Demo project for Spring Boot", "type" : "text" }, "packaging" : { "default" : "jar", "values" : [ { "name" : "Jar", "id" : "jar" }, { "name" : "War", "id" : "war" } ], "type" : "single-select" }, "language" : { "default" : "java", "values" : [ { "name" : "Groovy", "id" : "groovy" }, { "name" : "Java", "id" : "java" }, { "name" : "Kotlin", "id" : "kotlin" } ], "type" : "single-select" }, "type" : { "default" : "maven-project", "values" : [ { "name" : "Maven POM", "action" : "/pom.xml", "id" : "maven-build", "tags" : { "build" : "maven", "format" : "build" } }, { "name" : "Maven Project", "action" : "/starter.zip", "id" : "maven-project", "tags" : { "build" : "maven", "format" : "project" } }, { "name" : "Gradle Config", "action" : "/build.gradle", "id" : "gradle-build", "tags" : { "build" : "gradle", "format" : "build" } }, { "name" : "Gradle Project", "action" : "/starter.zip", "id" : "gradle-project", "tags" : { "build" : "gradle", "format" : "project" } } ], "type" : "action" }, "version" : { "default" : "0.0.1-SNAPSHOT", "type" : "text" }, "dependencies" : { "values" : [ { "values" : [ { "_links" : { "reference" : { "href" : "https://example.com/doc" }, "guide" : { "href" : "https://example.com/guide", "title" : "Building a RESTful Web Service" } }, "name" : "Web", "description" : "Web dependency description", "id" : "web" }, { "name" : "Security", "id" : "security" }, { "name" : "Data JPA", "id" : "data-jpa" } ], "name" : "Core" }, { "values" : [ { "_links" : { "reference" : { "templated" : true, "href" : "https://example.com/{bootVersion}/doc" }, "guide" : [ { "href" : "https://example.com/guide1" }, { "href" : "https://example.com/guide2", "title" : "Some guide for foo" } ] }, "name" : "Foo", "id" : "org.acme:foo" }, { "name" : "Bar", "id" : "org.acme:bar" }, { "versionRange" : "1.2.0.BUILD-SNAPSHOT", "name" : "Biz", "id" : "org.acme:biz" }, { "versionRange" : "[1.1.4.RELEASE,1.2.0.BUILD-SNAPSHOT)", "name" : "Bur", "id" : "org.acme:bur" }, { "name" : "My API", "id" : "my-api" } ], "name" : "Other" } ], "type" : "hierarchical-multi-select" }, "name" : { "default" : "demo", "type" : "text" }, "artifactId" : { "default" : "demo", "type" : "text" }, "packageName" : { "default" : "com.example.demo", "type" : "text" } }
The current capabilities are the following:
groupId
, artifactId
, version
, name
,
description
and packageName
.Each top-level attribute (i.e. capability) has a standard format:
type
attribute that defines the semantic of the attribute (see below).default
attribute that defines either the default value or the reference to
the default value.values
attribute that defines the set of acceptable values (if any). This can
be hierarchical (with values
being held in values
). Each item in a values
array
can have an id
, name
and description
).The following attribute type
are supported:
text
: defines a simple text value with no option.single-select
: defines a simple value to be chosen amongst the specified options.hierarchical-multi-select
: defines a hierarchical set of values (values in
values) with the ability to select multiple values.action
: a special type that defines the attribute defining the action to use.Each action is defined as a HAL-compliant URL. For instance, the maven-project
type
templated URL is defined as follows:
Type link example.
{ "templated" : true, "href" : "https://start.spring.io/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}" }
You can use Spring HATEOAS and the UriTemplate
helper in particular to generate an
URI from template variables. Note that the variables match the name of top-level
attribute in the metadata document. If you can’t parse such URI, the action
attribute of each type gives you the root action to invoke on the server. This
requires more manual handling on your end.
A dependency is usually the coordinates of a starter module but it can be just a regular dependency. A typical dependency structure looks like this:
{ "name": "Display name", "id": "org.acme.project:project-starter-foo", "description": "What starter foo does" }
The name is used as a display name to be shown in whatever UI used by the remote
client. The id can be anything, really as the actual dependency definition is
defined through configuration. If no id is defined, a default one is built using the
groupId
and artifactId
of the dependency. Note in particular that the version is
never used as part of an automatic id.
Each dependency belongs to a group. The idea of the group is to gather similar
dependencies and order them. Here is a value containing the core
group to
illustrates the feature:
Dependency group example.
{ "values" : [ { "_links" : { "reference" : { "href" : "https://example.com/doc" }, "guide" : { "href" : "https://example.com/guide", "title" : "Building a RESTful Web Service" } }, "name" : "Web", "description" : "Web dependency description", "id" : "web" }, { "name" : "Security", "id" : "security" }, { "name" : "Data JPA", "id" : "data-jpa" } ], "name" : "Core" }
Each dependency can have links (in a HAL-compliant format). Links are grouped by
"relations" that provide a semantic to the link. A link can also have a title and
its URI can be templated. At the moment, the only valid parameter is bootVersion
.
The official relations are:
guide
: link to an how-to or guide that explain how to get startedreference
: link to a section of a reference guide (documentation)The type
element defines what kind of project can be generated and how. For
instance, if the service exposes the capability to generate a Maven project, this
would look like this:
Project type example.
{ "name" : "Maven POM", "action" : "/pom.xml", "id" : "maven-build", "tags" : { "build" : "maven", "format" : "build" } }
You should not rely on the output format depending that information. Always use the
response headers that define a Content-Type
and also a Content-Disposition
header.
Note that each id has a related HAL-compliant link that can be used to generate a
proper URI based on template variables. The top-level type
has, as any other
attribute, a default
attribute that is a hint to select what the service consider
to be a good default.
The action
attribute defines the endpoint the client should contact to actually
generate a project of that type if you can’t use the HAL-compliant url.
The tags
object is used to categorize the project type and give hints to 3rd
party client. For instance, the build tag defines the build system the project is
going to use and the format tag defines the format of the generated content (i.e.
here a complete project vs. a build file. Note that the Content-type
header of the
reply provides additional metadata).
The packaging
element defines the kind of project that should be generated.
Packaging example.
{ "name" : "Jar", "id" : "jar" }
The obvious values for this element are jar
and war
.
The javaVersion
element provides a list of possible java versions for the project:
Java example.
{ "name" : "1.6", "id" : "1.6" }
The language
element provides a list of possible languages for the project:
Language example.
{ "name" : "Groovy", "id" : "groovy" }
The Initializr project publishes WireMock stubs for all the JSON responses that are tested in the project. If you are writing a client for the Initializr service, you can use these stubs to test your own code. You can consume them with the raw Wiremock APIs, or via some features of Spring Cloud Contract.
Tip | |
---|---|
WireMock is an embedded web server that analyses incoming requests and chooses stub responses based on matching some rules (e.g. a specific header value). So if you send it a request which matches one of its stubs, it will send you a response as if it was a real Initializr service, and you can use that to do full stack integration testing of your client. |
A convenient way to consume the stubs in your project is to add a test dependency:
<dependency> <groupId>io.spring.initializr</groupId> <artifactId>initializr-web</artifactId> <classifier>stubs</classifier> <version>{project-version}</version> <scope>test</scope> </dependency>
and then pull the stubs from the classpath. In a Spring Boot application, using Spring Cloud Contract, you can start a WireMock server and register all the stubs with it like this:
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureWireMock(port = 0, stubs="classpath:META-INF/io.spring.initializr/initializr-web/0.4.0.RELEASE") public class ClientApplicationTests { @Value("${wiremock.server.port}") private int port; ... }
The Wiremock features come with Spring Cloud Contract Wiremock:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-wiremock</artifactId> <scope>test</scope> </dependency>
Tip | |
---|---|
This dependency is managed by the |
Alternatively you can configure the stub runner to look for the artifact, using a
different Spring Cloud Contract dependency:
spring-cloud-starter-contract-stub-runner
. The example below will automatically
download, if necessary, the defined version of the initializr stubs (so you don’t need the
stubs declared as a dependency):
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-stubrunner</artifactId> <scope>test</scope> </dependency>
The test should use @AutoConfigureStubRunner
instead:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.NONE) @AutoConfigureStubRunner( ids = "io.spring.initializr:initializr-web:0.4.0.RELEASE", repositoryRoot = "https://repo.spring.io/snapshot") public class ClientApplicationTests { @Autowired private StubFinder stubFinder; ... }
Here is an example of a test that retrieves the metadata of the service. The assertions do not matter much here but it illustrates how you could integrate that in the test suite of a custom client:
public class ClientApplicationTests { @Autowired private StubFinder stubFinder; @Autowired private RestTemplate restTemplate; @Test public void testCurrentMetadata() throws IOException { RequestEntity<Void> request = RequestEntity.get(createUri("/")) .accept(MediaType.valueOf("application/vnd.initializr.v2.1+json")) .build(); ResponseEntity<String> response = this.restTemplate .exchange(request, String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); // other assertions here } private URI createUri(String path) { String url = this.stubFinder.findStubUrl("initializr-web").toString(); return URI.create(url + path); } @TestConfiguration static class Config { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.build(); } } }
Then you have a server that returns the stub of the JSON metadata
(metadataWithCurrentAcceptHeader.json
) when you send it a header
Accept:application/vnd.initializr.v2.1+json
(as recommended).
The stubs are laid out in a jar file in a form (under "**/mappings") that can be consumed
by WireMock just by setting its file source. The names of the individual stubs are the
same as the method names of the test cases that generated them in the Initializr
project. So for example there is a test case "metadataWithV2AcceptHeader" in
MainControllerIntegrationTests
that makes assertions about the response when the accept
header is application/vnd.initializr.v2.1+json
. The response is recorded in the stub,
and it will match in WireMock if the same headers and request parameters that were used in
the Initializr test case and used in the client. The method name usually summarizes what
those values are.
The stub runner, and the @AutoConfigureWireMock
in the examples above loads all the
stubs into WireMock, so you don’t necessarily need to know the names of the stubs. You can
also register stubs one by one, though, in which case it would help to scan the stubs jar
and compare the file names with the test methods. For instance, if you look in the stubs
jar, you will see a file called metadataWithV2AcceptHeader.json
and, in the
initializr-web project, a test method called metadataWithV2AcceptHeader
which generated
it.