[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 <dev@florianhotze.com>
This commit is contained in:
Florian Hotze
2026-06-26 14:34:39 +02:00
committed by GitHub
parent 2c5f67d303
commit a94c69fd36
3 changed files with 23 additions and 4 deletions
@@ -24,6 +24,7 @@ import org.eclipse.jdt.annotation.Nullable;
import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.Language; import org.graalvm.polyglot.Language;
import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker; 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.automation.jsscripting.internal.util.ThreadLocalSlf4jOutputStream;
import org.openhab.core.OpenHAB; import org.openhab.core.OpenHAB;
import org.openhab.core.automation.module.script.ScriptDependencyTracker; import org.openhab.core.automation.module.script.ScriptDependencyTracker;
@@ -75,8 +76,16 @@ public class GraalJSScriptEngineFactory implements ScriptEngineFactory {
private final JSDependencyTracker jsDependencyTracker; private final JSDependencyTracker jsDependencyTracker;
@Activate @Activate
public GraalJSScriptEngineFactory(final @Reference JSScriptServiceUtil jsScriptServiceUtil, public GraalJSScriptEngineFactory(final @Reference JSScriptServiceUtil jsScriptServiceUtil, //
final @Reference JSDependencyTracker jsDependencyTracker, Map<String, Object> config) { 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<String, Object> config) {
logger.debug("Loading GraalJSScriptEngineFactory"); logger.debug("Loading GraalJSScriptEngineFactory");
this.jsDependencyTracker = jsDependencyTracker; this.jsDependencyTracker = jsDependencyTracker;
@@ -21,7 +21,7 @@ import org.osgi.service.component.annotations.Component;
* *
* @author Jonathan Gilbert - Initial contribution * @author Jonathan Gilbert - Initial contribution
*/ */
@Component(immediate = true, service = ScriptExtensionProvider.class) @Component(immediate = true, service = { ScriptExtensionProvider.class, OSGiScriptExtensionProvider.class })
public class OSGiScriptExtensionProvider extends ScriptDisposalAwareScriptExtensionProvider { public class OSGiScriptExtensionProvider extends ScriptDisposalAwareScriptExtensionProvider {
@Override @Override
@@ -30,6 +30,7 @@ import org.mockito.quality.Strictness;
import org.openhab.automation.jsscripting.internal.GraalJSScriptEngineFactory; import org.openhab.automation.jsscripting.internal.GraalJSScriptEngineFactory;
import org.openhab.automation.jsscripting.internal.JSScriptServiceUtil; import org.openhab.automation.jsscripting.internal.JSScriptServiceUtil;
import org.openhab.automation.jsscripting.internal.fs.watch.JSDependencyTracker; 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.automation.module.script.action.ScriptExecution;
import org.openhab.core.scheduler.Scheduler; import org.openhab.core.scheduler.Scheduler;
import org.openhab.core.service.WatchService; import org.openhab.core.service.WatchService;
@@ -63,6 +64,9 @@ public abstract class GraalJSOSGiTest extends JavaOSGiTest {
@NonNullByDefault({}) @NonNullByDefault({})
ScriptExecution scriptExecution; ScriptExecution scriptExecution;
@NonNullByDefault({})
OSGiScriptExtensionProvider osgiScriptExtensionProvider;
@NonNullByDefault({}) @NonNullByDefault({})
JSScriptServiceUtil jsScriptServiceUtil; JSScriptServiceUtil jsScriptServiceUtil;
@NonNullByDefault({}) @NonNullByDefault({})
@@ -82,10 +86,14 @@ public abstract class GraalJSOSGiTest extends JavaOSGiTest {
public void beforeEach() throws Exception { public void beforeEach() throws Exception {
when(watchService.getWatchPath()).thenReturn(tempDir); when(watchService.getWatchPath()).thenReturn(tempDir);
osgiScriptExtensionProvider = new OSGiScriptExtensionProvider();
osgiScriptExtensionProvider.activate(bundleContext);
jsScriptServiceUtil = new JSScriptServiceUtil(scheduler, scriptExecution); jsScriptServiceUtil = new JSScriptServiceUtil(scheduler, scriptExecution);
jsDependencyTracker = new JSDependencyTracker(watchService); jsDependencyTracker = new JSDependencyTracker(watchService);
scriptEngineFactory = new GraalJSScriptEngineFactory(jsScriptServiceUtil, jsDependencyTracker, config); scriptEngineFactory = new GraalJSScriptEngineFactory(jsScriptServiceUtil, jsDependencyTracker,
osgiScriptExtensionProvider, config);
} }
@AfterEach @AfterEach
@@ -96,6 +104,8 @@ public abstract class GraalJSOSGiTest extends JavaOSGiTest {
jsDependencyTracker.deactivate(); jsDependencyTracker.deactivate();
jsDependencyTracker = null; jsDependencyTracker = null;
osgiScriptExtensionProvider = null;
clearInvocations(watchService, scheduler, scriptExecution); clearInvocations(watchService, scheduler, scriptExecution);
} }
} }