Spring Initializr Documentation

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 an extensible API to generate JVM-based projects, and to inspect the metadata used to generate projects, for instance to list the available dependencies and versions.

The documentation is roughly divided into three parts:

You can easily create your own instance using Spring 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 Configuration Guide has all the details you need. You might only want to modify an existing instance of Spring 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 ‘How-to’ guides.

Spring Initializr also provides an extensible API to generate JVM-based 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 major IDEs such as Spring Tool Suite, IntelliJ IDEA Ultimate, Netbeans and VSCode). These features are covered in API Guide.

1. About the documentation

The Spring Initializr reference guide is available as html. The latest copy is available at docs.spring.io/initializr/docs/current/reference/html.

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.

2. Getting help

Having trouble with Spring Initializr, We’d like to help!

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.

User Guide

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 ways you can interact with the service and get a better insight at what you can do with it.

The service allows you to generate Spring Boot projects quickly. You can customize the project to generate: the build system and packaging, the language, the packaging, the coordinates, the platform version and, finally, the dependencies to add to the project. Most dependencies available on start.spring.io are Spring Boot starters which is the recommended way to add dependencies to a Spring Boot application.

3. Getting Started

Let’s create a 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 below. 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:

Browser
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:

.gitignore
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, the 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 option at the top of the screen. This will generate a Gradle-based project that also contains a wrapper which can be used if you don’t have Gradle installed (build it with ./gradlew build).

3.1. Advanced options

Below the Artifact form field, you’ll find an "Options" link. If you click on that, you’ll see all the available options. Let’s browse through them quickly:

  • Group: project coordinates (id of the project’s group, as referred by the groupId attribute in Apache Maven). Also infers the root package name to use.

  • Artifact: project coordinates (id of the artifact, as referred by the artifactId attribute in Apache Maven). Also infers the name of the project

  • Name: display name of the project that also determines the name of your Spring Boot application. For instance, if the name of your project is my-app, the generated project will have a MyAppApplication class

  • Description: description of the project

  • Package Name: root package of the project. If not specified, the value of the Group attribute is used

  • Packaging: project packaging (as referred by the concept of the same name in Apache Maven). start.spring.io can generate jar or war projects

  • Java: the Java version to use

3.2. Dependencies

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 choose 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 search for a dependency that you know to be available and you get a disabled panel, it indicates that you cannot use it with the currently selected Spring Boot version;

Requires Spring Boot >=2.0.0.RELEASE and <2.1.0.RELEASE

Concretely, this defines a "version range" that states the dependency is deprecated and is no longer available as of Spring Boot 2.1. 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.2.0.RELEASE

That version range means the dependency is not available with the selected Spring Boot generation. If you select Spring Boot 2.2 (or later if available), you’ll be able to select that dependency.

3.3. Tuning default values

A Spring 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. You can use the share action to generate the URL based on your current selection. The URL contains all attributes but you can remove the ones you’re not interested. 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:

  • Spring Boot version: platformVersion

  • Dependencies: dependencies

  • Programming language: language (java, groovy or kotlin)

  • Java version: javaVersion (1.8, 11, 12)

  • Project type: type (maven-project, gradle-project)

  • Packaging: packaging (jar, war)

  • Group: groupId

  • Artifact: artifactId

  • Name: name

  • Description: description

  • Package Name: packageName

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.
If the Spring Boot version is outdated, the UI will request you to make a choice and select a supported version.

4. Command line support

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 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 parameter

  • baseDir 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 first

Finally, 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 2.1.9.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=2.1.9.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:

  • The project will be extracted in the current directory (the web UI adds a base directory automatically with the same name as the one of the project)

  • The name of the project is not 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==2.1.9.RELEASE -d
HTTPie reads the same hint as the browser so it will store a demo.zip file in the current directory, with the same differences discussed above.

5. IDEs support

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:

  • Eclipse/STS

  • IntelliJ IDEA (Ultimate Edition)

  • NetBeans (using the NB SpringBoot plugin)

  • Microsoft VSCode

Refer to the documentation of your favorite IDE for more details.

6. Spring Boot CLI support

The spring command line tool defines an init command that allows you to create a project using Spring Initializr.

Configuration Guide

You can use Spring Initializr to create your own service that can generate JVM projects. This section describes how you can create your own service and tune it for your needs, and also how you can configure an existing service.

7. Project Generation Overview

