Dedicated dependencies UI endpoint

Move the `/dependencies` endpoint to `/ui/dependencies` and automatically
filter dependencies that are out of range if a base boot version is
provided.

See gh-145
This commit is contained in:
Stephane Nicoll
2015-09-30 12:52:39 +02:00
parent 5c05a9a373
commit 7fe849a5bf
7 changed files with 219 additions and 9 deletions

View File

@@ -28,6 +28,7 @@ import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.metadata.InitializrProperties import io.spring.initializr.metadata.InitializrProperties
import io.spring.initializr.support.DefaultInitializrMetadataProvider import io.spring.initializr.support.DefaultInitializrMetadataProvider
import io.spring.initializr.web.MainController import io.spring.initializr.web.MainController
import io.spring.initializr.web.UiController
import io.spring.initializr.web.WebConfig import io.spring.initializr.web.WebConfig
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
@@ -72,6 +73,12 @@ class InitializrAutoConfiguration {
new MainController() new MainController()
} }
@Bean
@ConditionalOnMissingBean(UiController)
UiController initializrUiController() {
new UiController()
}
@Bean @Bean
@ConditionalOnMissingBean(ProjectGenerator) @ConditionalOnMissingBean(ProjectGenerator)
ProjectGenerator projectGenerator() { ProjectGenerator projectGenerator() {

View File

@@ -24,7 +24,6 @@ import io.spring.initializr.mapper.InitializrMetadataV2JsonMapper
import io.spring.initializr.mapper.InitializrMetadataVersion import io.spring.initializr.mapper.InitializrMetadataVersion
import io.spring.initializr.generator.ProjectGenerator import io.spring.initializr.generator.ProjectGenerator
import io.spring.initializr.generator.ProjectRequest import io.spring.initializr.generator.ProjectRequest
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.InitializrMetadata import io.spring.initializr.metadata.InitializrMetadata
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
@@ -126,12 +125,6 @@ class MainController extends AbstractInitializrController {
renderHome('home.html') renderHome('home.html')
} }
@RequestMapping(value = '/dependencies.json', produces = 'application/json')
@ResponseBody
List<Dependency> dependencies() {
metadataProvider.get().dependencies.content.collectMany {it.content}
}
@RequestMapping('/spring') @RequestMapping('/spring')
String spring() { String spring() {
def url = metadataProvider.get().createCliDistributionURl('zip') def url = metadataProvider.get().createCliDistributionURl('zip')

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2012-2015 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
*
* http://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
import groovy.json.JsonBuilder
import io.spring.initializr.metadata.DependenciesCapability
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.util.Version
import io.spring.initializr.util.VersionRange
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
/**
* UI specific controller providing dedicated endpoints for the Web UI.
*
* @author Stephane Nicoll
* @since 1.0
*/
@RestController
class UiController {
@Autowired
protected InitializrMetadataProvider metadataProvider
@RequestMapping(value = "/ui/dependencies" , produces = ["application/json"])
String dependencies(@RequestParam(required = false) String version) {
DependenciesCapability dependenciesCapability = metadataProvider.get().dependencies
List<Dependency> allDependencies = dependenciesCapability.content.collectMany { it.content }
if (version) {
Version v = Version.parse(version)
def filteredDependencies = allDependencies.findAll { d ->
if (d.versionRange) {
return VersionRange.parse(d.versionRange).match(v)
}
return true
}
writeDependencies(filteredDependencies)
} else {
writeDependencies(allDependencies)
}
}
private static String writeDependencies(List<Dependency> deps) {
JsonBuilder json = new JsonBuilder();
json {
dependencies deps.collect { d ->
mapDependency(d)
}
}
json.toString()
}
private static mapDependency(Dependency d) {
def result = [:]
result.id = d.id
result.name = d.name
result.description = d.description
result
}
}

View File

@@ -92,9 +92,9 @@ $(function () {
$("#starters div[data-id='" + id + "']").remove(); $("#starters div[data-id='" + id + "']").remove();
}; };
var initializeSearchEngine = function (engine, bootVersion) { var initializeSearchEngine = function (engine, bootVersion) {
$.getJSON("/dependencies.json?version=" + bootVersion, function (data) { $.getJSON("/ui/dependencies.json?version=" + bootVersion, function (data) {
engine.clear(); engine.clear();
engine.add(data); engine.add(data.dependencies);
}); });
}; };
refreshDependencies($("#bootVersion").val()); refreshDependencies($("#bootVersion").val());

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2012-2015 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
*
* http://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
import org.json.JSONObject
import org.junit.Test
import org.skyscreamer.jsonassert.JSONAssert
import org.skyscreamer.jsonassert.JSONCompareMode
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.test.context.ActiveProfiles
/**
* @author Stephane Nicoll
*/
@ActiveProfiles('test-default')
class UiControllerIntegrationTests extends AbstractInitializrControllerIntegrationTests {
@Test
void dependenciesNoVersion() {
ResponseEntity<String> response = execute('/ui/dependencies', String, null, null)
validateContentType(response, MediaType.APPLICATION_JSON)
validateDependenciesOutput('all', new JSONObject(response.body))
}
@Test
void dependenciesSpecificVersion() {
ResponseEntity<String> response = execute('/ui/dependencies?version=1.1.2.RELEASE', String, null, null)
validateContentType(response, MediaType.APPLICATION_JSON)
validateDependenciesOutput('1.1.2', new JSONObject(response.body))
}
protected void validateDependenciesOutput(String version, JSONObject actual) {
def expected = readJsonFrom("metadata/dependencies/test-dependencies-$version" + ".json")
JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT)
}
}

View File

@@ -0,0 +1,34 @@
{
"dependencies": [
{
"id": "web",
"name": "Web",
"description": "Web dependency description"
},
{
"id": "security",
"name": "Security",
"description": null
},
{
"id": "data-jpa",
"name": "Data JPA",
"description": null
},
{
"id": "org.acme:foo",
"name": "Foo",
"description": null
},
{
"id": "org.acme:bar",
"name": "Bar",
"description": null
},
{
"id": "my-api",
"name": "My API",
"description": null
}
]
}

View File

@@ -0,0 +1,44 @@
{
"dependencies": [
{
"id": "web",
"name": "Web",
"description": "Web dependency description"
},
{
"id": "security",
"name": "Security",
"description": null
},
{
"id": "data-jpa",
"name": "Data JPA",
"description": null
},
{
"id": "org.acme:foo",
"name": "Foo",
"description": null
},
{
"id": "org.acme:bar",
"name": "Bar",
"description": null
},
{
"id": "org.acme:biz",
"name": "Biz",
"description": null
},
{
"id": "org.acme:bur",
"name": "Bur",
"description": null
},
{
"id": "my-api",
"name": "My API",
"description": null
}
]
}