# \[No longer relevant on OH 3.0+\] Design Pattern: Rule Latching

**URL:** <https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748>\
**Category:** Tutorials & Examples\
**Tags:** designpattern\
**Created:** [August 4, 2017, 5:22pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748 "2017-08-04T17:22:18Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [August 4, 2017, 5:22pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/1 "2017-08-04T17:22:18Z")

</div>

Edit: Updates for OH 4.

Please see [Design Pattern: What is a Design Pattern and How Do I Use Them](https://community.openhab.org/t/design-pattern-what-is-a-design-pattern-and-how-do-i-use-them/40319) for details on how to work with DPs.

# Problem Statement

Sometimes one wants to make sure that only one instance of a Rule is running at a given time. For example, when a rule is triggered by a Group Item’s receiving updates, the Rule gets triggered more than once per event. Another use is if one needs to implement debouncing where events that take place within a certain time are ignored.

## No more than one instance of the rule running at a time

As of OH 3.0, the rule engine for _all_ rules languages no longer allow this to happen. Each rule gets it’s own thread and if a rule that is actively running gets triggered again, the subsequent triggers will be queued up and worked off in order instead of there being two or more instances of the same rule running at the same time.

Therefore rule latching for this use case is no longer required.

## Debounce

To handle this use case use [Design Pattern: Rate Limit](https://community.openhab.org/t/design-pattern-rate-limit/17831).

If you are on OH 2.5 or before, see the edit history for the old version of this post.

---

<div class="post-metadata">

**Author:** ![lipp\_markus](https://community.openhab.org/user_avatar/community.openhab.org/lipp_markus/32/56218_2.png) [@lipp\_markus](https://community.openhab.org/u/lipp_markus)\
**Post date:** [August 4, 2017, 7:07pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/2 "2017-08-04T19:07:03Z")

</div>

I had trouble in the past that the system did not try long enough to get a lock and the rule sometimes did not run. I modified this reentrant locks to try a little longer to get a lock and it seem to have helped. Now I may have been misunderstanding things, but could it be helpful to give more time to try to get a lock? Of course, there are other edge conditions to be considered for every application. But in case it helps anyone, here the code that worked for me

```auto
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock

rule "My rule"
when
        System started or
        Item Date received update
then
var gotLock = lock.tryLock(2000, TimeUnit.MILLISECONDS)		
	try {
		if (gotLock) {
 // do stuff ( i cut out my rule here for brevity)	    
}		   
 		}
		else logInfo("My rule", "re-entry lock actived")
	}
	finally {
		if(gotLock){
			lock.unlock()
		}
	} 
end

```

Obviously the part I wanted to point out is this ` lock.tryLock(2000, TimeUnit.MILLISECONDS)` (and the additionally imported library). I used this when I was on a raspberry and it seemed to make it more reliable;

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [August 4, 2017, 7:24pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/3 "2017-08-04T19:24:19Z")

</div>

This is actually something that is discussed in the [ReentrantLock’s JavaDocs](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html#tryLock()).

Part of the problem, as with everything involved with concurrency, is timing or requests and such. The tryLock method that doesn’t take the timeout says

> Even when this lock has been set to use a fair ordering policy, a call to tryLock() will immediately acquire the lock if it is available, whether or not other threads are currently waiting for the lock. This “barging” behavior can be useful in certain circumstances, even though it breaks fairness. If you want to honor the fairness setting for this lock, then use tryLock(0, TimeUnit.SECONDS) which is almost equivalent (it also detects interruption).

The section discussing tryLock with the timeout says:

> If this lock has been set to use a fair ordering policy then an available lock will not be acquired if any other threads are waiting for the lock.

So, given that, tryLock() causes the thread to jump to the front of the line which could theoretically starve out previous threads waiting to acquire the lock. By adding the timeout what you are doing is forcing the threads to behave nicely and go for the lock in order. I suspect this explains why adding it worked for you. I bet if you changed the 2000 to 0 it would still work as expected.

Thanks for posting! I’m going to change the OP to use the timeout version instead like your example.

---

<div class="post-metadata">

**Author:** ![jvanzuijlen](https://community.openhab.org/user_avatar/community.openhab.org/jvanzuijlen/32/70715_2.png) [@jvanzuijlen](https://community.openhab.org/u/jvanzuijlen)\
**Post date:** [May 14, 2018, 7:20am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/4 "2018-05-14T07:20:00Z")

</div>

> [@rlkoshak](#):
>
> ```
> if(latch.tryLock(0, TimeUnit.SECONDS){
> 
> ```

Misses a closing brace 🙂

```
if (latch.tryLock(0, TimeUnit.SECONDS)) {

```

---

<div class="post-metadata">

**Author:** ![mhilbush](https://community.openhab.org/user_avatar/community.openhab.org/mhilbush/32/56108_2.png) [@mhilbush](https://community.openhab.org/u/mhilbush)\
**Post date:** [July 30, 2018, 5:02pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/5 "2018-07-30T17:02:54Z")

</div>

@rlkoshak Would you consider editing the example in the first post to:

```auto
import java.util.concurrent.locks.ReentrantLock

```

Copying the example as is gives an error.

Also, there’s a typo here

```auto
        logErrror("latch", "Error occured in Latched Rule! " + e.toString)

```

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [July 30, 2018, 5:04pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/6 "2018-07-30T17:04:01Z")

</div>

> [@mhilbush](#):
>
> import java.util.concurrent.locks.ReentrantLock

This whole DP is slated to be rewritten, but I’ve added the import for now.

---

<div class="post-metadata">

**Author:** ![mhilbush](https://community.openhab.org/user_avatar/community.openhab.org/mhilbush/32/56108_2.png) [@mhilbush](https://community.openhab.org/u/mhilbush)\
**Post date:** [July 30, 2018, 5:06pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/7 "2018-07-30T17:06:05Z")

</div>

Thanks. I missed one.

```auto
import java.util.concurrent.TimeUnit

```

---

<div class="post-metadata">

**Author:** ![MikeTheTux](https://community.openhab.org/letter_avatar_proxy/v4/letter/m/c68b51/32.png) [@MikeTheTux](https://community.openhab.org/u/MikeTheTux)\
**Post date:** [March 2, 2019, 5:43pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/8 "2019-03-02T17:43:49Z")

</div>

Alternative:

```auto
if ( !lock.isLocked )
{
    lock.lock()
    try {
        //TODO
        
        Thread::sleep(OneMinute*5)
    } finally {
        lock.unlock()
    }
}

```

Although I prefeer the timre variant …

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [March 2, 2019, 6:59pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/9 "2019-03-02T18:59:50Z")

</div>

You have to be very very careful using locks like this, and it’s one reason why I didn’t show that version above on purpose.

1. If there is a type error inside the try block the finally block never runs and the lock will never be unlocked. After this rule gets triggered 5 more times all your rules will stop.

2. If this rule triggers five times in five minutes for some reason, almost your other rules elm so until the first rule exits. And if your rule continues to trigger it will confine to starve all the rest of your rules.

It’s a really bad idea to block rules using a lock like this. Instead, use the Gate Keeper’s Queue example which will let you put the event on a queue that gradually gets worked off without consuming a rule runtime thread for each event awaiting processing.

---

<div class="post-metadata">

**Author:** ![MikeTheTux](https://community.openhab.org/letter_avatar_proxy/v4/letter/m/c68b51/32.png) [@MikeTheTux](https://community.openhab.org/u/MikeTheTux)\
**Post date:** [March 3, 2019, 6:27pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/10 "2019-03-03T18:27:30Z")

</div>

OK. Got it. Between the isLocked() and lock() another lock can happen. In this case the second thread needs to wait the 5 minutes 🤨

> [@rlkoshak](#):
>
> If there is a type error inside the try block the finally block never runs and the lock will never be unlocked. After this rule gets triggered 5 more times all your rules will stop.

Why is in the case of an type error the finally block with the unlock not called?

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [March 3, 2019, 7:04pm UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/11 "2019-03-03T19:04:48Z")

</div>

> [@MikeTheTux](#):
>
> Why is in the case of an type error the finally block with the unlock not called?

All I can say is that’s how the underlying Xbase/Xtend language libraries work. I can’t tell you why.

I studier it’s because the language is weakly typed running on a strongly typed language base (Java) when it cannot convert an object’s type to something usable it can’t proceed and execution must ends instead of the exception being thrown.

---

<div class="post-metadata">

**Author:** ![maihacke](https://community.openhab.org/user_avatar/community.openhab.org/maihacke/32/20847_2.png) [@maihacke](https://community.openhab.org/u/maihacke)\
**Post date:** [April 27, 2021, 6:25am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/12 "2021-04-27T06:25:39Z")

</div>

I have several rules modifing timers from different rules (see example below). To prevent race conditions I used a lock pattern. Sometimes I have the problem that the rules fail because `lock is NULL`. I think there is a problem with the initialization of the global var. On top of that I read here in the forum that it is no longer recommend to use reentrant locks. Is there a better pattern/solution available? Is there a difference in OH2 vs OH3.

```auto
import java.util.concurrent.locks.ReentrantLock

var ReentrantLock lock = new ReentrantLock()
var Timer timer1

rule "Rule 1"
when
    Item Item_1 changed from OFF to ON
then
    lock.lock()
  try {   
        if (timer1 !== null) {
            timer1.cancel()
        }
        timer1 = createTimer(now.plusSeconds(30), [|
            ...
        ])
    } finally {
        lock.unlock()
    }
end

rule "Rule 2"
when
   Item Item_1 changed from ON to OFF
then
    lock.lock()
    try {
        if (timer1 !== null) {
            timer1.cancel()
        }  

    } finally {
        lock.unlock()
    }
end

```

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [April 27, 2021, 8:09am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/13 "2021-04-27T08:09:10Z")

</div>

> [@maihacke](#):
>
> rules fail because `lock is NULL`.

You might look at your real error message again. If it really mentions NULL it is to do with an Item state.

---

<div class="post-metadata">

**Author:** ![maihacke](https://community.openhab.org/user_avatar/community.openhab.org/maihacke/32/20847_2.png) [@maihacke](https://community.openhab.org/u/maihacke)\
**Post date:** [April 27, 2021, 8:36am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/14 "2021-04-27T08:36:27Z")

</div>

The error message is

`Rule '...': cannot invoke method public void java.util.concurrent.locls.ReentrantLock.lock() on null`

This happens both for `Rule_1` and `Rule_2`.

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [April 27, 2021, 9:00am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/15 "2021-04-27T09:00:08Z")

</div>

Are you actually using OH3? It’s not clear.

Certainly edge-case timing will have changed in OH3, because you are operating in a different rule engine.

You don’t need any kind of lock for a single UI entered DSL rule - only one “copy” of a rule may execute at a time, further triggers queuing.  
I’m not certain that also applies to file created DSL rules - but I expect it does.  
So that’s one application for reentrant lock that is no longer needed.

That doesn’t help you much where you are trying to share a lock across multiple rules, though.

> [@maihacke](#):
>
> Is there a better pattern/solution available?

Further up this thread is a description of using tryLock with a timeout for better reliability.

There are usually lots of more or less complicated ways to avoid using locks. In the example you’ve given us, you’d simply combine those two rules into one.  
Or post 1 gives a timer based approach.  
We should probably know a bit more about what you are really doing and what problems it gives you to offer sensible suggestions.

However …

> [@maihacke](#):
>
> `Rule '...': cannot invoke method public void java.util.concurrent.locls.ReentrantLock.lock() on null`

That would be a bad import, with a typo. **locls**?

---

<div class="post-metadata">

**Author:** ![maihacke](https://community.openhab.org/user_avatar/community.openhab.org/maihacke/32/20847_2.png) [@maihacke](https://community.openhab.org/u/maihacke)\
**Post date:** [April 27, 2021, 9:02am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/16 "2021-04-27T09:02:48Z")

</div>

Yes typo, had only a screenshot. The error comes from a system not “under my control”, which is running OH2.

---

<div class="post-metadata">

**Author:** ![maihacke](https://community.openhab.org/user_avatar/community.openhab.org/maihacke/32/20847_2.png) [@maihacke](https://community.openhab.org/u/maihacke)\
**Post date:** [April 27, 2021, 9:05am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/17 "2021-04-27T09:05:26Z")

</div>

> [@rossko57](#):
>
> Further up this thread is a description of using tryLock with a timeout for better reliability.

I do not see how this could help, if the root problem is that there is no lock instance at all (for a reason I don’t understand).

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [April 27, 2021, 9:08am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/18 "2021-04-27T09:08:02Z")

</div>

> [@maihacke](#):
>
> I do not see how this could help, if the root problem is that there is no lock instance at all

You asked for alternatives, you get alternatives.  
But yes, you are looking at the correct problem. The import fails I reckon still.

---

<div class="post-metadata">

**Author:** ![maihacke](https://community.openhab.org/user_avatar/community.openhab.org/maihacke/32/20847_2.png) [@maihacke](https://community.openhab.org/u/maihacke)\
**Post date:** [April 27, 2021, 9:54am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/19 "2021-04-27T09:54:35Z")

</div>

I meant calling other methods on `lock` would also fail if the instance is null. What do you mean with “import fails I reckon still”. This is the original code:

```auto
import java.util.concurrent.locks.ReentrantLock

var ReentrantLock lock = new ReentrantLock()

var Timer einbruchTimer
var Timer alarmAktivierenTimer
...

```

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [April 27, 2021, 11:47am UTC](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748/21 "2021-04-27T11:47:56Z")

</div>

> [@maihacke](#):
>
> fail if the instance is null

There’s a limited number of ways for that to happen. You’re going to have to investigate _when_ it happens to track it down further. We’re not told the circumstances; maybe you could test and log alerts if null at each rule run. That would change rule timings by itself of course, but that doesn’t matter in the example shown.

[Next page](https://community.openhab.org/t/no-longer-relevant-on-oh-3-0-design-pattern-rule-latching/32748.md?page=2)
