Pushover + lambda = failed: null in

I have a few lambda functions that arn’t working post upgrade to OH3. I disected my function down to something very basic to narrow down the problem i found the cause:

Whenever I call the pushover action to send a notification within the lambda it fails with the error message:

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘lamba_test-1’ failed: null in lamba_test

Here’s my example code (ignore the naming - its my function used for autolocking doors):

Rule:

import org.eclipse.xtext.xbase.lib.Functions
import java.util.Map
val pushover = getActions("pushover", "pushover:pushover-account:locks")

val Map<String, Timer> timers = newHashMap
val Functions$Function6<GenericItem, GenericItem, GenericItem, Integer, Map<String, Timer>, String, Boolean> LambdaTest = [
    lockItem,
    lockItemStatus,
	sensorItem,
	time,
	timers,
	lockDesc	|
	logInfo("LambdaTest", "lockItem: " + lockItem +"lockItemStatus: "+ lockItemStatus + "sensorItem: " + sensorItem + "time: " + time + "timers: " + timers + " lockDesc: "+ lockDesc )
    var String TimerKey = lockItem.name
    if (timers.containsKey(TimerKey)) {
        logInfo("LambdaTest", "Key Contained")
    } else {
        //pushover.sendMessage("LOCKED (Auto)","Title of Message")

    }
    
    true
]

Rule that calls the function:

rule "Auto Lock Timer: House Lock"
when
	//Item vHouseLock changed from LOCKED to UNLOCKED or
	//Item vHouseLock changed from UNLOCKED to LOCKED or
	Item vTest changed
then
logInfo("LambdaTest", "### Auto Lock Timer: House Lock ###")
{

		LambdaTest.apply(vHouseLock_Proxy, vHouseLock_Status, vHouseDoor, 30, timers, "House Lock")
}							 
end

Running the above rule works no problem.
If i were to uncomment out the line that says:

//pushover.sendMessage(“LOCKED (Auto)”,“Title of Message”)

I then get the following error message:

2021-03-06 21:57:05.255 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘lamba_test-1’ failed: null in lamba_test

The lambda function cannot “see” that ‘global’ variable pushover.
The function lambda_test is itself a ‘global’, but peer globals cannot see each other.

You either have to pass it in to the function, just the same as you have to pass in the global timers map, or you can do a getActions within the function.

This hasn’t changed from OH2.

1 Like

Thank you - I added my getActions within the function and fixed it !

If you have more than a couple of lambdas like this I highly recommend considering a look at one of the other Rules languages. Lambdas in Rules DSL have a number of very significant problems including but not limited to:

  • not thread safe, if it’s called twice and has two instances running at the same time, the second run will stomp over the variables in use by the first call
  • errors inside the lambdas tend to become suppresses (as seen here)
  • the syntax is a little ugly though it can be better than shown here
val LambdaTest = [ GenericItem lockItem,
                   GenericItem lockItemStatus,
...
                 |
	logInfo("LambdaTest", "lockItem: " + lockItem +"lockItemStatus: "+ lockItemStatus + "sensorItem: " + sensorItem + "time: " + time + "timers: " + timers + " lockDesc: "+ lockDesc )
    var String TimerKey = lockItem.name
    ...
]

You don’t need to specify the type of the lambda. And you can get rid of the last true line and it will create a Procedure instead of a Function. You don’t care about the result so that’s desired.

  • A lambda can accept no more than seven arguments.

Python, JavaSCript, and Groovy support fully fledged functions and libraries which do not have any of these problems or limitations.

1 Like

Thank you for the insight @rlkoshak !

I will look into moving my Lambda’s to a different language in the near future once I have everything 100% in OH3, then do code cleanup :slight_smile: