Skip to content

Commit 2689f5f

Browse files
authored
AbstractScriptModuleHandler: Recompile scripts on dependency change (#4922)
* AbstractScriptModuleHandler: Recompile scripts on dependency change When a script's dependency changes, it should recompile the compiled script similarly to resetting the engine for uncompiled scripts. Fixing this behaviour fixes an issue where compiled scripts stopped working after a dependency changed. This also simplifies the code a bit. Signed-off-by: Florian Hotze <dev@florianhotze.com>
1 parent 13ffa1c commit 2689f5f

4 files changed

Lines changed: 36 additions & 13 deletions

File tree

bundles/org.openhab.core.automation.module.script/src/main/java/org/openhab/core/automation/module/script/internal/factory/ScriptModuleHandlerFactory.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import java.util.Map;
1818
import java.util.concurrent.ConcurrentHashMap;
1919

20+
import javax.script.ScriptException;
21+
2022
import org.eclipse.jdt.annotation.NonNullByDefault;
2123
import org.eclipse.jdt.annotation.Nullable;
2224
import org.openhab.core.automation.Action;
@@ -100,6 +102,11 @@ public void onDependencyChange(String engineIdentifier) {
100102
if (handler != null) {
101103
logger.debug("Resetting script engine for script {}", engineIdentifier);
102104
handler.resetScriptEngine();
105+
try {
106+
handler.compile();
107+
} catch (ScriptException e) {
108+
logger.error("Failed to recompile script for rule {}: {}", handler.getRuleUID(), e.getMessage());
109+
}
103110
}
104111
}
105112
}

bundles/org.openhab.core.automation.module.script/src/main/java/org/openhab/core/automation/module/script/internal/handler/AbstractScriptModuleHandler.java

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,10 @@ private static String getValidConfigParameter(String parameter, Configuration co
9393
* {@link Compilable}.
9494
*/
9595
protected void compileScript() throws ScriptException {
96-
if (compiledScript.isPresent()) {
97-
return;
98-
}
99-
if (!scriptEngineManager.isSupported(this.type)) {
100-
logger.debug(
101-
"ScriptEngine for language '{}' could not be found, skipping compilation of script for identifier: {}",
102-
type, engineIdentifier);
96+
if (compiledScript.isPresent() || script.isEmpty()) {
10397
return;
10498
}
99+
105100
Optional<ScriptEngine> engine = getScriptEngine();
106101
if (engine.isPresent()) {
107102
ScriptEngine scriptEngine = engine.get();
@@ -119,11 +114,20 @@ public void dispose() {
119114

120115
/**
121116
* Reset the script engine to force a script reload
122-
*
123117
*/
124118
public synchronized void resetScriptEngine() {
125119
scriptEngineManager.removeEngine(engineIdentifier);
126120
scriptEngine = Optional.empty();
121+
compiledScript = Optional.empty();
122+
}
123+
124+
/**
125+
* Gets the unique identifier of the rule this module handler is used for.
126+
*
127+
* @return the UID of the rule
128+
*/
129+
public String getRuleUID() {
130+
return ruleUID;
127131
}
128132

129133
/**
@@ -135,10 +139,20 @@ public String getEngineIdentifier() {
135139
return engineIdentifier;
136140
}
137141

142+
/**
143+
* Get the script engine instance used by this module handler.
144+
*
145+
* @return the script engine instance if available, otherwise Optional.empty()
146+
*/
138147
protected Optional<ScriptEngine> getScriptEngine() {
139148
return scriptEngine.isPresent() ? scriptEngine : createScriptEngine();
140149
}
141150

151+
/**
152+
* Creates a new script engine for the type defined in the module configuration.
153+
*
154+
* @return the script engine if available, otherwise Optional.empty()
155+
*/
142156
private Optional<ScriptEngine> createScriptEngine() {
143157
ScriptEngineContainer container = scriptEngineManager.createScriptEngine(type, engineIdentifier);
144158

@@ -203,13 +217,15 @@ protected void resetExecutionContext(ScriptEngine engine, Map<String, ?> context
203217
}
204218

205219
/**
206-
* Evaluates the passed script with the ScriptEngine.
220+
* Evaluates the script with the given script engine.
207221
*
208222
* @param engine the script engine that is used
209-
* @param script the script to evaluate
210223
* @return the value returned from the execution of the script
211224
*/
212-
protected @Nullable Object eval(ScriptEngine engine, String script) {
225+
protected @Nullable Object eval(ScriptEngine engine) {
226+
if (script.isEmpty()) {
227+
return null;
228+
}
213229
try {
214230
if (compiledScript.isPresent()) {
215231
logger.debug("Executing pre-compiled script of rule with UID '{}'", ruleUID);

bundles/org.openhab.core.automation.module.script/src/main/java/org/openhab/core/automation/module/script/internal/handler/ScriptActionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public void compile() throws ScriptException {
9191
}
9292
try {
9393
setExecutionContext(scriptEngine, context);
94-
Object result = eval(scriptEngine, script);
94+
Object result = eval(scriptEngine);
9595
resultMap.put("result", result);
9696
resetExecutionContext(scriptEngine, context);
9797
} finally { // Make sure that Lock is unlocked regardless of an exception being thrown or not to avoid

bundles/org.openhab.core.automation.module.script/src/main/java/org/openhab/core/automation/module/script/internal/handler/ScriptConditionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public boolean isSatisfied(final Map<String, Object> context) {
7575
}
7676
try {
7777
setExecutionContext(scriptEngine, context);
78-
Object returnVal = eval(scriptEngine, script);
78+
Object returnVal = eval(scriptEngine);
7979
if (returnVal instanceof Boolean boolean1) {
8080
result = boolean1;
8181
} else {

0 commit comments

Comments
 (0)