Skip to content

Commit 4fe5be7

Browse files
committed
Single error message for SprinIO service failure. Re-work progress.
1 parent 8ef70e9 commit 4fe5be7

File tree

5 files changed

+90
-44
lines changed

5 files changed

+90
-44
lines changed

Diff for: headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootVersionValidationConfig.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ public class BootVersionValidationConfig {
4242
return new UpdateBootVersion(server.getDiagnosticSeverityProvider(), bootUpgradeOpt, projectsProvider);
4343
}
4444

45-
@Bean SpringIoProjectsProvider springProjectsProvider(BootJavaConfig config, RestTemplateFactory restTemplateFactory) {
46-
return new SpringIoProjectsProvider(config, restTemplateFactory);
45+
@Bean SpringIoProjectsProvider springProjectsProvider(SimpleLanguageServer server, BootJavaConfig config, RestTemplateFactory restTemplateFactory) {
46+
return new SpringIoProjectsProvider(config, restTemplateFactory, server.getProgressService(), server.getMessageService(), 30_000);
4747
}
4848

4949
@Bean GenerationsValidator generationsValidator(SimpleLanguageServer server, SpringProjectsProvider projectsProvider) {
5050
return new GenerationsValidator(server.getDiagnosticSeverityProvider(), projectsProvider);
5151
}
5252

53-
@Bean ProjectVersionDiagnosticProvider projectVersionDiagnosticProvider(SimpleLanguageServer server, List<VersionValidator> validators) {
54-
return new ProjectVersionDiagnosticProvider(server.getProgressService(), server.getMessageService(), validators);
53+
@Bean ProjectVersionDiagnosticProvider projectVersionDiagnosticProvider(List<VersionValidator> validators) {
54+
return new ProjectVersionDiagnosticProvider(validators);
5555
}
5656

5757
@ConditionalOnMissingClass("org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2023 VMware, Inc.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* VMware, Inc. - initial API and implementation
10+
*******************************************************************************/
11+
package org.springframework.ide.vscode.boot.validation.generations;
12+
13+
public class CachedErrorStateException extends Exception {
14+
15+
private static final long serialVersionUID = 1L;
16+
17+
public CachedErrorStateException(Throwable t) {
18+
super(t);
19+
}
20+
21+
}

Diff for: headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/ProjectVersionDiagnosticProvider.java

+16-34
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,14 @@
2424
import org.springframework.ide.vscode.commons.Version;
2525
import org.springframework.ide.vscode.commons.java.IJavaProject;
2626
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
27-
import org.springframework.ide.vscode.commons.languageserver.MessageService;
28-
import org.springframework.ide.vscode.commons.languageserver.PercentageProgressTask;
29-
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
3027

3128
public class ProjectVersionDiagnosticProvider {
3229

3330
private static final Logger log = LoggerFactory.getLogger(ProjectVersionDiagnosticProvider.class);
3431

3532
private final List<VersionValidator> validators;
3633

37-
private ProgressService progressService;
38-
39-
private MessageService messageService;
40-
41-
public ProjectVersionDiagnosticProvider(ProgressService progressService, MessageService messageService, List<VersionValidator> validators) {
42-
this.progressService = progressService;
43-
this.messageService = messageService;
34+
public ProjectVersionDiagnosticProvider(List<VersionValidator> validators) {
4435
this.validators = validators;
4536
}
4637

@@ -57,33 +48,24 @@ public DiagnosticResult getDiagnostics(IJavaProject javaProject) throws Exceptio
5748

5849

5950
if (!applicableValidators.isEmpty()) {
60-
PercentageProgressTask progress = progressService.createPercentageProgressTask(
61-
"validate-" + javaProject.getElementName(),
62-
applicableValidators.size(),
63-
"Validating Spring Boot Version of project '%s'".formatted(javaProject.getElementName()));
64-
65-
try {
66-
Version javaProjectVersion = SpringProjectUtil.getSpringBootVersion(javaProject);
67-
68-
if (javaProjectVersion == null) {
69-
log.warn("Unable to resolve version for project: " + javaProject.getLocationUri().toASCIIString());
70-
return new DiagnosticResult(buildFileUri, Collections.emptyList());
71-
}
51+
Version javaProjectVersion = SpringProjectUtil.getSpringBootVersion(javaProject);
52+
53+
if (javaProjectVersion == null) {
54+
log.warn("Unable to resolve version for project: " + javaProject.getLocationUri().toASCIIString());
55+
return new DiagnosticResult(buildFileUri, Collections.emptyList());
56+
}
7257

73-
for (VersionValidator validator : applicableValidators) {
74-
try {
75-
Collection<Diagnostic> batch = validator.validate(javaProject, javaProjectVersion);
76-
if (batch != null) {
77-
diagnostics.addAll(batch);
78-
}
79-
} catch (Exception e) {
80-
messageService.error("Failed Spring Boot version validation for project '%s': %s".formatted(javaProject.getElementName(), e.getMessage()));
81-
log.error("", e);
58+
for (VersionValidator validator : applicableValidators) {
59+
try {
60+
Collection<Diagnostic> batch = validator.validate(javaProject, javaProjectVersion);
61+
if (batch != null) {
62+
diagnostics.addAll(batch);
8263
}
83-
progress.increment();
64+
} catch (CachedErrorStateException e) {
65+
// ignore the cached error state
66+
} catch (Exception e) {
67+
log.error("", e);
8468
}
85-
} finally {
86-
progress.done();
8769
}
8870
}
8971

Diff for: headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/validation/generations/SpringIoProjectsProvider.java

+48-5
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@
1212

1313
import java.util.List;
1414
import java.util.Map;
15+
import java.util.Optional;
1516

1617
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
1718
import org.springframework.ide.vscode.boot.app.RestTemplateFactory;
1819
import org.springframework.ide.vscode.boot.validation.generations.json.ResolvedSpringProject;
1920
import org.springframework.ide.vscode.boot.validation.generations.json.SpringProject;
2021
import org.springframework.ide.vscode.boot.validation.generations.json.SpringProjects;
22+
import org.springframework.ide.vscode.commons.languageserver.IndefiniteProgressTask;
23+
import org.springframework.ide.vscode.commons.languageserver.MessageService;
24+
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
2125

2226
import com.google.common.collect.ImmutableMap;
2327
import com.google.common.collect.ImmutableMap.Builder;
@@ -31,13 +35,23 @@
3135
*
3236
*/
3337
public class SpringIoProjectsProvider implements SpringProjectsProvider {
34-
38+
3539
private SpringProjectsClient client;
3640
private Map<String, ResolvedSpringProject> cache;
3741
private RestTemplateFactory restTemplateFactory;
42+
final private ProgressService progressService;
43+
final private MessageService messageService;
44+
final private long errorStateCachingTime;
45+
46+
private long lastErrorTime;
47+
private Optional<Throwable> errorState;
3848

39-
public SpringIoProjectsProvider(BootJavaConfig config, RestTemplateFactory restTemplateFactory) {
49+
public SpringIoProjectsProvider(BootJavaConfig config, RestTemplateFactory restTemplateFactory, ProgressService progressService, MessageService messageService, long errorStateCachingTime) {
4050
this.restTemplateFactory = restTemplateFactory;
51+
this.progressService = progressService;
52+
this.messageService = messageService;
53+
this.errorStateCachingTime = errorStateCachingTime;
54+
clearErrorState();
4155
updateIoApiUri(config.getSpringIOApiUrl());
4256
config.addListener(v -> updateIoApiUri(config.getSpringIOApiUrl()));
4357
}
@@ -46,6 +60,7 @@ public synchronized void updateIoApiUri(String uri) {
4660
if (client == null || !uri.equals(client.getUrl())) {
4761
this.client = new SpringProjectsClient(uri, restTemplateFactory);
4862
cache = null;
63+
clearErrorState();
4964
}
5065
}
5166

@@ -63,12 +78,40 @@ public synchronized ResolvedSpringProject getProject(String projectSlug) throws
6378

6479
private Map<String, ResolvedSpringProject> cache() throws Exception {
6580
if (cache == null) {
66-
SpringProjects springProjects = client.getSpringProjects();
67-
cache = asMap(springProjects);
81+
if (lastErrorTime + errorStateCachingTime < System.currentTimeMillis()) {
82+
IndefiniteProgressTask progress = progressService.createIndefiniteProgressTask("fetching-from-spring-io", "Fetching Generations from Spring IO", null);
83+
try {
84+
SpringProjects springProjects = client.getSpringProjects();
85+
cache = asMap(springProjects);
86+
// Wipe out error state
87+
clearErrorState();
88+
} catch (Exception e) {
89+
messageService.error("Failed to fetch Generation from Spring IO: %s".formatted(e.getMessage()));
90+
setErrorState(e);
91+
throw e;
92+
} finally {
93+
progress.done();
94+
}
95+
} else {
96+
// The error state hasn't expired - throw a cached error state exception
97+
if (errorState.isPresent()) {
98+
throw new CachedErrorStateException(errorState.get());
99+
}
100+
}
68101
}
69102
return cache != null ? cache : ImmutableMap.of();
70103
}
71-
104+
105+
private void clearErrorState() {
106+
errorState = Optional.empty();
107+
lastErrorTime = 0;
108+
}
109+
110+
private void setErrorState(Throwable t) {
111+
errorState = Optional.of(t);
112+
lastErrorTime = System.currentTimeMillis();
113+
}
114+
72115
private Map<String, ResolvedSpringProject> asMap(SpringProjects springProjects) {
73116
Builder<String, ResolvedSpringProject> builder = ImmutableMap.builder();
74117

Diff for: headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/validation/test/ProjectGenerationsValidationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void setup() throws Exception {
5656

5757
@Test
5858
void testProjectsInfoFromSpringIo() throws Exception {
59-
SpringProjectsProvider cache = new SpringIoProjectsProvider(config, restTemplateFactory);
59+
SpringProjectsProvider cache = new SpringIoProjectsProvider(config, restTemplateFactory, harness.getServer().getProgressService(), harness.getServer().getMessageService(), -1);
6060

6161
SpringProject project = cache.getProject("spring-boot");
6262
assertNotNull(project);

0 commit comments

Comments
 (0)