Skip to content

Conversation

@florian-h05
Copy link
Contributor

@florian-h05 florian-h05 commented Oct 7, 2025

Fixes #5046.

@dilyanpalauzov
Copy link
Contributor

In the use case described at #5046 with automation/js/node_modules/nmod1/index.js

var a = "G"
console.log("uuu")
module.exports = { a }

sitemap

sitemap cd label="B" {
  Text item=x label="Y [JS(|require('nmod1').a + ' E'):%s]"
}

and the current change applied, when I change index.js sometimes it works, and sometimes it logs

2025-10-07 17:21:38.913 [WARN ] [ui.internal.items.ItemUIRegistryImpl] - Failed transforming the value 'NULL' with pattern 'JS(|require('nmod1').a + ' E'):NULL': Transformation service of type 'JS' threw an exception: null

and shows in the sitemap "Y -".

I think I have to reload the sitemap twice. The first time the above waring is logged, the second time console.log("uuu") is executed (logged) and the transformation is applied correctly using OH 5.1.0 Build 4847.

@florian-h05
Copy link
Contributor Author

I see the the root cause of the issue, close is called two times inside the ScriptTransformationService if ScriptEngine implements Compilable, else once, and after the engine is already closed, on the next invocation of transform the ScriptEngineManager::createScriptEngine call causes the ScriptEngineManager to internally clean up the old engine, calling scriptUnloaded on the closed engine.

florian-h05 added a commit to florian-h05/openhab-core that referenced this pull request Oct 7, 2025
Currently, there are two issues:

When a ScriptRecord is cleared from the cache,
the ScriptTransformationService currently closes the ScriptEngine itself, without involving the ScriptEngineManager.
If a transformation script is invoked again after it has been cleared from the scriptCache, the ScriptEngineManager::createScriptEngine call makes the ScriptEngineManager first remove the old engine from its internal "store",
which includes invoking the scriptUnloaded hook. This invocation can cause an exception because the engine is already closed (by ScriptTransformationService) and hence function/method invocations inside the engine are not possible anymore.

Ff the engine implement Compilable, it is even closed two times by ScriptTransformationService, possibly causing an exception if the ScriptEngine doesn't handle multiple close() calls gracefully.

These issues are fixed by properly notifying the ScriptEngineManager when an engine should be removed and leaving the removal handling to the ScriptEngineManager.

The issues were discovered while working on openhab#5062.

Signed-off-by: Florian Hotze <[email protected]>
@florian-h05
Copy link
Contributor Author

See #5063 for that fix.

@dilyanpalauzov
Copy link
Contributor

With both patches applied, it works. After changing the dependency, the dependency is reloaded when:

  • the sitemap is reloaded (F5 key in the browser), that probably means when the transformation is executed again, or
  • the item, involved in the transformation is changed with curl --header "Content-Type: text/plain" -H POST "http://192.168.0.11:8080/rest/items/x" --data "a"

After changing the dependency, the dependency does not reload when:

  • nothing else happens, or
  • the item is updated, e.g. with curl --header "Content-Type: text/plain" -H POST "http://192.168.0.11:8080/rest/items/x" --data "abcM" when the value is not changed.

@florian-h05
Copy link
Contributor Author

florian-h05 commented Oct 8, 2025

Turn on debug logging and you will see the script is always reloaded when the dependency changes.
You can't close from Item state change to dependency reload, on dependency change the transformation is not invoked again for all Items it is used on. And architecture-wise this isn’t possible. So you make sure yourself the transformation is invoked again, e.g. by reloading the page.

@dilyanpalauzov
Copy link
Contributor

Turn on debug logging and you will see the script is always reloaded when the dependency changes.

I mean above with reload, that if the dependency contains console.log("uuu") uuu is not logged. So it is maybe reloaded in memory as bytecode, but the dependency is not executed.

@florian-h05
Copy link
Contributor Author

When the dependency changes, the bytecode of the script is thrown away.
The script and thus the dependency is loaded again when the transformation is invoked the next time. Not before.

I use a JS transformation with an Item, the transformation depends on the items namespace from openhab-js:

  1. Open the Item in Main UI. The transformation gets invoked.
  2. Edit node_modules/openhab/src/items/items.js, add a log statement.
  3. ScriptTransformation service clears the cache for the transformation script
  4. I reload the Main UI page, so the transformation gets invoked again.
  5. Now the log statement is executed, as the dependency is now loaded when the script is loaded.

Proper behaviour.

@kaikreuzer kaikreuzer merged commit 508f1f6 into openhab:main Oct 10, 2025
4 checks passed
@kaikreuzer kaikreuzer added the bug An unexpected problem or unintended behavior of the Core label Oct 10, 2025
@kaikreuzer kaikreuzer added this to the 5.1 milestone Oct 10, 2025
kaikreuzer pushed a commit that referenced this pull request Oct 10, 2025
…neManager (#5063)

* ScriptTransformationService: Fix engine closed too early

Currently, there are two issues:

When a ScriptRecord is cleared from the cache,
the ScriptTransformationService currently closes the ScriptEngine itself, without involving the ScriptEngineManager.
If a transformation script is invoked again after it has been cleared from the scriptCache, the ScriptEngineManager::createScriptEngine call makes the ScriptEngineManager first remove the old engine from its internal "store",
which includes invoking the scriptUnloaded hook. This invocation can cause an exception because the engine is already closed (by ScriptTransformationService) and hence function/method invocations inside the engine are not possible anymore.

Ff the engine implement Compilable, it is even closed two times by ScriptTransformationService, possibly causing an exception if the ScriptEngine doesn't handle multiple close() calls gracefully.

These issues are fixed by properly notifying the ScriptEngineManager when an engine should be removed and leaving the removal handling to the ScriptEngineManager.

The issues were discovered while working on #5062.

Signed-off-by: Florian Hotze <[email protected]>
@florian-h05 florian-h05 deleted the script-transform-dependency-tracking branch October 10, 2025 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug An unexpected problem or unintended behavior of the Core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Transformation with ScriptEngine do not have dependecy change and do not recompile on dependency change

3 participants