Attempted fix of suspected deadlock
See: https://github.com/spring-projects/sts4/issues/136
This commit is contained in:
@@ -217,7 +217,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
|
||||
});
|
||||
|
||||
server.onInitialize(this::initialize);
|
||||
server.onInitialized(this::initialized);
|
||||
server.doOnInitialized(this::initialized);
|
||||
server.onShutdown(this::shutdown);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
package org.springframework.ide.vscode.boot.jdt.ls;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public interface InitializableJavaProjectsService extends JavaProjectsService {
|
||||
|
||||
Disposable initialize() throws Exception;
|
||||
|
||||
Mono<Disposable> initialize();
|
||||
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ import com.google.common.base.Suppliers;
|
||||
import reactor.core.Disposable;
|
||||
|
||||
public class JavaProjectsServiceWithFallback implements JavaProjectsService {
|
||||
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(JavaProjectsServiceWithFallback.class);
|
||||
|
||||
final private CompletableFuture<Void> initialized = new CompletableFuture<Void>();
|
||||
final private CompletableFuture<Disposable> mainServiceInitialized;
|
||||
|
||||
final private SimpleLanguageServer server;
|
||||
private Supplier<JavaProjectsService> fallback;
|
||||
@@ -42,30 +42,22 @@ public class JavaProjectsServiceWithFallback implements JavaProjectsService {
|
||||
this.main = main;
|
||||
this.fallback = Suppliers.memoize(fallback);
|
||||
this.server = server;
|
||||
CompletableFuture<Disposable> disposable = new CompletableFuture<Disposable>();
|
||||
this.server.onInitialized(() -> {
|
||||
try {
|
||||
disposable.complete(main.initialize());
|
||||
initialized.complete(null);
|
||||
} catch (Throwable e) {
|
||||
log.info("Fallback classpath provider will be enabled");
|
||||
disposable.complete(()-> {});
|
||||
initialized.completeExceptionally(e);
|
||||
}
|
||||
});
|
||||
this.server.onShutdown(() ->
|
||||
disposable.thenAccept(Disposable::dispose).join()
|
||||
this.mainServiceInitialized = this.server
|
||||
.onInitialized(main.initialize())
|
||||
.toFuture();
|
||||
this.server.onShutdown(() ->
|
||||
mainServiceInitialized.thenAccept(Disposable::dispose).join()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<IJavaProject> find(TextDocumentIdentifier doc) {
|
||||
if (initialized.isDone()) {
|
||||
if (initialized.isCompletedExceptionally()) {
|
||||
if (mainServiceInitialized.isDone()) {
|
||||
if (mainServiceInitialized.isCompletedExceptionally()) {
|
||||
return fallback.get().find(doc);
|
||||
} else {
|
||||
return main.find(doc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug("find => NOT INITIALIZED YET");
|
||||
}
|
||||
@@ -75,7 +67,7 @@ public class JavaProjectsServiceWithFallback implements JavaProjectsService {
|
||||
|
||||
@Override
|
||||
public void addListener(Listener listener) {
|
||||
initialized.handle((success, failed) -> {
|
||||
mainServiceInitialized.handle((success, failed) -> {
|
||||
if (failed!=null) {
|
||||
fallback.get().addListener(listener);
|
||||
} else {
|
||||
@@ -87,7 +79,7 @@ public class JavaProjectsServiceWithFallback implements JavaProjectsService {
|
||||
|
||||
@Override
|
||||
public void removeListener(Listener listener) {
|
||||
initialized.handle((success, failed) -> {
|
||||
mainServiceInitialized.handle((success, failed) -> {
|
||||
if (failed!=null) {
|
||||
fallback.get().removeListener(listener);
|
||||
} else {
|
||||
@@ -99,12 +91,12 @@ public class JavaProjectsServiceWithFallback implements JavaProjectsService {
|
||||
|
||||
@Override
|
||||
public IJavadocProvider javadocProvider(String projectUri, CPE classpathEntry) {
|
||||
if (initialized.isDone()) {
|
||||
if (initialized.isCompletedExceptionally()) {
|
||||
if (mainServiceInitialized.isDone()) {
|
||||
if (mainServiceInitialized.isCompletedExceptionally()) {
|
||||
return fallback.get().javadocProvider(projectUri, classpathEntry);
|
||||
} else {
|
||||
return main.javadocProvider(projectUri, classpathEntry);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug("javadoc => NOT INITIALIZED YET");
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.UriUtil;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class JdtLsProjectCache implements InitializableJavaProjectsService {
|
||||
|
||||
@@ -163,45 +164,43 @@ public class JdtLsProjectCache implements InitializableJavaProjectsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Disposable initialize() throws Exception {
|
||||
try {
|
||||
return server.addClasspathListener(new ClasspathListener() {
|
||||
@Override
|
||||
public void changed(Event event) {
|
||||
log.debug("claspath event received {}", event);
|
||||
server.onInitialized(() -> {
|
||||
//log.info("initialized.thenRun block entered");
|
||||
try {
|
||||
synchronized (table) {
|
||||
String uri = UriUtil.normalize(event.projectUri);
|
||||
log.debug("uri = {}", uri);
|
||||
if (event.deleted) {
|
||||
log.debug("event.deleted = true");
|
||||
JavaProject deleted = table.remove(uri);
|
||||
if (deleted!=null) {
|
||||
log.debug("removed from table = true");
|
||||
notifyDelete(deleted);
|
||||
} else {
|
||||
log.warn("Deleted project not removed because uri {} not found in {}", uri, table.keySet());
|
||||
}
|
||||
public Mono<Disposable> initialize() {
|
||||
return server.addClasspathListener(new ClasspathListener() {
|
||||
@Override
|
||||
public void changed(Event event) {
|
||||
log.debug("claspath event received {}", event);
|
||||
server.doOnInitialized(() -> {
|
||||
//log.info("initialized.thenRun block entered");
|
||||
try {
|
||||
synchronized (table) {
|
||||
String uri = UriUtil.normalize(event.projectUri);
|
||||
log.debug("uri = {}", uri);
|
||||
if (event.deleted) {
|
||||
log.debug("event.deleted = true");
|
||||
JavaProject deleted = table.remove(uri);
|
||||
if (deleted!=null) {
|
||||
log.debug("removed from table = true");
|
||||
notifyDelete(deleted);
|
||||
} else {
|
||||
log.debug("deleted = false");
|
||||
JavaProject newProject = new JavaProject(getFileObserver(), new URI(uri), new ClasspathData(event.name, event.classpath.getEntries()), JdtLsProjectCache.this);
|
||||
JavaProject oldProject = table.put(uri, newProject);
|
||||
if (oldProject != null) {
|
||||
notifyChanged(newProject);
|
||||
} else {
|
||||
notifyCreated(newProject);
|
||||
}
|
||||
log.warn("Deleted project not removed because uri {} not found in {}", uri, table.keySet());
|
||||
}
|
||||
} else {
|
||||
log.debug("deleted = false");
|
||||
JavaProject newProject = new JavaProject(getFileObserver(), new URI(uri), new ClasspathData(event.name, event.classpath.getEntries()), JdtLsProjectCache.this);
|
||||
JavaProject oldProject = table.put(uri, newProject);
|
||||
if (oldProject != null) {
|
||||
notifyChanged(newProject);
|
||||
} else {
|
||||
notifyCreated(newProject);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).doOnError(t -> {
|
||||
if (isNoJdtError(t)) {
|
||||
log.info("JDT Language Server not available. Fallback classpath provider will be used instead.");
|
||||
} else if (isOldJdt(t)) {
|
||||
@@ -209,7 +208,6 @@ public class JdtLsProjectCache implements InitializableJavaProjectsService {
|
||||
} else {
|
||||
log.error("Unexpected error registering classpath listener with JDT. Fallback classpath provider will be used instead.", t);
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user