It was never really recommended. The root problem is that errors can occur inside the try that cause exceptions that never filter back up unto the rule. As a result, the lock will never get unlocked, even if it’s in a finally clause. Furthermore, locks cause a rule to consume a runtime thread doing nothing but waiting for access to the lock. This runs the risk of running out of your runtime threads making it so no rules can run because all your threads are in use waiting for a lock, a lock that might not ever be released if there was an error.
That’s for OH 2. In OH 3 the problem is still there but a little less drastic. You can starve out individual rules instead of all your rules because each rule gets its own thread. Also, there is no need to use a lock in a single rule because in OH 3 only one instance of a given rule can run at a time anyway.
I realize your example is contrived, but I see two concerns with the presented approach:
-
The rule runs really fast so it is unlikely to ever happen that Item_1 changed again while the rule is still running processing the previous change. In short the lock here is adding danger and complexity to the system solving a problem that doesn’t exist. Before adding the lock did you ever actually see Rule 2 run while Rule 1 was still running?
-
Why split this into two rules in the first place? If the need for the lock is caused by the fact that it’s in two separate rules, it’s a far better approach to merge the rules and eliminate the lock than it is to add a lock. This is especially the case in OH 3 where you’ll get the locking for free for the one rule.
And this is also an example where contrived examples like this don’t really help us. As far as is written in this example, there is no reason at all for the lock in the first place. But presumably you have a set of rules where the lock was necessary for some reason. But because we don’t see that, we can’t offer other solutions which might work much better.
This is true for all rules in OH 3, regardless of how the rule is defined and what language the rule is defined in. It’s not just UI entered rules and not just Rules DSL. It’s a universal behavior.
Anyway, as rossko57 is stating, it’s really hard to offer much here in terms of debugging without more information. In the contrived example shown, there is no need for the lock at all so sidestep this problem and stop using the lock. Even with the rules separated as they are, as written there would be no need to use a lock.
One final note. Unfortunately that specific error is kind of a catchall error that Rules DSL throws when it can’t figure out how to coerce the arguments to compatible types. So it’s entirely possible that the problem is not that the lock is null
at all. It might be something else weird going on. Try adding some logging. Log out what lock
is. If it’s null it will log as null
. If it’s a valid lock it will log out something else. The main thing we want to prove is whether or not lock is indeed null
or something else is going on.
And for the record, a merged rule that doesn’t need the lock would be something like:
var Timer timer1
rule "The Rule"
when
Item Item_1 changed
then
timer1?.cancel()
if(newState == ON) {
timer1 = createTimer(now.plusSeconds(30), [ |
...
])
}
end