Before getting into creating your own service, let’s take a look at the core concepts of project generation and how the library is structured to support them.

Initializr is split across several modules:

  • initializr-actuator: optional module to provide additional information and statistics on project generation.

  • initializr-bom: provides a Bill of Materials for easier dependency management in your project.

  • initializr-docs: documentation.

  • initializr-generator: core project generation library.

  • initializr-generator-spring: optional module defining the conventions for a typical Spring Boot project. Can be reused or replaced by your own conventions.

  • initializr-generator-test: test infrastructure for project generation.

  • initializr-metadata: metadata infrastructure for various aspects of the project.

  • initializr-service-sample: showcases a basic custom instance.

  • initializr-version-resolver: optional module to extract version numbers from an arbitrary POM.

  • initializr-web: web endpoints for third party clients.

To understand concepts behind project generation, let’s take a look at initializr-generator and initializr-generator-spring in a little more detail.

7.1. Initializr Generator

The initializr-generator module contains the low-level infrastructure necessary to generate JVM-based projects.

7.1.1. Project Generator

The ProjectGenerator class is the main entry point for project generation. A ProjectGenerator takes a ProjectDescription that defines a particular project to generate as well as an implementation of ProjectAssetGenerator that is responsible to generate assets based on available candidates.

A project is defined by ProjectDescription which consists of the following properties:

  • Basic coordinates such as groupId, artifactId, name, description

  • The BuildSystem and Packaging

  • The JVM Language

  • The requested dependencies, indexed by ID

  • A platform Version used by the project. This can be used to tune available dependencies according to the chosen generation.

  • The name of the application

  • The root package name

  • The base directory for the project (if different from the root)

Project generation occurs in a dedicated application context (ProjectGenerationContext), which means that for every project that is generated, the context only contains configuration and components relevant to that particular project. Candidate components for a ProjectGenerationContext are defined in @ProjectGenerationConfiguration-annotated configuration classes. These configuration classes are imported automatically if they are registered in META-INF/spring.factories, as shown in the following example:

io.spring.initializr.generator.project.ProjectGenerationConfiguration=\
com.example.acme.build.BuildProjectGenerationConfiguration,\
com.example.acme.code.SourceCodeProjectGenerationConfiguration

Components that are added to the ProjectGenerationContext are generally made available using conditions. Using conditions avoids exposing beans that have to check if they have to do something and makes the declaration more idiomatic. Consider the following example:

@Bean
@ConditionalOnBuildSystem(GradleBuildSystem.ID)
@ConditionalOnPackaging(WarPackaging.ID)
public BuildCustomizer<GradleBuild> warPluginContributor() {
    return (build) -> build.addPlugin("war");
}

This registers a component that can customize a Gradle build only if the project to generate uses the "Gradle" BuildSystem and "war" Packaging. Check the io.spring.initializr.generator.condition package for more conditions. You can create custom conditions easily by inheriting from ProjectGenerationCondition.

You can only use such conditions on beans that have been loaded on the ProjectGenerationConfiguration as they require a concrete ProjectDescription bean to operate properly.

Project generation may also rely on infrastructure that is not specific to a particular project configuration and is usually configured in the main ApplicationContext to avoid registering it every time a new request comes in. A common use case is to set the main ApplicationContext as the parent of the ProjectGenerationContext, as shown in the following example:

public ProjectGenerator createProjectGenerator(ApplicationContext appContext) {
    return new ProjectGenerator((context) -> {
        context.setParent(appContext);
        context.registerBean(SampleContributor.class, SampleContributor::new);
    });
}

This creates a new ProjectGenerator that can use any bean of the application, register all contributors found in META-INF/spring.factories and also registers an additional ProjectContributor programmatically.

ProjectContributor is the highest level interface one can implement to contribute assets to a a project. The SampleContributor registered above generates a test.txt file at the root of the project structure, as shown below:

public class SampleContributor implements ProjectContributor {

    @Override
    public void contribute(Path projectRoot) throws IOException {
        Path file = Files.createFile(projectRoot.resolve("hello.txt"));
        try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(file))) {
            writer.println("Test");
        }
    }

}

7.1.2. Project Generation Lifecycle

When a ProjectGenerator is instructed to generate a project, the specified ProjectDescription can be customized using available ProjectDescriptionCustomizer beans and can be ordered using Spring’s Ordered interface.

