From a94c69fd360a35c4a3904c2a2a2c9420bcfbb82e Mon Sep 17 00:00:00 2001 From: Florian Hotze Date: Fri, 26 Jun 2026 14:34:39 +0200 Subject: [PATCH] [jsscripting] Await activation of OSGiScriptExtensionProvider before registering ScriptEngineFactory (#21042) * [jsscripting] Await activation of OSGiScriptExtensionProvider before registering ScriptEngineFactory This ensures that OSGiScriptExtensionProvider / `require('@runtime/osgi').bundleContext` is always available when JS ScriptEngines are created. Fixes issues such as #21014. Signed-off-by: Florian Hotze --- .../internal/GraalJSScriptEngineFactory.java | 13 +++++++++++-- .../internal/scope/OSGiScriptExtensionProvider.java | 2 +- .../automation/jsscripting/GraalJSOSGiTest.java | 12 +++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java index 53287a5339..52d4e17dd2 100644 --- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java +++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/GraalJSScriptEngineFactory.java @@ -24,6 +24,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.Language; import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker; +import org.openhab.automation.jsscripting.internal.scope.OSGiScriptExtensionProvider; import org.openhab.automation.jsscripting.internal.util.ThreadLocalSlf4jOutputStream; import org.openhab.core.OpenHAB; import org.openhab.core.automation.module.script.ScriptDependencyTracker; @@ -75,8 +76,16 @@ public class GraalJSScriptEngineFactory implements ScriptEngineFactory { private final JSDependencyTracker jsDependencyTracker; @Activate - public GraalJSScriptEngineFactory(final @Reference JSScriptServiceUtil jsScriptServiceUtil, - final @Reference JSDependencyTracker jsDependencyTracker, Map config) { + public GraalJSScriptEngineFactory(final @Reference JSScriptServiceUtil jsScriptServiceUtil, // + final @Reference JSDependencyTracker jsDependencyTracker, // + final @Reference OSGiScriptExtensionProvider osgiScriptExtensionProvider, // declare dependency on + // OSGiScriptExtensionProvider to + // fix a timing issue where + // openhab-js attempts to lookup + // OSGi services before + // OSGiScriptExtensionProvider is + // active + Map config) { logger.debug("Loading GraalJSScriptEngineFactory"); this.jsDependencyTracker = jsDependencyTracker; diff --git a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/scope/OSGiScriptExtensionProvider.java b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/scope/OSGiScriptExtensionProvider.java index c3555d1555..117ca3175e 100644 --- a/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/scope/OSGiScriptExtensionProvider.java +++ b/bundles/org.openhab.automation.jsscripting/src/main/java/org/openhab/automation/jsscripting/internal/scope/OSGiScriptExtensionProvider.java @@ -21,7 +21,7 @@ import org.osgi.service.component.annotations.Component; * * @author Jonathan Gilbert - Initial contribution */ -@Component(immediate = true, service = ScriptExtensionProvider.class) +@Component(immediate = true, service = { ScriptExtensionProvider.class, OSGiScriptExtensionProvider.class }) public class OSGiScriptExtensionProvider extends ScriptDisposalAwareScriptExtensionProvider { @Override diff --git a/itests/org.openhab.automation.jsscripting.tests/src/main/java/org/openhab/automation/jsscripting/GraalJSOSGiTest.java b/itests/org.openhab.automation.jsscripting.tests/src/main/java/org/openhab/automation/jsscripting/GraalJSOSGiTest.java index e8de6d8a92..8da06df937 100644 --- a/itests/org.openhab.automation.jsscripting.tests/src/main/java/org/openhab/automation/jsscripting/GraalJSOSGiTest.java +++ b/itests/org.openhab.automation.jsscripting.tests/src/main/java/org/openhab/automation/jsscripting/GraalJSOSGiTest.java @@ -30,6 +30,7 @@ import org.mockito.quality.Strictness; import org.openhab.automation.jsscripting.internal.GraalJSScriptEngineFactory; import org.openhab.automation.jsscripting.internal.JSScriptServiceUtil; import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker; +import org.openhab.automation.jsscripting.internal.scope.OSGiScriptExtensionProvider; import org.openhab.core.automation.module.script.action.ScriptExecution; import org.openhab.core.scheduler.Scheduler; import org.openhab.core.service.WatchService; @@ -63,6 +64,9 @@ public abstract class GraalJSOSGiTest extends JavaOSGiTest { @NonNullByDefault({}) ScriptExecution scriptExecution; + @NonNullByDefault({}) + OSGiScriptExtensionProvider osgiScriptExtensionProvider; + @NonNullByDefault({}) JSScriptServiceUtil jsScriptServiceUtil; @NonNullByDefault({}) @@ -82,10 +86,14 @@ public abstract class GraalJSOSGiTest extends JavaOSGiTest { public void beforeEach() throws Exception { when(watchService.getWatchPath()).thenReturn(tempDir); + osgiScriptExtensionProvider = new OSGiScriptExtensionProvider(); + osgiScriptExtensionProvider.activate(bundleContext); + jsScriptServiceUtil = new JSScriptServiceUtil(scheduler, scriptExecution); jsDependencyTracker = new JSDependencyTracker(watchService); - scriptEngineFactory = new GraalJSScriptEngineFactory(jsScriptServiceUtil, jsDependencyTracker, config); + scriptEngineFactory = new GraalJSScriptEngineFactory(jsScriptServiceUtil, jsDependencyTracker, + osgiScriptExtensionProvider, config); } @AfterEach @@ -96,6 +104,8 @@ public abstract class GraalJSOSGiTest extends JavaOSGiTest { jsDependencyTracker.deactivate(); jsDependencyTracker = null; + osgiScriptExtensionProvider = null; + clearInvocations(watchService, scheduler, scriptExecution); } }