No. That is why the recommendation is to avoid using locks in lambdas.
The finally block is also not executed when there is a break or a type exception in a lambda.
finally is pretty much useless in lambdas and therefore using a lock inside a lambda is a really dangerous idea.
I completely agree. Look at the Design Pattern postings. Most of them will provide techniques you can use that should let you avoid the need for lambdas and locks.
Alternatively, you can move to JSR223 Rules and code in Jython, JavaScript, or Groovy. Given that JSR223 Rules and the new Experimental Next-Gen Rules engine both use the same underlying Rules Engine, this would position you fairly well to adopt the NGRE once the Experimental is removed from it’s name.
NOTE: documentation of the NGRE has been started here.
But beware, JSR223 documentation quantity and quality is hit and miss at the moment, but there are efforts starting up to address that as well.
It depends on the specific problem:
Design Pattern |
Use |
Design Pattern: Separation of Behaviors |
Great for centralizing cross cutting code like sending of alerts. Essentially you are creating Rules that trigger other Rules through an Item. |
Design Pattern: Working with Groups in Rules |
Can be used to combine lots of similar Rules into a single Rule. If you only have one Rule to process all the lights, for example, you don’t need lambdas. Pay particular attention to Member of and triggeringItem which addresses your concern with a “big when”. |
Design Pattern: Associated Items |
Great when used in combination with the previous one, provides a way to access Items that are related to each other making it so you can further consolidate many Rules into one. This addresses much of concern about the “big then”. |
Design Pattern: Expire Binding Based Timers |
Reduces the need for Timers in some cases. |
For example, here is my code that sends me an alert when any door is left open for more than an hour.
rule "Keep track of the last time a door was opened or closed"
when
Member of gDoorSensors changed
then
if(previousState == NULL) return;
val name = triggeringItem.name
val state = triggeringItem.state
// Double check if the event makes sense with the deadbolt state
if(name.contains("Front") || name.contains("Back")) {
val lock = ScriptServiceUtil.getItemRegistry.getItem(name.replace("v", "a") + "_Lock").state
if(lock == ON) {
logWarn(logName, name + " appears to be flapping, door changed to " + state + " but deadbolt is locked! Ignoring change.")
return;
}
}
// Update the time stamp
postUpdate(name+"_LastUpdate", now.toString)
// Set the timer if the door is open, cancel if it is closed
if(state == OPEN) sendCommand(name+"_Timer", "ON")
else postUpdate(name+"_Timer", "OFF")
// Set the message
val msg = new StringBuilder
msg.append(transform("MAP", "en.map", name) + " was ")
msg.append(if(state == OPEN) "opened" else "closed")
var alert = false
if(vTimeOfDay.state.toString == "NIGHT" || vTimeOfDay.state.toString == "BED") {
msg.append(" and it is night")
alert = true
}
if(vPresent.state == OFF) {
msg.append(" and no one is home")
alert = true
}
msg.append("!")
// Alert if necessary
if(alert){
aAlert.sendCommand(msg.toString)
}
// Log the message if we didn't alert
else {
logInfo(logName, msg.toString)
}
end
rule "Timer expired for a door"
when
Member of gDoorsTimers received command OFF
then
val doorName = transform("MAP", "en.map", triggeringItem.name)
aAlert.sendCommand(doorName + " has been open for over an hour")
if(vTimeOfDay.state.toString == "NIGHT" || vTimeOfDay.state.toString == "BED") {
triggeringItem.sendCommand(ON) // reschedule the timer
}
end
This example uses pretty much all of the mentioned DPs to create Rules that handle any number of door sensors without locks, lambdas, or duplicated code. I’ve only a little bit of code that handles the special case where the door sensor represents one of the doors that has a deadbolt attached to it.
Notice the bulk of the code is building the message to send as an Alert.
Notice how there is nothing that actually directly references specific door sensor Items. I could have 1 door or a dozen doors/windows and use this same single Rule.
NOTE: lock
above is Item representing the door deadbolt, not a ReentrantLock.