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

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

2.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: "1262473f5c28f970e1e42d107213b064"
Content-Type: application/vnd.initializr.v2.1+json
Cache-Control: max-age=604800
Content-Length: 4872

{
  "_links" : {
    "maven-build" : {
      "href" : "https://start.spring.io/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
      "templated" : true
    },
    "maven-project" : {
      "href" : "https://start.spring.io/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
      "templated" : true
    },
    "gradle-build" : {
      "href" : "https://start.spring.io/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
      "templated" : true
    },
    "gradle-project" : {
      "href" : "https://start.spring.io/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
      "templated" : true
    },
    "dependencies" : {
      "href" : "https://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" : "1.2.0.BUILD-SNAPSHOT"
      }, {
        "id" : "org.acme:bur",
        "name" : "Bur",
        "versionRange" : "[1.1.4.RELEASE,1.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" : "1.1.4.RELEASE",
    "values" : [ {
      "id" : "1.2.0.BUILD-SNAPSHOT",
      "name" : "Latest SNAPSHOT"
    }, {
      "id" : "1.1.4.RELEASE",
      "name" : "1.1.4"
    }, {
      "id" : "1.0.2.RELEASE",
      "name" : "1.0.2"
    } ]
  },
  "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"
  }
}

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

2.1.1 Project dependencies

A dependency is usually the coordinates of a starter module but it can be just as well be 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)

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

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

2.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"
}

2.1.5 Languages

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

Language example. 

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

2.1.6 Boot version

The bootVersion element provides the list of available boot versions

Spring Boot version example. 

{
  "id" : "1.2.0.BUILD-SNAPSHOT",
  "name" : "Latest SNAPSHOT"
}

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