From 92c6a1698f22bec0df6b934b13fb8840ef3e6f49 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Wed, 14 Sep 2022 15:46:12 -0700 Subject: [PATCH] Enable m2e-apt by default Also a small bugfix related to enabling spring-boot validation builder on new projects. Both of these contribute to make a smoother experience working with JDT APT. See: https://github.com/spring-projects/sts4/issues/822 --- .../validation/BootValidationEnabler.java | 2 +- .../plugin.xml | 4 ++- .../core/internal/MavenSpringBootProject.java | 7 ++-- .../MavenAptPreferenceInitializer.java | 34 +++++++++++++++++++ .../workspace/ClasspathListenerManager.java | 23 +++++++++++-- 5 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/MavenAptPreferenceInitializer.java diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/src/org/springframework/ide/eclipse/boot/validation/BootValidationEnabler.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/src/org/springframework/ide/eclipse/boot/validation/BootValidationEnabler.java index 904932f35..86c5d505d 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/src/org/springframework/ide/eclipse/boot/validation/BootValidationEnabler.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.validation/src/org/springframework/ide/eclipse/boot/validation/BootValidationEnabler.java @@ -109,7 +109,7 @@ public class BootValidationEnabler implements org.eclipse.ui.IStartup { @Override public void earlyStartup() { //Don't do this stuff actually during startup. Its not critical and it can wait. - new ValidationEnablerStartupJob().schedule(Duration.ofMinutes(1).toMillis()); + new ValidationEnablerStartupJob().schedule(Duration.ofSeconds(10).toMillis()); } } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/plugin.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot/plugin.xml index 0996cf6f2..35b30cc45 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot/plugin.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/plugin.xml @@ -272,5 +272,7 @@ point="org.springframework.ide.eclipse.boot.project"> - + + + diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/internal/MavenSpringBootProject.java b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/internal/MavenSpringBootProject.java index aa09f2b4b..9547874e5 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/internal/MavenSpringBootProject.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/core/internal/MavenSpringBootProject.java @@ -36,7 +36,6 @@ import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.performOnDOMDocu import java.io.File; import java.lang.reflect.Constructor; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -337,7 +336,11 @@ public class MavenSpringBootProject extends SpringBootProject { protected IStatus run(IProgressMonitor arg0) { Job job = createUpdateMavenProjectJob(getProject()); if (job != null) { - job.schedule(); + job.schedule(2000); //Without 2000ms delay, we tend to get deadlocks. + // TODO: ^^^^ debug this and find a better solution (suspect this actually bug in m2e, + // but it rarely happens when a user invokes the operation from the UI. + // It happens here presumably because some updates happen in quick succession + // and this causes some sort of a race condition causing a deadlock situation. return Status.OK_STATUS; } else { diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/MavenAptPreferenceInitializer.java b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/MavenAptPreferenceInitializer.java new file mode 100644 index 000000000..9e4242e8c --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot/src/org/springframework/ide/eclipse/boot/ui/preferences/MavenAptPreferenceInitializer.java @@ -0,0 +1,34 @@ +package org.springframework.ide.eclipse.boot.ui.preferences; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.ui.IStartup; +import org.osgi.service.prefs.BackingStoreException; +import org.springframework.ide.eclipse.boot.core.BootActivator; +import org.springsource.ide.eclipse.commons.livexp.util.Log; + +public class MavenAptPreferenceInitializer implements IStartup { + + private static final String M2E_APT_PLUGIN_ID = "org.eclipse.m2e.apt"; + private static final String PREF_MODE= M2E_APT_PLUGIN_ID+".mode"; + + private static final String PREF_STS_CUSTONISATIONS_APPLIED= BootActivator.PLUGIN_ID+".customised"; + // ^^^ used to ensure we do not apply our customisations more than once (allows users to change the preference + // by themselves and not have us repeatedly return it back to our own default setting. + + @Override + public void earlyStartup() { + try { + IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(M2E_APT_PLUGIN_ID); + if (!prefs.getBoolean(PREF_STS_CUSTONISATIONS_APPLIED, false)) { + prefs.put(PREF_MODE, "jdt_apt"); + prefs.putBoolean(PREF_STS_CUSTONISATIONS_APPLIED, true); + } + prefs.flush(); + } catch (BackingStoreException e) { + Log.log(e); + } + } +} diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/src/org/springsource/ide/eclipse/commons/frameworks/core/workspace/ClasspathListenerManager.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/src/org/springsource/ide/eclipse/commons/frameworks/core/workspace/ClasspathListenerManager.java index fc17c9fd7..81c51b213 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/src/org/springsource/ide/eclipse/commons/frameworks/core/workspace/ClasspathListenerManager.java +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.frameworks.core/src/org/springsource/ide/eclipse/commons/frameworks/core/workspace/ClasspathListenerManager.java @@ -10,6 +10,10 @@ *******************************************************************************/ package org.springsource.ide.eclipse.commons.frameworks.core.workspace; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; @@ -37,6 +41,8 @@ public class ClasspathListenerManager implements Disposable { private class MyListener implements IElementChangedListener { + private Set knownProjectNames = Collections.synchronizedSet(new HashSet<>()); + //@Override public void elementChanged(ElementChangedEvent event) { visit(event.getDelta()); @@ -49,8 +55,9 @@ public class ClasspathListenerManager implements Disposable { visitChildren(delta); break; case IJavaElement.JAVA_PROJECT: - if (isClasspathChanged(delta.getFlags())) { - listener.classpathChanged((IJavaProject)el); + IJavaProject jp = (IJavaProject) el; + if (isNewProject(jp) || isClasspathChanged(delta.getFlags())) { + listener.classpathChanged(jp); } break; default: @@ -58,6 +65,10 @@ public class ClasspathListenerManager implements Disposable { } } + private boolean isNewProject(IJavaProject jp) { + return knownProjectNames.add(jp.getElementName()); + } + private boolean isClasspathChanged(int flags) { return 0!= (flags & ( IJavaElementDelta.F_CLASSPATH_CHANGED | @@ -70,6 +81,10 @@ public class ClasspathListenerManager implements Disposable { visit(c); } } + + public void addKnownProject(IJavaProject jp) { + this.knownProjectNames.add(jp.getElementName()); + } } private ClasspathListener listener; @@ -83,19 +98,21 @@ public class ClasspathListenerManager implements Disposable { */ public ClasspathListenerManager(ClasspathListener listener, boolean initialEvent) { this.listener = listener; + myListener=new MyListener(); if (initialEvent) { for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { try { if (p.isAccessible() && p.hasNature(JavaCore.NATURE_ID)) { IJavaProject jp = JavaCore.create(p); listener.classpathChanged(jp); + myListener.addKnownProject(jp); } } catch (CoreException e) { FrameworkCoreActivator.log(e); } } } - JavaCore.addElementChangedListener(myListener=new MyListener(), ElementChangedEvent.POST_CHANGE); + JavaCore.addElementChangedListener(myListener, ElementChangedEvent.POST_CHANGE); } public ClasspathListenerManager(ClasspathListener listener) {