Once the description has been customized based on the available ProjectDescriptionCustomizers, the generator uses a ProjectAssetGenerator to generate the project assets. The initializr-generator module provides a default implementation of this interface (`DefaultProjectAssetGenerator) that generates a directory structure using available ProjectContributor beans.

While the default ProjectAssetGenerator use the file system and invoke a particular set of components, it is possible to use the same ProjectGenerator instance with a custom implementation that focus on something else entirely.

7.1.3. Project Abstractions

This module also contains abstractions for various aspects of the project along with some convenient implementations:

  • A build system abstraction with Maven and Gradle implementations.

  • A language abstraction with Java, Groovy and Kotlin implementations, including a SourceCodeWriter for each implementation.

  • A packaging abstraction with implementations for jar and war.

Adding new implementations for these involves creating a BuildSystemFactory, LanguageFactory and PackagingFactory and registering them in META-INF/spring.factories under io.spring.initializr.generator.buildsystem.BuildSystemFactory, io.spring.initializr.generator.language.LanguageFactory and io.spring.initializr.generator.packaging.PackagingFactory respectively.

A JVM project typically contains a build configuration for the project. The initializr-generator module provides a model for Build with implementations for Maven and Gradle. This model can be manipulated depending on the conventions. The library also provides a MavenBuildWriter and GradleBuildWriter that can convert a Build model to build file(s).

The next section about the initializr-generator-spring module showcases how the Build can be manipulated before the build file is written using customizers.

7.2. Conventions for Spring Boot

This is an optional module that defines the conventions that we think will be useful for any Spring Boot project. You can include this jar in your project if your service is meant for generating Spring Boot projects.

In the Project Generator section, we looked at how ProjectContributors can be used to contribute assets to a project. This module contains concrete implementations of ProjectContributor along with the @ProjectGenerationConfigurations that configure them. For example, there is a MavenBuildProjectContributor which contributes the files for a Maven build, such as pom.xml. This contributor is registered as a bean in a ProjectGenerationConfiguration which is conditional on the build system being Maven.

This module also introduces the concept of BuildCustomizers. BuildCustomizers are used to customize a project’s Build and are ordered. For instance, if your service requires you to add a certain plugin to the build, you can provide a BuildCustomizer that adds the plugin and the customizer will be called according to the order specified on it.

7.2.1. Requirements

Contributors of this module expect the following beans to be available in the ProjectGenerationContext:

  • The InitializrMetadata instance to use

  • Optionally, a MetadataBuildItemResolver that can resolve various build items (such as dependencies and BOMs based on their id in the metadata

If you are using a parent context, it is advised to configure those there as you should not register them every time a new project is generated:

  • An IndentingWriterFactory that represents the indenting strategy to use.

  • A MustacheTemplateRenderer using classpath:/templates as root location. Consider registering such bean with a cache strategy to avoid resolving templates every time.

7.2.2. Supported facets

The following facets are handled:

  • web: used to drive the inclusion of a dependency with id web (defaulting to spring-boot-starter-web if no dependency with that facet is present

  • jpa: used to tag that this project uses JPA. When combined with Kotlin, this makes sure to configure the appropriate plugin

  • json: used to tag that this project depends on Jackson. When combined with Kotlin, this makes sure to add the Kotlin-specific jackson module for better interoperability.

8. Creating your own instance

This walkthrough of how to create your own service assumes that the service will be used for creating Spring Boot projects which is the why initializr-generator-spring jar is included.

Spring Initializr provides a Bill of Materials (BOM) so that you don’t have to worry about versions. You can generate a project for your own instance on start.spring.io. Create a new project with the web dependency and add the following dependencies and BOM:

<dependencies>
    <dependency>
        <groupId>io.spring.initializr</groupId>
        <artifactId>initializr-web</artifactId>
    </dependency>
    <dependency>
        <groupId>io.spring.initializr</groupId>
        <artifactId>initializr-generator-spring</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.spring.initializr</groupId>
            <artifactId>initializr-bom</artifactId>
            <version>0.8.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Or if you are using Gradle:

implementation("io.spring.initializr:initializr-web")
implementation("io.spring.initializr:initializr-generator-spring")

dependencyManagement {
  imports {
    mavenBom "io.spring.initializr:initializr-bom:0.8.0.RELEASE"
  }
}

Once you’ve started the application, you can hit localhost:8080. You’ll get a json document that describes the capabilities of the service. None of the select capabilities will 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.

Most of the settings are configured via application.properties using the initializr namespace. Because the configuration is highly hierarchical, we recommend using the yaml format that is more readable for such structure. If you agree, go ahead and rename application.properties to application.yml.

8.1. Configuring basic settings

Most of the select capabilities 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 JVM generations we want to support:

initializr:
  javaVersions:
    - id: 11
      default: false
    - id: 1.8
      default: true
  languages:
    - name: Java
      id: java
      default: true
    - name: Kotlin
      id: kotlin
      default: false

If you restart the application and refresh localhost:8080, the language capability now has the options and default values defined above.

The language identifiers defined there must have a corresponding Language implementation. java, kotlin and groovy can be used out-of-the-box as implementations for those are available in the core library itself.

The available packagings are also configurable that way:

initializr:
  packagings:
    - name: Jar
      id: jar
      default: true
    - name: War
      id: war
      default: false
Jar and War packaging types are available out-of-the-box. For additional packaging formats, you need to implement the Packaging abstraction and provide a PackagingFactory that corresponds to it.

8.2. Configuring text-only settings

Text-only capabilities include groupId, artifactId, name, description, version and packageName. Each capability has a default value if nothing is configured. The defaults can be overridden as shown below:

initializr:
  group-id:
    value: org.acme
  artifact-id:
    value: my-app

8.3. Configuring available Spring Boot versions

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 Spring 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 InitializrMetadataUpdateStrategy bean to provide your own strategy when the metadata has to be refreshed. For instance, you could swap to an implementation that always returns the contents of static application.yml:

@Bean
public InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy() {
    return (metadata) -> 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.

8.4. Configuring available project types

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 tgz

The build system must be defined with a build tag providing the name of the BuildSystem to use (e.g. maven, gradle).

Additional tags can be provided to further qualify the entry. Besides the mandatory build tag, a format tag is also available to define 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
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.

8.5. Configuring dependencies

The most basic dependency is composed of:

  • An id used in clients to refer to it

  • The full maven coordinates of the dependency (groupId and artifactId)

  • A display name (used in the UI and the search results)

  • A description can (and should) be added to provide more information about the dependency

Spring 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.

8.5.1. Compatibility Range

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 compatibilityRange attribute to its definition that defines a version range. 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" release

  • RC 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).

snapshots are in a bit special in that scheme as they always represents the "latest state" of a release. M1 represents the most oldest version for a given major, minor and patch revisions.

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).

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.

8.5.2. Repository

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: https://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.

The snapshots and milestones repositories on repo.spring.io are automatically available with the spring-snapshots and spring-milestones identifiers respectively.

8.6. Configuring Bill of Materials

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 Spring Initializr before you add a new one, and make sure that you aren’t adding a conflict.

In Spring 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

8.6.1. Map coordinates according to the Spring Boot version

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:
          - compatibilityRange: "[1.2.3.RELEASE,1.3.0.RELEASE)"
            groupId: com.example.bar
            artifactId: acme-foo-bom
            version: Arcturus.SR6
          - compatibilityRange: "[1.3.0.RELEASE,1.4.0.RELEASE)"
            version: Botein.SR7
          - compatibilityRange: "[1.4.0.RELEASE,1.5.x.RELEASE)"
            version: Castor.SR6
          - compatibilityRange: "[1.5.0.RELEASE,1.5.x.BUILD-SNAPSHOT)"
            version: Diadem.RC1
            repositories: spring-milestones
          - compatibilityRange: "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. Initially the BOM was identified as com.example.bar:acme-foo-bom and renamed as of Botein to com.example.foo:acme-foo-dependencies.

We also use the x trick in version ranges to avoid updating the range every time a new Spring Boot 1.5 bug fix release is available

See below in the section on linking versions for more examples.

8.6.2. Aliases

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.

8.6.3. Facets

A "facet" is a label on a dependency which is used to drive a code modification in the generated project. For example, initializr-generator-spring checks for the presence of a dependency with the web facet if the packaging type is war. The absence of a dependency with the web facet drives inclusion of a dependency with id web (defaulting to spring-boot-starter-web if such dependency is not available).

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/guides

  • reference: the link points to a section of a developer guide typically or any page that documents how to use the dependency

The 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 active

Here 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: https://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).

9. ‘How-to’ guides

This section provides answers to some common ‘how do I do that…​’ type of questions that often arise when configuring Spring Initializr.

9.1. Add a new dependency

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.

  • If there is a published BOM that manages the version of you dependency, then add that first, in the env section (see Configuring Bill of Materials).

  • Then configure the dependency, fitting it into an existing group if you can, otherwise creating a new group.

  • If there is a BOM then omit the version.

  • If there is a Spring Boot version range (or min or max) that you need for this dependency, add that as a linked version.

9.2. Override the version of a dependency

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 compatibilityRange 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
          ...
          compatibilityRange: 1.2.0.M1
        - name: Bar
          id: bar
          ...
          compatibilityRange: "[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 compatibilityRange 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
          compatibilityRange: 1.3.0.RELEASE
          bom: cloud-task-bom
          mappings:
            - compatibilityRange: "[1.3.0.RELEASE,1.3.x.RELEASE]"
              artifactId: foo-starter
            - compatibilityRange: "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:
          - compatibilityRange: "[1.0.0.RELEASE,1.1.6.RELEASE)"
            version: 1.0.0.RELEASE
            repositories: my-api-repo-1
          - compatibilityRange: "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.

9.4. Configure a snapshot 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.

9.5. Configure a custom parent POM

For Maven projects, you can configure a custom parent POM as follows:

initializr:
  env:
    maven:
      parent:
        groupId: com.example
        artifactId: my-parent
        version: 1.0.0
        includeSpringBootBom : true

includeSpringBootBom is false by default. When set to true, the spring-boot-dependencies bom is added to the dependencyManagement section with the version of Spring Boot used for the project.

9.6. Make sure a regular dependency brings the base starter

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.

9.7. Share common dependency settings in a group

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, compatibilityRange and bom:

initializr:
  dependencies:
    - name: Stuff
      bom: stuff-bom
      compatibilityRange: "[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.

10. Advanced configuration

10.1. Caching configuration

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:

implementation("javax.cache:cache-api")
implementation("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 1. Cache configuration
cache name Description

initializr.metadata

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.

initializr.dependency-metadata

Cache dependency-specific metadata.

initializr.templates

Cache templates that are used to generate projects.

10.2. Bind to custom project request

Only attributes that are defined in the metadata can be bound to a ProjectRequest and ultimately made available in ProjectDescription. A custom instance may chose however to provide additional attributes. Please note that those attributes won’t be supported by official clients (i.e. IDEs).

The first step is to define a custom ProjectRequest with your additional attributes and create a custom ProjectGenerationController that binds to it:

public class CustomProjectGenerationController extends ProjectGenerationController<CustomProjectRequest> {

    public CustomProjectGenerationController(InitializrMetadataProvider metadataProvider,
            ProjectGenerationInvoker<CustomProjectRequest> projectGenerationInvoker) {
        super(metadataProvider, projectGenerationInvoker);
    }

    @Override
    public CustomProjectRequest projectRequest(Map<String, String> headers) {
        CustomProjectRequest request = new CustomProjectRequest();
        request.getParameters().putAll(headers);
        request.initialize(getMetadata());
        return request;
    }

}

If you inherit from WebProjectRequest, defaults can be automatically applied from the metadata as shown above but you may also chose to ignore that.

The next step is to make sure that those additional attributes are made available in the ProjectGenerationContext. The idiomatic way of doing this is to create your own interface that extends from ProjectDescription and expose your custom attributes. To make sure your view of ProjectDescription is made available in the ProjectGenerationContext, a custom ProjectRequestToDescriptionConverter should be defined and could reuse DefaultProjectRequestToDescriptionConverter to apply general rules for standard fields.

Finally, you should wire up everything:

@Bean
public CustomProjectGenerationController projectGenerationController(InitializrMetadataProvider metadataProvider,
        ApplicationContext applicationContext) {
    ProjectGenerationInvoker<CustomProjectRequest> projectGenerationInvoker = new ProjectGenerationInvoker<>(
            applicationContext, new CustomProjectRequestToDescriptionConverter());
    return new CustomProjectGenerationController(metadataProvider, projectGenerationInvoker);
}

API Guide

11. Metadata Format

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).

11.1. Content

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: "7884ff1cd4c266dedd7fb74f3c0defcf"
Content-Type: application/vnd.initializr.v2.1+json
Vary: Accept
Cache-Control: max-age=7200
Content-Length: 4874

{
  "_links" : {
    "maven-build" : {
      "href" : "http://start.spring.io/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
      "templated" : true
    },
    "maven-project" : {
      "href" : "http://start.spring.io/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
      "templated" : true
    },
    "gradle-build" : {
      "href" : "http://start.spring.io/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
      "templated" : true
    },
    "gradle-project" : {
      "href" : "http://start.spring.io/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
      "templated" : true
    },
    "dependencies" : {
      "href" : "http://start.spring.io/dependencies{?bootVersion}",
      "templated" : true
    }
  },
  "dependencies" : {
    "type" : "hierarchical-multi-select",
    "values" : [ {
      "name" : "Core",
      "values" : [ {
        "id" : "web",
        "name" : "Web",
        "description" : "Web dependency description",
        "_links" : {
          "guide" : {
            "href" : "https://example.com/guide",
            "title" : "Building a RESTful Web Service"
          },
          "reference" : {
            "href" : "https://example.com/doc"
          }
        }
      }, {
        "id" : "security",
        "name" : "Security"
      }, {
        "id" : "data-jpa",
        "name" : "Data JPA"
      } ]
    }, {
      "name" : "Other",
      "values" : [ {
        "id" : "org.acme:foo",
        "name" : "Foo",
        "_links" : {
          "guide" : [ {
            "href" : "https://example.com/guide1"
          }, {
            "href" : "https://example.com/guide2",
            "title" : "Some guide for foo"
          } ],
          "reference" : {
            "href" : "https://example.com/{bootVersion}/doc",
            "templated" : true
          }
        }
      }, {
        "id" : "org.acme:bar",
        "name" : "Bar"
      }, {
        "id" : "org.acme:biz",
        "name" : "Biz",
        "versionRange" : "2.2.0.BUILD-SNAPSHOT"
      }, {
        "id" : "org.acme:bur",
        "name" : "Bur",
        "versionRange" : "[2.1.4.RELEASE,2.2.0.BUILD-SNAPSHOT)"
      }, {
        "id" : "my-api",
        "name" : "My API"
      } ]
    } ]
  },
  "type" : {
    "type" : "action",
    "default" : "maven-project",
    "values" : [ {
      "id" : "maven-build",
      "name" : "Maven POM",
      "action" : "/pom.xml",
      "tags" : {
        "build" : "maven",
        "format" : "build"
      }
    }, {
      "id" : "maven-project",
      "name" : "Maven Project",
      "action" : "/starter.zip",
      "tags" : {
        "build" : "maven",
        "format" : "project"
      }
    }, {
      "id" : "gradle-build",
      "name" : "Gradle Config",
      "action" : "/build.gradle",
      "tags" : {
        "build" : "gradle",
        "format" : "build"
      }
    }, {
      "id" : "gradle-project",
      "name" : "Gradle Project",
      "action" : "/starter.zip",
      "tags" : {
        "build" : "gradle",
        "format" : "project"
      }
    } ]
  },
  "packaging" : {
    "type" : "single-select",
    "default" : "jar",
    "values" : [ {
      "id" : "jar",
      "name" : "Jar"
    }, {
      "id" : "war",
      "name" : "War"
    } ]
  },
  "javaVersion" : {
    "type" : "single-select",
    "default" : "1.8",
    "values" : [ {
      "id" : "1.6",
      "name" : "1.6"
    }, {
      "id" : "1.7",
      "name" : "1.7"
    }, {
      "id" : "1.8",
      "name" : "1.8"
    } ]
  },
  "language" : {
    "type" : "single-select",
    "default" : "java",
    "values" : [ {
      "id" : "groovy",
      "name" : "Groovy"
    }, {
      "id" : "java",
      "name" : "Java"
    }, {
      "id" : "kotlin",
      "name" : "Kotlin"
    } ]
  },
  "bootVersion" : {
    "type" : "single-select",
    "default" : "2.1.4.RELEASE",
    "values" : [ {
      "id" : "2.2.0.BUILD-SNAPSHOT",
      "name" : "Latest SNAPSHOT"
    }, {
      "id" : "2.1.4.RELEASE",
      "name" : "2.1.4"
    }, {
      "id" : "1.5.17.RELEASE",
      "name" : "1.5.17"
    } ]
  },
  "groupId" : {
    "type" : "text",
    "default" : "com.example"
  },
  "artifactId" : {
    "type" : "text",
    "default" : "demo"
  },
  "version" : {
    "type" : "text",
    "default" : "0.0.1-SNAPSHOT"
  },
  "name" : {
    "type" : "text",
    "default" : "demo"
  },
  "description" : {
    "type" : "text",
    "default" : "Demo project for Spring Boot"
  },
  "packageName" : {
    "type" : "text",
    "default" : "com.example.demo"
  }
}

The current capabilities are the following:

  • Project dependencies: these are the starters really or actually any dependency that we might want to add to the project.

  • Project types: these define the action that can be invoked on this service and a description of what it would produce (for instance a zip holding a pre-configured Maven project). Each type may have one more tags that further define what it generates.

  • Packaging: the kind of projects to generate. This merely gives a hint to the component responsible to generate the project (for instance, generate an executable jar project).

  • Java version: the supported java versions

  • Language: the language to use (e.g. Java)

  • Boot version: the Spring Boot version to use

  • Additional basic information such as: groupId, artifactId, version, name, description and packageName.

Each top-level attribute (i.e. capability) has a standard format:

  • A type attribute that defines the semantic of the attribute (see below).

  • A default attribute that defines either the default value or the reference to the default value.

  • A 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
{
  "href" : "http://start.spring.io/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
  "templated" : true
}

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.

11.1.1. Project dependencies

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
{
  "name" : "Core",
  "values" : [ {
    "id" : "web",
    "name" : "Web",
    "description" : "Web dependency description",
    "_links" : {
      "guide" : {
        "href" : "https://example.com/guide",
        "title" : "Building a RESTful Web Service"
      },
      "reference" : {
        "href" : "https://example.com/doc"
      }
    }
  }, {
    "id" : "security",
    "name" : "Security"
  }, {
    "id" : "data-jpa",
    "name" : "Data JPA"
  } ]
}

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 started

  • reference: link to a section of a reference guide (documentation)

11.1.2. Project types

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
{
  "id" : "maven-build",
  "name" : "Maven POM",
  "action" : "/pom.xml",
  "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).

11.1.3. Packaging

The packaging element defines the kind of project that should be generated.

Packaging example
{
  "id" : "jar",
  "name" : "Jar"
}

The obvious values for this element are jar and war.

11.1.4. Java version

The javaVersion element provides a list of possible java versions for the project:

Java example
{
  "id" : "1.6",
  "name" : "1.6"
}

11.1.5. Languages

The language element provides a list of possible languages for the project:

Language example
{
  "id" : "groovy",
  "name" : "Groovy"
}

11.1.6. Boot version

The bootVersion element provides the list of available boot versions

Spring Boot version example
{
  "id" : "2.2.0.BUILD-SNAPSHOT",
  "name" : "Latest SNAPSHOT"
}

11.2. Defaults

Each top-level element has a default attribute that should be used as a hint to provide the default value in the relevant UI component.

12. Using the Stubs

Spring Initializr project publishes WireMock stubs for all the JSON responses that are tested in the project. If you are writing a client for Spring 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.

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.

12.1. Using WireMock with Spring Boot

12.1.1. Loading Stubs from the Classpath

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, as shown in the following JUnit 5-based example:

@SpringBootTest
@AutoConfigureWireMock(port = 0,
    stubs="classpath:META-INF/io.spring.initializr/initializr-web/0.8.0.RELEASE")
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>
This dependency is managed by the spring-cloud-contract-dependencies BOM.

12.1.2. Using the Stub Runner

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 Spring 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, as shown in the following JUnit 5-based example:

@SpringBootTest(webEnvironment = WebEnvironment.NONE)
@AutoConfigureStubRunner(
    ids = "io.spring.initializr:initializr-web:0.8.0.RELEASE",
    repositoryRoot = "https://repo.spring.io/snapshot")
class ClientApplicationTests {

    @Autowired
    private StubFinder stubFinder;


    ...

}

Here is JUnit 5-based 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:

@SpringBootTest(webEnvironment = WebEnvironment.NONE)
@AutoConfigureStubRunner(ids = "io.spring.initializr:initializr-web:${project.version}", stubsMode = StubsMode.LOCAL)
class ClientApplicationTests {

    @Autowired
    private StubFinder stubFinder;

    @Autowired
    private RestTemplate restTemplate;

    @Test
    void testCurrentMetadata() {
        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
        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).

12.2. Names and Paths of Stubs

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 Spring 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 Spring 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.