From 5838058d21906ec954604a3ed1ea528f422ff6fe Mon Sep 17 00:00:00 2001 From: Lars Vogel Date: Thu, 27 Aug 2026 00:04:10 +0200 Subject: [PATCH 1/2] Fail fast when a model processor prerequisite is missing BindingToModelProcessor logged that CommandManager or ContextManager was null and then passed the nulls to the BindingManager constructor, which rejects them. The resulting NPE was swallowed by ModelAssembler and only surfaced much later as an InjectionException on BindingService, hiding the real cause. It now throws with a message naming the processor that should have provided the missing value, and reads the two @Reference fields that establish the ordering, so they can no longer be dropped as unused. ModelAssembler logs a failing processor as an error and names it, instead of a warning without the class. --- .../ui/internal/workbench/ModelAssembler.java | 6 ++-- .../ui/internal/BindingToModelProcessor.java | 34 ++++++++++++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java index 581e1243588..ceb2e28d2a0 100644 --- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java @@ -690,7 +690,7 @@ private void runProcessor(IConfigurationElement ce) { ContextInjectionFactory.invoke(o, Execute.class, context, localContext, null); } } catch (Exception e) { - warn("Could not run processor: {}", e); //$NON-NLS-1$ + error("Could not run processor {}: {}", ce.getAttribute("class"), e); //$NON-NLS-1$//$NON-NLS-2$ } } @@ -731,7 +731,9 @@ private void runProcessor(IModelProcessorContribution processor) { ContextInjectionFactory.invoke(o, Execute.class, context, localContext, null); } } catch (Exception e) { - warn("Could not run processor: {}", e); //$NON-NLS-1$ + Class processorClass = processor.getProcessorClass() != null ? processor.getProcessorClass() + : processor.getClass(); + error("Could not run processor {}: {}", processorClass.getName(), e); //$NON-NLS-1$ } } diff --git a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/BindingToModelProcessor.java b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/BindingToModelProcessor.java index 2ce701a02a2..08e80a28070 100644 --- a/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/BindingToModelProcessor.java +++ b/bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/BindingToModelProcessor.java @@ -52,7 +52,8 @@ public class BindingToModelProcessor implements IModelProcessorContribution { // define dependencies to CommandToModelProcessor and ContextToModelProcessor to // ensure these two IModelProcessorContributions are registered before this - // BindingToModelProcessor + // BindingToModelProcessor. Both fields are read in process(), removing them + // silently breaks that ordering. @Reference private CommandToModelProcessor commandToModelProcessor; @@ -66,14 +67,10 @@ void process(final MApplication application, IEclipseContext context) { gatherCommands(application.getCommands()); gatherTables(application.getBindingTables()); - CommandManager commandManager = context.get(CommandManager.class); - if (commandManager == null) { - WorkbenchPlugin.log("Command manager was null in org.eclipse.ui.internal.BindingToModelProcessor"); //$NON-NLS-1$ - } - ContextManager contextManager = context.get(ContextManager.class); - if (contextManager == null) { - WorkbenchPlugin.log("Context manager was null in org.eclipse.ui.internal.BindingToModelProcessor"); //$NON-NLS-1$ - } + CommandManager commandManager = requirePrerequisite(context, CommandManager.class, + CommandToModelProcessor.class, commandToModelProcessor); + ContextManager contextManager = requirePrerequisite(context, ContextManager.class, + ContextToModelProcessor.class, contextToModelProcessor); BindingManager bindingManager = new BindingManager(contextManager, commandManager); context.set(BindingManager.class, bindingManager); BindingPersistence persistence = new BindingPersistence(bindingManager, commandManager); @@ -98,6 +95,25 @@ void process(final MApplication application, IEclipseContext context) { keys.clear(); } + /** + * Returns the value stored under the given key, failing with a message that + * names the processor expected to have provided it. The provider instance is + * the DS reference that orders this processor after that one. + */ + private static T requirePrerequisite(IEclipseContext context, Class key, Class providerType, + Object provider) { + T value = context.get(key); + if (value == null || provider == null) { + String message = String.format( + "%s did not find %s in the application context. %s must run first; check that its @Reference in %s is still declared and that the OSGi component descriptors of this bundle are up to date.", //$NON-NLS-1$ + BindingToModelProcessor.class.getName(), key.getName(), providerType.getName(), + BindingToModelProcessor.class.getSimpleName()); + WorkbenchPlugin.log(message); + throw new IllegalStateException(message); + } + return value; + } + private void gatherTables(List bindingTables) { for (MBindingTable table : bindingTables) { tables.put(table.getBindingContext().getElementId(), table); From 4f7e8664044cf274d1f1c321a0c9079bad38df33 Mon Sep 17 00:00:00 2001 From: Eclipse Platform Bot Date: Wed, 26 Aug 2026 22:12:26 +0000 Subject: [PATCH 2/2] Version bump(s) for 4.41 stream --- bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF index 79b52fd9e9a..be8da055481 100644 --- a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.e4.ui.workbench;singleton:=true -Bundle-Version: 1.18.300.qualifier +Bundle-Version: 1.18.400.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin