From e4a2ee7905ee745592236d98d8214e8f5da3b8b6 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Fri, 25 Nov 2022 19:14:36 +0100 Subject: [PATCH] cache boot version results from maven central to avoid too many unnecessary requests --- .../vscode/boot/app/BootVersionValidator.java | 1 + .../BootVersionsFromMavenCentral.java | 29 +++++++--- .../CachedBootVersionsFromMavenCentral.java | 58 +++++++++++++++++++ .../json/ResolvedSpringProject.java | 10 +--- 4 files changed, 82 insertions(+), 16 deletions(-) create mode 100644 headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/CachedBootVersionsFromMavenCentral.java diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidator.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidator.java index 34da2f69c..fbd6065e7 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidator.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidator.java @@ -28,6 +28,7 @@ import org.springframework.stereotype.Component; public class BootVersionValidator { private static final Logger log = LoggerFactory.getLogger(BootVersionValidator.class); + private SimpleLanguageServer server; private BootJavaConfig config; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/BootVersionsFromMavenCentral.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/BootVersionsFromMavenCentral.java index f64bdcae2..c43964da9 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/BootVersionsFromMavenCentral.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/BootVersionsFromMavenCentral.java @@ -15,6 +15,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -26,26 +28,32 @@ import org.springframework.web.client.RestTemplate; public class BootVersionsFromMavenCentral { + private static final Logger log = LoggerFactory.getLogger(BootVersionsFromMavenCentral.class); private static final String URL = "https://search.maven.org/solrsearch/select?q=g:org.springframework.boot+AND+a:spring-boot-starter-parent&core=gav&rows=200&wt=json"; @SuppressWarnings({ "rawtypes", "unchecked" }) - public static List getBootVersions() { + public static List getBootVersions() throws Exception { HttpHeaders headers = new HttpHeaders(); - headers.setAccept(MediaType.parseMediaTypes("application/json")); HttpEntity entity = new HttpEntity(headers); - RestTemplate restTemplate = new RestTemplate(); - try { - ResponseEntity responseEntity = restTemplate.exchange(URL, HttpMethod.GET, entity, Map.class); + + log.info("search maven central for Spring Boot release information via: " + URL); + + ResponseEntity responseEntity = restTemplate.exchange(URL, HttpMethod.GET, entity, Map.class); + int status = responseEntity.getStatusCodeValue(); + + log.info("search maven central response code: " + status); + + if (status == 200) { Map json = responseEntity.getBody(); Map response = (Map) json.get("response"); if (response != null) { List versions = new ArrayList<>(); Object docs = response.get("docs"); + if (docs instanceof List) { - for (Object o : (List) docs) { if (o instanceof Map) { Map e = (Map) o; @@ -62,10 +70,13 @@ public class BootVersionsFromMavenCentral { Collections.sort(versions); return versions; } - } catch (Exception e) { - // Error case + else { + throw new Exception("unable to access Spring Boot versions from Maven Central, empty response"); + } + } + else { + throw new Exception("unable to access Spring Boot versions from Maven Central, query returned " + status); } - return null; } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/CachedBootVersionsFromMavenCentral.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/CachedBootVersionsFromMavenCentral.java new file mode 100644 index 000000000..54f1abb95 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/CachedBootVersionsFromMavenCentral.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2022 VMware, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VMware, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.validation.generations; + +import java.time.Duration; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.ide.vscode.commons.java.Version; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableList; + +public class CachedBootVersionsFromMavenCentral { + + private static final Logger log = LoggerFactory.getLogger(CachedBootVersionsFromMavenCentral.class); + + private static final String KEY = "cacheKey"; + private static final Duration EXPIRES_AFTER = Duration.ofMinutes(60); + + private static final LoadingCache> cache = CacheBuilder.newBuilder() + .expireAfterWrite(EXPIRES_AFTER) + .build(new CacheLoader>() { + + @Override + public List load(String key) { + try { + return BootVersionsFromMavenCentral.getBootVersions(); + } + catch (Exception e) { + return ImmutableList.of(); + } + } + + }); + + public static List getBootVersions() { + try { + return cache.get(KEY); + } + catch (Exception e) { + log.error("failed to load Spring Boot release information from maven central", e); + return ImmutableList.of(); + } + } + +} diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/json/ResolvedSpringProject.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/json/ResolvedSpringProject.java index 3980a2ddc..682ea2c24 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/json/ResolvedSpringProject.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/json/ResolvedSpringProject.java @@ -12,7 +12,7 @@ package org.springframework.ide.vscode.boot.validation.generations.json; import java.util.List; -import org.springframework.ide.vscode.boot.validation.generations.BootVersionsFromMavenCentral; +import org.springframework.ide.vscode.boot.validation.generations.CachedBootVersionsFromMavenCentral; import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsClient; import org.springframework.ide.vscode.commons.java.Version; @@ -22,7 +22,6 @@ public class ResolvedSpringProject extends SpringProject { private final SpringProjectsClient client; private Generations generations; - private List releases; public ResolvedSpringProject(SpringProject project, SpringProjectsClient client) { this.client = client; @@ -53,10 +52,7 @@ public class ResolvedSpringProject extends SpringProject { * @throws Exception */ public List getReleases() throws Exception { - // cache the releases to prevent frequent calls to the client - if (this.releases == null) { - this.releases = BootVersionsFromMavenCentral.getBootVersions(); - } - return this.releases != null ? this.releases : ImmutableList.of(); + return CachedBootVersionsFromMavenCentral.getBootVersions(); } + }