mirror of
https://gitee.com/dcren/initializr.git
synced 2025-12-26 22:25:51 +08:00
Serve version format that is backward compatible
This commit makes sure the metadata format uses a backward compatible version format even if the new format is used. It also introduces a new metadata version (2.2) that can be used by clients that support the new version format. See gh-1092
This commit is contained in:
@@ -13,10 +13,16 @@ sent to the service. A good structure for a user agent is `clientId/clientVersio
|
||||
== Service Capabilities
|
||||
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
|
||||
`application/vnd.initializr.v2.2+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.
|
||||
|
||||
The following versions are supported:
|
||||
|
||||
* `v2` initial version, with support of V1 version format only
|
||||
* `v2.1` support compatibility range and dependencies links
|
||||
* `v2.2` (current) support for V1 and V2 version formats.
|
||||
|
||||
This is an example output for a service running at `https://start.spring.io`:
|
||||
|
||||
.request
|
||||
|
||||
@@ -110,7 +110,7 @@ include::{test-examples}/stub/ClientApplicationTests.java[tag=test]
|
||||
|
||||
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).
|
||||
`Accept:application/vnd.initializr.v2.2+json` (as recommended).
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import io.spring.initializr.metadata.InvalidInitializrMetadataException;
|
||||
import io.spring.initializr.web.mapper.DependencyMetadataV21JsonMapper;
|
||||
import io.spring.initializr.web.mapper.InitializrMetadataJsonMapper;
|
||||
import io.spring.initializr.web.mapper.InitializrMetadataV21JsonMapper;
|
||||
import io.spring.initializr.web.mapper.InitializrMetadataV22JsonMapper;
|
||||
import io.spring.initializr.web.mapper.InitializrMetadataV2JsonMapper;
|
||||
import io.spring.initializr.web.mapper.InitializrMetadataVersion;
|
||||
import io.spring.initializr.web.project.InvalidProjectRequestException;
|
||||
@@ -77,6 +78,11 @@ public class ProjectMetadataController extends AbstractMetadataController {
|
||||
return serviceCapabilitiesFor(InitializrMetadataVersion.V2_1, HAL_JSON_CONTENT_TYPE);
|
||||
}
|
||||
|
||||
@RequestMapping(path = { "/", "/metadata/client" }, produces = { "application/vnd.initializr.v2.2+json" })
|
||||
public ResponseEntity<String> serviceCapabilitiesV22() {
|
||||
return serviceCapabilitiesFor(InitializrMetadataVersion.V2_2);
|
||||
}
|
||||
|
||||
@RequestMapping(path = { "/", "/metadata/client" },
|
||||
produces = { "application/vnd.initializr.v2.1+json", "application/json" })
|
||||
public ResponseEntity<String> serviceCapabilitiesV21() {
|
||||
@@ -147,8 +153,10 @@ public class ProjectMetadataController extends AbstractMetadataController {
|
||||
switch (version) {
|
||||
case V2:
|
||||
return new InitializrMetadataV2JsonMapper();
|
||||
default:
|
||||
case V2_1:
|
||||
return new InitializrMetadataV21JsonMapper();
|
||||
default:
|
||||
return new InitializrMetadataV22JsonMapper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,8 @@ package io.spring.initializr.web.mapper;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.spring.initializr.generator.version.Version.Format;
|
||||
import io.spring.initializr.generator.version.VersionRange;
|
||||
import io.spring.initializr.metadata.Dependency;
|
||||
import io.spring.initializr.metadata.Type;
|
||||
|
||||
@@ -55,8 +57,8 @@ public class InitializrMetadataV21JsonMapper extends InitializrMetadataV2JsonMap
|
||||
@Override
|
||||
protected ObjectNode mapDependency(Dependency dependency) {
|
||||
ObjectNode content = mapValue(dependency);
|
||||
if (dependency.getCompatibilityRange() != null) {
|
||||
content.put("versionRange", dependency.getCompatibilityRange());
|
||||
if (dependency.getRange() != null) {
|
||||
content.put("versionRange", formatVersionRange(dependency.getRange()));
|
||||
}
|
||||
if (dependency.getLinks() != null && !dependency.getLinks().isEmpty()) {
|
||||
content.set("_links", LinkMapper.mapLinks(dependency.getLinks()));
|
||||
@@ -64,6 +66,10 @@ public class InitializrMetadataV21JsonMapper extends InitializrMetadataV2JsonMap
|
||||
return content;
|
||||
}
|
||||
|
||||
protected String formatVersionRange(VersionRange versionRange) {
|
||||
return versionRange.format(Format.V1).toRangeString();
|
||||
}
|
||||
|
||||
private ObjectNode dependenciesLink(String appUrl) {
|
||||
String uri = (appUrl != null) ? appUrl + "/dependencies" : "/dependencies";
|
||||
UriTemplate uriTemplate = UriTemplate.of(uri, this.dependenciesVariables);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.spring.initializr.web.mapper;
|
||||
|
||||
import io.spring.initializr.generator.version.Version;
|
||||
import io.spring.initializr.generator.version.VersionRange;
|
||||
|
||||
/**
|
||||
* A {@link InitializrMetadataJsonMapper} handling the metadata format for v2.2
|
||||
* <p>
|
||||
* Version 2.2 adds support for {@linkplain Version.Format#V2 SemVer version format}. Any
|
||||
* previous version formats versions to {@link Version.Format#V1}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class InitializrMetadataV22JsonMapper extends InitializrMetadataV21JsonMapper {
|
||||
|
||||
@Override
|
||||
protected String formatVersion(String versionId) {
|
||||
return versionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String formatVersionRange(VersionRange versionRange) {
|
||||
return versionRange.toRangeString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,12 +17,16 @@
|
||||
package io.spring.initializr.web.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.spring.initializr.generator.version.Version;
|
||||
import io.spring.initializr.generator.version.Version.Format;
|
||||
import io.spring.initializr.generator.version.VersionParser;
|
||||
import io.spring.initializr.metadata.DefaultMetadataElement;
|
||||
import io.spring.initializr.metadata.DependenciesCapability;
|
||||
import io.spring.initializr.metadata.Dependency;
|
||||
@@ -79,7 +83,7 @@ public class InitializrMetadataV2JsonMapper implements InitializrMetadataJsonMap
|
||||
singleSelect(delegate, metadata.getPackagings());
|
||||
singleSelect(delegate, metadata.getJavaVersions());
|
||||
singleSelect(delegate, metadata.getLanguages());
|
||||
singleSelect(delegate, metadata.getBootVersions());
|
||||
singleSelect(delegate, metadata.getBootVersions(), this::mapVersionMetadata);
|
||||
text(delegate, metadata.getGroupId());
|
||||
text(delegate, metadata.getArtifactId());
|
||||
text(delegate, metadata.getVersion());
|
||||
@@ -133,6 +137,11 @@ public class InitializrMetadataV2JsonMapper implements InitializrMetadataJsonMap
|
||||
}
|
||||
|
||||
protected void singleSelect(ObjectNode parent, SingleSelectCapability capability) {
|
||||
singleSelect(parent, capability, this::mapValue);
|
||||
}
|
||||
|
||||
protected void singleSelect(ObjectNode parent, SingleSelectCapability capability,
|
||||
Function<MetadataElement, ObjectNode> valueMapper) {
|
||||
ObjectNode single = nodeFactory.objectNode();
|
||||
single.put("type", capability.getType().getName());
|
||||
DefaultMetadataElement defaultType = capability.getDefault();
|
||||
@@ -140,7 +149,7 @@ public class InitializrMetadataV2JsonMapper implements InitializrMetadataJsonMap
|
||||
single.put("default", defaultType.getId());
|
||||
}
|
||||
ArrayNode values = nodeFactory.arrayNode();
|
||||
values.addAll(capability.getContent().stream().map(this::mapValue).collect(Collectors.toList()));
|
||||
values.addAll(capability.getContent().stream().map(valueMapper).collect(Collectors.toList()));
|
||||
single.set("values", values);
|
||||
parent.set(capability.getId(), single);
|
||||
}
|
||||
@@ -189,6 +198,18 @@ public class InitializrMetadataV2JsonMapper implements InitializrMetadataJsonMap
|
||||
return result;
|
||||
}
|
||||
|
||||
private ObjectNode mapVersionMetadata(MetadataElement value) {
|
||||
ObjectNode result = nodeFactory.objectNode();
|
||||
result.put("id", formatVersion(value.getId()));
|
||||
result.put("name", value.getName());
|
||||
return result;
|
||||
}
|
||||
|
||||
protected String formatVersion(String versionId) {
|
||||
Version version = VersionParser.DEFAULT.safeParse(versionId);
|
||||
return (version != null) ? version.format(Format.V1).toString() : versionId;
|
||||
}
|
||||
|
||||
protected ObjectNode mapValue(MetadataElement value) {
|
||||
ObjectNode result = nodeFactory.objectNode();
|
||||
result.put("id", value.getId());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,12 @@ public enum InitializrMetadataVersion {
|
||||
* versions are compatible with it. Also provide a separate "dependencies" endpoint to
|
||||
* query dependencies metadata.
|
||||
*/
|
||||
V2_1("application/vnd.initializr.v2.1+json");
|
||||
V2_1("application/vnd.initializr.v2.1+json"),
|
||||
|
||||
/**
|
||||
* Add support for SemVer compliant version format.
|
||||
*/
|
||||
V2_2("application/vnd.initializr.v2.2+json");
|
||||
|
||||
private final MediaType mediaType;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -72,7 +72,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@SpringBootTest(classes = Config.class)
|
||||
public abstract class AbstractInitializrIntegrationTests {
|
||||
|
||||
protected static final MediaType CURRENT_METADATA_MEDIA_TYPE = InitializrMetadataVersion.V2_1.getMediaType();
|
||||
protected static final MediaType DEFAULT_METADATA_MEDIA_TYPE = InitializrMetadataVersion.V2_1.getMediaType();
|
||||
|
||||
protected static final MediaType CURRENT_METADATA_MEDIA_TYPE = InitializrMetadataVersion.V2_2.getMediaType();
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@@ -125,14 +127,23 @@ public abstract class AbstractInitializrIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateCurrentMetadata(ResponseEntity<String> response) {
|
||||
validateContentType(response, CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateCurrentMetadata(response.getBody());
|
||||
protected void validateDefaultMetadata(ResponseEntity<String> response) {
|
||||
validateContentType(response, DEFAULT_METADATA_MEDIA_TYPE);
|
||||
validateMetadata(response.getBody(), "2.1.0");
|
||||
}
|
||||
|
||||
protected void validateCurrentMetadata(String json) {
|
||||
protected void validateCurrentMetadata(ResponseEntity<String> response) {
|
||||
validateContentType(response, CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateMetadata(response.getBody(), "2.2.0");
|
||||
}
|
||||
|
||||
protected void validateDefaultMetadata(String json) {
|
||||
validateMetadata(json, "2.1.0");
|
||||
}
|
||||
|
||||
protected void validateMetadata(String json, String version) {
|
||||
try {
|
||||
JSONObject expected = readMetadataJson("2.1.0");
|
||||
JSONObject expected = readMetadataJson(version);
|
||||
JSONAssert.assertEquals(expected, new JSONObject(json), JSONCompareMode.STRICT);
|
||||
}
|
||||
catch (JSONException ex) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,8 +45,8 @@ public class CommandLineMetadataControllerIntegrationTests extends AbstractIniti
|
||||
// make sure curl can still receive metadata with json
|
||||
void curlWithAcceptHeaderJson() {
|
||||
ResponseEntity<String> response = invokeHome("curl/1.2.4", "application/json");
|
||||
validateContentType(response, AbstractInitializrIntegrationTests.CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateCurrentMetadata(response.getBody());
|
||||
validateContentType(response, AbstractInitializrIntegrationTests.DEFAULT_METADATA_MEDIA_TYPE);
|
||||
validateDefaultMetadata(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -65,8 +65,8 @@ public class CommandLineMetadataControllerIntegrationTests extends AbstractIniti
|
||||
// make sure curl can still receive metadata with json
|
||||
void httpieWithAcceptHeaderJson() {
|
||||
ResponseEntity<String> response = invokeHome("HTTPie/0.8.0", "application/json");
|
||||
validateContentType(response, AbstractInitializrIntegrationTests.CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateCurrentMetadata(response.getBody());
|
||||
validateContentType(response, AbstractInitializrIntegrationTests.DEFAULT_METADATA_MEDIA_TYPE);
|
||||
validateDefaultMetadata(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -84,8 +84,8 @@ public class CommandLineMetadataControllerIntegrationTests extends AbstractIniti
|
||||
@Test
|
||||
void springBootCliReceivesJsonByDefault() {
|
||||
ResponseEntity<String> response = invokeHome("SpringBootCli/1.2.0", "*/*");
|
||||
validateContentType(response, AbstractInitializrIntegrationTests.CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateCurrentMetadata(response.getBody());
|
||||
validateContentType(response, AbstractInitializrIntegrationTests.DEFAULT_METADATA_MEDIA_TYPE);
|
||||
validateDefaultMetadata(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -84,24 +84,24 @@ class ProjectMetadataControllerCustomDefaultsIntegrationTests extends AbstractFu
|
||||
@Test
|
||||
void metadataClientEndpoint() {
|
||||
ResponseEntity<String> response = execute("/metadata/client", String.class, null, "application/json");
|
||||
validateCurrentMetadata(response);
|
||||
validateDefaultMetadata(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
void noBootVersion() throws JSONException {
|
||||
ResponseEntity<String> response = execute("/dependencies", String.class, null, "application/json");
|
||||
assertThat(response.getHeaders().getFirst(HttpHeaders.ETAG)).isNotNull();
|
||||
validateContentType(response, CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateContentType(response, DEFAULT_METADATA_MEDIA_TYPE);
|
||||
validateDependenciesOutput("2.1.4", response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
void filteredDependencies() throws JSONException {
|
||||
ResponseEntity<String> response = execute("/dependencies?bootVersion=2.2.1.RELEASE", String.class, null,
|
||||
ResponseEntity<String> response = execute("/dependencies?bootVersion=2.4.1.RELEASE", String.class, null,
|
||||
"application/json");
|
||||
assertThat(response.getHeaders().getFirst(HttpHeaders.ETAG)).isNotNull();
|
||||
validateContentType(response, CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateDependenciesOutput("2.2.1", response.getBody());
|
||||
validateContentType(response, DEFAULT_METADATA_MEDIA_TYPE);
|
||||
validateDependenciesOutput("2.4.1", response.getBody());
|
||||
}
|
||||
|
||||
protected void validateDependenciesOutput(String version, String actual) throws JSONException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,7 +43,7 @@ public class ProjectMetadataControllerIntegrationTests extends AbstractInitializ
|
||||
void metadataWithNoAcceptHeader() {
|
||||
// rest template sets application/json by default
|
||||
ResponseEntity<String> response = invokeHome(null, "*/*");
|
||||
validateCurrentMetadata(response);
|
||||
validateDefaultMetadata(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,6 +60,18 @@ public class ProjectMetadataControllerIntegrationTests extends AbstractInitializ
|
||||
validateMetadata(response, InitializrMetadataVersion.V2.getMediaType(), "2.0.0", JSONCompareMode.STRICT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void metadataWithV21AcceptHeader() {
|
||||
ResponseEntity<String> response = invokeHome(null, "application/vnd.initializr.v2.1+json");
|
||||
validateMetadata(response, InitializrMetadataVersion.V2_1.getMediaType(), "2.1.0", JSONCompareMode.STRICT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void metadataWithV22AcceptHeader() {
|
||||
ResponseEntity<String> response = invokeHome(null, "application/vnd.initializr.v2.2+json");
|
||||
validateMetadata(response, InitializrMetadataVersion.V2_2.getMediaType(), "2.2.0", JSONCompareMode.STRICT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void metadataWithInvalidPlatformVersion() {
|
||||
try {
|
||||
@@ -76,18 +88,18 @@ public class ProjectMetadataControllerIntegrationTests extends AbstractInitializ
|
||||
void metadataWithCurrentAcceptHeader() {
|
||||
getRequests().setFields("_links.maven-project", "dependencies.values[0]", "type.values[0]",
|
||||
"javaVersion.values[0]", "packaging.values[0]", "bootVersion.values[0]", "language.values[0]");
|
||||
ResponseEntity<String> response = invokeHome(null, "application/vnd.initializr.v2.1+json");
|
||||
ResponseEntity<String> response = invokeHome(null, "application/vnd.initializr.v2.2+json");
|
||||
assertThat(response.getHeaders().getFirst(HttpHeaders.ETAG)).isNotNull();
|
||||
validateContentType(response, AbstractInitializrIntegrationTests.CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateCurrentMetadata(response.getBody());
|
||||
validateMetadata(response.getBody(), "2.2.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
void metadataWithSeveralAcceptHeader() {
|
||||
ResponseEntity<String> response = invokeHome(null, "application/vnd.initializr.v2.1+json",
|
||||
ResponseEntity<String> response = invokeHome(null, "application/vnd.initializr.v2.2+json",
|
||||
"application/vnd.initializr.v2+json");
|
||||
validateContentType(response, AbstractInitializrIntegrationTests.CURRENT_METADATA_MEDIA_TYPE);
|
||||
validateCurrentMetadata(response.getBody());
|
||||
validateCurrentMetadata(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,7 +107,7 @@ public class ProjectMetadataControllerIntegrationTests extends AbstractInitializ
|
||||
ResponseEntity<String> response = invokeHome(null, "application/hal+json");
|
||||
assertThat(response.getHeaders().getFirst(HttpHeaders.ETAG)).isNotNull();
|
||||
validateContentType(response, ProjectMetadataController.HAL_JSON_CONTENT_TYPE);
|
||||
validateCurrentMetadata(response.getBody());
|
||||
validateDefaultMetadata(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -117,13 +129,13 @@ public class ProjectMetadataControllerIntegrationTests extends AbstractInitializ
|
||||
@Test
|
||||
void unknownAgentReceivesJsonByDefault() {
|
||||
ResponseEntity<String> response = invokeHome("foo/1.0", "*/*");
|
||||
validateCurrentMetadata(response);
|
||||
validateDefaultMetadata(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
// Test that the current output is exactly what we expect
|
||||
void validateCurrentProjectMetadata() {
|
||||
validateCurrentMetadata(getMetadataJson());
|
||||
validateDefaultMetadata(getMetadataJson());
|
||||
}
|
||||
|
||||
private String getMetadataJson() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,8 +18,10 @@ package io.spring.initializr.web.mapper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.spring.initializr.generator.test.InitializrMetadataTestBuilder;
|
||||
import io.spring.initializr.metadata.Dependency;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
@@ -29,13 +31,15 @@ import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link InitializrMetadataV21JsonMapper}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class InitializrMetadataJsonMapperTests {
|
||||
class InitializrMetadataV21JsonMapperTests {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private final InitializrMetadataJsonMapper jsonMapper = new InitializrMetadataV21JsonMapper();
|
||||
private final InitializrMetadataV21JsonMapper jsonMapper = new InitializrMetadataV21JsonMapper();
|
||||
|
||||
@Test
|
||||
void withNoAppUrl() throws IOException {
|
||||
@@ -74,6 +78,42 @@ class InitializrMetadataJsonMapperTests {
|
||||
assertThat(second).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionRangesUsingSemVerUseBackwardCompatibleFormat() {
|
||||
Dependency dependency = Dependency.withId("test");
|
||||
dependency.setCompatibilityRange("[1.1.1-RC1,1.2.0-M1)");
|
||||
dependency.resolve();
|
||||
ObjectNode node = this.jsonMapper.mapDependency(dependency);
|
||||
assertThat(node.get("versionRange").textValue()).isEqualTo("[1.1.1.RC1,1.2.0.M1)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionRangesUsingSemVerSnapshotReplacedByBackwardCompatibleSnapshotQualifier() {
|
||||
Dependency dependency = Dependency.withId("test");
|
||||
dependency.setCompatibilityRange("1.2.0-SNAPSHOT");
|
||||
dependency.resolve();
|
||||
ObjectNode node = this.jsonMapper.mapDependency(dependency);
|
||||
assertThat(node.get("versionRange").textValue()).isEqualTo("1.2.0.BUILD-SNAPSHOT");
|
||||
}
|
||||
|
||||
@Test
|
||||
void platformVersionUsingSemVerUseBackwardCompatibleFormat() throws JsonProcessingException {
|
||||
InitializrMetadata metadata = new InitializrMetadataTestBuilder().addBootVersion("2.5.0-SNAPSHOT", false)
|
||||
.addBootVersion("2.5.0-M2", false).addBootVersion("2.4.2", true).build();
|
||||
String json = this.jsonMapper.write(metadata, null);
|
||||
JsonNode result = objectMapper.readTree(json);
|
||||
JsonNode versions = result.get("bootVersion").get("values");
|
||||
assertThat(versions).hasSize(3);
|
||||
assertVersionMetadata(versions.get(0), "2.5.0.BUILD-SNAPSHOT", "2.5.0-SNAPSHOT");
|
||||
assertVersionMetadata(versions.get(1), "2.5.0.M2", "2.5.0-M2");
|
||||
assertVersionMetadata(versions.get(2), "2.4.2.RELEASE", "2.4.2");
|
||||
}
|
||||
|
||||
private void assertVersionMetadata(JsonNode node, String id, String name) {
|
||||
assertThat(node.get("id").textValue()).isEqualTo(id);
|
||||
assertThat(node.get("name").textValue()).isEqualTo(name);
|
||||
}
|
||||
|
||||
private Object get(JsonNode result, String path) {
|
||||
String[] nodes = path.split("\\.");
|
||||
for (int i = 0; i < nodes.length - 1; i++) {
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.spring.initializr.web.mapper;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.spring.initializr.generator.test.InitializrMetadataTestBuilder;
|
||||
import io.spring.initializr.metadata.Dependency;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link InitializrMetadataV22JsonMapper}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class InitializrMetadataV22JsonMapperTests {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private final InitializrMetadataV22JsonMapper jsonMapper = new InitializrMetadataV22JsonMapper();
|
||||
|
||||
@Test
|
||||
void versionRangesUsingSemVerIsNotChanged() {
|
||||
Dependency dependency = Dependency.withId("test");
|
||||
dependency.setCompatibilityRange("[1.1.1-RC1,1.2.0-M1)");
|
||||
dependency.resolve();
|
||||
ObjectNode node = this.jsonMapper.mapDependency(dependency);
|
||||
assertThat(node.get("versionRange").textValue()).isEqualTo("[1.1.1-RC1,1.2.0-M1)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionRangesUsingSemVerSnapshotIsNotChanged() {
|
||||
Dependency dependency = Dependency.withId("test");
|
||||
dependency.setCompatibilityRange("1.2.0-SNAPSHOT");
|
||||
dependency.resolve();
|
||||
ObjectNode node = this.jsonMapper.mapDependency(dependency);
|
||||
assertThat(node.get("versionRange").textValue()).isEqualTo("1.2.0-SNAPSHOT");
|
||||
}
|
||||
|
||||
@Test
|
||||
void platformVersionUsingSemVerUIsNotChanged() throws JsonProcessingException {
|
||||
InitializrMetadata metadata = new InitializrMetadataTestBuilder().addBootVersion("2.5.0-SNAPSHOT", false)
|
||||
.addBootVersion("2.5.0-M2", false).addBootVersion("2.4.2", true).build();
|
||||
String json = this.jsonMapper.write(metadata, null);
|
||||
JsonNode result = objectMapper.readTree(json);
|
||||
JsonNode versions = result.get("bootVersion").get("values");
|
||||
assertThat(versions).hasSize(3);
|
||||
assertVersionMetadata(versions.get(0), "2.5.0-SNAPSHOT", "2.5.0-SNAPSHOT");
|
||||
assertVersionMetadata(versions.get(1), "2.5.0-M2", "2.5.0-M2");
|
||||
assertVersionMetadata(versions.get(2), "2.4.2", "2.4.2");
|
||||
}
|
||||
|
||||
private void assertVersionMetadata(JsonNode node, String id, String name) {
|
||||
assertThat(node.get("id").textValue()).isEqualTo(id);
|
||||
assertThat(node.get("name").textValue()).isEqualTo(name);
|
||||
}
|
||||
|
||||
private Object get(JsonNode result, String path) {
|
||||
String[] nodes = path.split("\\.");
|
||||
for (int i = 0; i < nodes.length - 1; i++) {
|
||||
String node = nodes[i];
|
||||
result = result.path(node);
|
||||
}
|
||||
return result.get(nodes[nodes.length - 1]).textValue();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -90,7 +90,7 @@ initializr:
|
||||
id: org.acme:bur
|
||||
version: 2.1.0
|
||||
scope: test
|
||||
compatibilityRange: "[2.1.4.RELEASE,2.2.0.BUILD-SNAPSHOT)"
|
||||
compatibilityRange: "[2.1.4.RELEASE,2.4.0-SNAPSHOT)"
|
||||
- name: My API
|
||||
id : my-api
|
||||
groupId: org.acme
|
||||
@@ -152,7 +152,7 @@ initializr:
|
||||
default: false
|
||||
bootVersions:
|
||||
- name : Latest SNAPSHOT
|
||||
id: 2.2.0.BUILD-SNAPSHOT
|
||||
id: 2.4.0-SNAPSHOT
|
||||
default: false
|
||||
- name: 2.1.4
|
||||
id: 2.1.4.RELEASE
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"content": [
|
||||
{
|
||||
"default": false,
|
||||
"id": "2.2.0.BUILD-SNAPSHOT",
|
||||
"id": "2.4.0-SNAPSHOT",
|
||||
"name": "Latest SNAPSHOT"
|
||||
},
|
||||
{
|
||||
@@ -230,7 +230,7 @@
|
||||
"name": "Bur",
|
||||
"scope": "test",
|
||||
"version": "2.1.0",
|
||||
"compatibilityRange": "[2.1.4.RELEASE,2.2.0.BUILD-SNAPSHOT)"
|
||||
"compatibilityRange": "[2.1.4.RELEASE,2.4.0-SNAPSHOT)"
|
||||
},
|
||||
{
|
||||
"starter": true,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"bootVersion": "2.2.1.RELEASE",
|
||||
"bootVersion": "2.4.1.RELEASE",
|
||||
"repositories": {
|
||||
"my-api-repo-2": {
|
||||
"name": "repo2",
|
||||
@@ -154,7 +154,7 @@
|
||||
"default": "2.1.4.RELEASE",
|
||||
"values": [
|
||||
{
|
||||
"id": "2.2.0.BUILD-SNAPSHOT",
|
||||
"id": "2.4.0.BUILD-SNAPSHOT",
|
||||
"name": "Latest SNAPSHOT"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
"default": "2.1.4.RELEASE",
|
||||
"values": [
|
||||
{
|
||||
"id": "2.2.0.BUILD-SNAPSHOT",
|
||||
"id": "2.4.0.BUILD-SNAPSHOT",
|
||||
"name": "Latest SNAPSHOT"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
{
|
||||
"id": "org.acme:bur",
|
||||
"name": "Bur",
|
||||
"versionRange": "[2.1.4.RELEASE,2.2.0.BUILD-SNAPSHOT)"
|
||||
"versionRange": "[2.1.4.RELEASE,2.4.0.BUILD-SNAPSHOT)"
|
||||
},
|
||||
{
|
||||
"id": "my-api",
|
||||
@@ -192,7 +192,7 @@
|
||||
"default": "2.1.4.RELEASE",
|
||||
"values": [
|
||||
{
|
||||
"id": "2.2.0.BUILD-SNAPSHOT",
|
||||
"id": "2.4.0.BUILD-SNAPSHOT",
|
||||
"name": "Latest SNAPSHOT"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
{
|
||||
"id": "org.acme:bur",
|
||||
"name": "Bur",
|
||||
"versionRange": "[2.1.4.RELEASE,2.2.0.BUILD-SNAPSHOT)"
|
||||
"versionRange": "[2.1.4.RELEASE,2.4.0.BUILD-SNAPSHOT)"
|
||||
},
|
||||
{
|
||||
"id": "my-api",
|
||||
@@ -192,7 +192,7 @@
|
||||
"default": "2.1.4.RELEASE",
|
||||
"values": [
|
||||
{
|
||||
"id": "2.2.0.BUILD-SNAPSHOT",
|
||||
"id": "2.4.0.BUILD-SNAPSHOT",
|
||||
"name": "Latest SNAPSHOT"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
{
|
||||
"_links": {
|
||||
"dependencies": {
|
||||
"href": "http://@host@/dependencies{?bootVersion}",
|
||||
"templated": true
|
||||
},
|
||||
"maven-build": {
|
||||
"href": "http://@host@/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||
"templated": true
|
||||
},
|
||||
"maven-project": {
|
||||
"href": "http://@host@/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||
"templated": true
|
||||
},
|
||||
"gradle-build": {
|
||||
"href": "http://@host@/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||
"templated": true
|
||||
},
|
||||
"gradle-project": {
|
||||
"href": "http://@host@/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||
"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.4.0-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.4.0-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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user