# \[Bug\] v8.1.12 Error on invoking extension function, NoBlockingWorkAllowedException

**URL:** <https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102>\
**Category:** Module Development\
**Tags:** perspective\
**Created:** [January 18, 2022, 12:30pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102 "2022-01-18T12:30:14Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 18, 2022, 12:30pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/1 "2022-01-18T12:30:15Z")

</div>

version 8.1.12

Im getting an error on my component, when i invoke an extension function in the java ComponentModelDelegate.

`com.inductiveautomation.perspective.gateway.threading.BlockingWork$NoBlockingWorkAllowedException: No blocking work allowed on thread: perspective-queue-41`

Though i am quite sure it worked and i have not changed anything around this. Did something in igntion change around this?

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/7/576e5c0a23b19a332e6bde41d0616aa88fbf3d52.png)

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 18, 2022, 2:59pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/2 "2022-01-18T14:59:08Z")

</div>

@paul-griffith (calling you since you seem to have been answering my questions to the java side a lot :D)  
So looking in the previous version of the javadocs i see no mention of BlockingWork before 8.1.12 ☹

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 18, 2022, 3:25pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/3 "2022-01-18T15:25:45Z")

</div>

Yes, we became more strict about Perspective’s threading model.  
You need to submit your extension function invocation to the work queue.  
One way to do it is the new `PerspectivePollingFuture` class; for the alarm status table we create one in the model delegate in the constructor:

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/9/8/985688f8a925296a402b03e2e9b41489fdf7a86f.png)

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 18, 2022, 3:32pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/4 "2022-01-18T15:32:45Z")

</div>

> [@paul-griffith](#):
>
> `PerspectivePollingFuture`

Oke what do i do with the querypoll once i created one in the constructor?

Ahh the fetchAlarmStatusFuture points to somethign about the Blockingoworker...  
andthe this::receaiveAlarmStatus points to a function with invoke...

phew this got quite a bit more complicated xD

Is the defaultrate how often it checks the extension function exists or what do i make of that?  
Cuz normaly i only invoke the extensionfunction on a specific handleEvent. i dont really want to poll to this function, just execute it one time when the clientside send a specific message. which really wont happen often

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 18, 2022, 4:03pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/5 "2022-01-18T16:03:25Z")

</div>

Heh i cant build it doesnt find the packages blocking worker or polling future.  
do i have to update the base packages of ignition in order to build? thats odd i dont think ive ever done that xD

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 18, 2022, 4:11pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/6 "2022-01-18T16:11:39Z")

</div>

Yes, since we added that class in 8.1.12 you’ll have to bump your SDK dependency version(s) to that. You’ll also want to bump the minimum required version of your module to at least that SDK version, so that someone can’t attempt to install your module on an older gateway (which would invariably fail, due to the missing classes).

You might be able to get away with a simpler strategy - post a Runnable (probably a lambda) to the common queue, e.g.:  
`queue.submitOrRun(() -> fireEvent(ResponseEvent.DATA, asJsonObject("fetchUrl", fetchId)));`  
If you invoke your extension function on queue, you shouldn’t get that error message.

Disclaimer: I’m mostly just reading the code and aware of some background here, this is not my area of expertise.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 19, 2022, 8:47am UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/7 "2022-01-19T08:47:41Z")

</div>

Hm i need to use runOrSubmit to get the return value, but even doing so im still getting the blocking error ☹ i notice the error is now on a much lower queue (1 or 2) compared to last time (40+) though that might be unrelated or just because the server hasnt run that long yet xd  
I havent updated the sdk yet tho or included anything about the blocking

 ![image 690x72](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/a/4a51b86dcfb65d8d95899aa661b46b39c4381531.png) ![image 690x72](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/a/4a51b86dcfb65d8d95899aa661b46b39c4381531.png)

Edit: i bumped up the sdk.version in my gradle.build (i think)

 ![image 690x318](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/f/7f17060d7c0d392f2a83fa4ae076742a687109f4.png) It started downloading a bunch of thiings but then i got this error ![image 690x92](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/e/ee8804792abaccbf83dbb50196dcb48766a9b49c.png)  
Do i need to do something else here? the snapshot of gradle? where can i find what path i need?

Edit3:  
So i tried updating sdk again and noticed it continued downloading where it left of…  
it gave an similar error with some other numbers but the same file.  
then i did it again and it downloaded it fully and now it builds xd  
weird xd

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 24, 2022, 10:30am UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/8 "2022-01-24T10:30:21Z")

</div>

Phew finally got it working again!

I created a runnable with a getValue function  
where i set `BlockingWork.setBLockingWarkAllowed(true)`

(im doing it twice idk which one is needed but it works)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/9/d90eeb365d90024bec75e1dcef22a4bbd7f6a30d.png)  
Then initialize the runnable,  
start it in a thread.  
wait for it to finish running (join)  
and get the value from the runnable  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/9/0/90485b1276cfb1877b029176c35e6a91714f1b9b.png)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 24, 2022, 12:59pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/9 "2022-01-24T12:59:19Z")

</div>

`.join()` is a blocking operation, so I think you are just cheating. I don’t know enough about the queuing rules to say if that is safe. I would expect you to put the assignment to `openDefault` in the runnable. Possibly needing synchronization, though.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 24, 2022, 1:02pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/10 "2022-01-24T13:02:35Z")

</div>

> [@pturmel](#):
>
> so I think you are just cheating

yes xD  
I never wanted/needed this to be in a seperate thread,  
but with the new update (8.1.12+) it seems extensionfunction.invoke automatically gets created in a new one, because so far igntion only used it for polling functions, but i do not use it for that purpose.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 23, 2022, 12:08pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/11 "2022-02-23T12:08:18Z")

</div>

Alright it seems this is causing some unexpected problems afterall…  
for some reason i can not access any params or props inside my extension function.  
When i call one it seems to get stuck infinitly, i can see the script running in diagnosics running scripts.  
The server gets completly stuck even after canceling the script, forcing me to restart, yet no logs or errors are shown.

even something as simple as a print, gets stuck on the view param line.  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/b/eb6a8818491cbf3ce232d173e9b4ba2e681df76c.png)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/6/362c5f8584afdb338f221e2ee4590a47509deac2.png)

Ive tested this in the alarm component and there it does work. Seems im blocking the async props call somehow and it keeps waiting for it to respond?  
I doubt this has anything to do with me “joining” the thread tho…  
And probably more with how i create the runnable thread itself with the blockingwork…

@paul-griffith @Kevin.Herron  
any idea how i could do this differently?  
Do i maybe have to use wrapThreadFactory?BlockingTaskQueue? if so how?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 23, 2022, 1:13pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/12 "2022-02-23T13:13:06Z")

</div>

Solving these sorts of problems usually means rethinking the movement of data through your logic, so that the problem item is already “present” when requested. And you deliver it without blocking. If stale, the caller gets the stale value.

Your comment that it probably isn’t the “joining” seems outrageously unlikely to me.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 23, 2022, 1:29pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/13 "2022-02-23T13:29:51Z")

</div>

> [@pturmel](#):
>
> problem item

I mean i could move along this one prop through the data flow... but who knows next weeks its a different prop...  
The fact that is works normally for the alarms status means the self.view.props should be accesable in extension functions somehow.

Maybe it is? i do not have all that much experience with threads in java (or in general).  
i thought it just waits for it finish what its doing, should not also wait for any async (prop) calls inside its thread aswell?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [February 23, 2022, 3:36pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/14 "2022-02-23T15:36:52Z")

</div>

The `PerspectivePollingFuture` mentioned above automatically handles the subscription to the properties.  
The `Supplier<CompletableFuture<V>> fetch` is a computed function that returns a `CompletableFuture` (think `Promise`) containing your result type `V`. Then `BiConsumer<V, Throwable> consumer` will be invoked when your future completes, with either your result type `V` _or some exception_ that was thrown during the fetch.  
That `BiConsumer` will be called on the Perspective executor pool that allows ‘blocking’ work automatically, so you’re allowed to invoke whatever extension functions you want.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 23, 2022, 3:58pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/15 "2022-02-23T15:58:23Z")

</div>

Hm i did not see that function subscribed to the props. I guess ill have to do something similar.

or else i suppose ill have to dig a bit deeper into the CompletableFuture and BiConsumer to make something else that works without having to poll.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 24, 2022, 8:51am UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/16 "2022-02-24T08:51:34Z")

</div>

So ive been digging into the polling future and found an easier way to call the invoke.

I was almost like you said here:

> [@paul-griffith](#):
>
> queue.submitOrRun(()

but instead of running it on the queue, i run it on the executor.  
This by passes all the blocking and threading problems 😃  
`component.getSession().getPerspectiveContext().getExecutorService().submit(()-> ...invoke(...)).get()`

However im still getting frozen on calling session props. I looked at the pollingfuture and it did not seem to provide the props to executor service or something. OR maybe i have missed it, im looking a bit more into it and will update this post if i find something

Edit1:

Alright so insteadof print(self.view.params.key) i did print(self.view.params.get('key'))  
and im getting the print of the prop **after** the event and the event is returning nothing

So it seems like Future.get() is not waiting for the params.get('key') but waiting infinity on the params.key?  
So i guess this also was happening before in the thread i made with the joining...

I really dont understand this...

How would i wait for it to finish?  
or do i just put all my code inside the future? Guess ill try that next

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 24, 2022, 9:56am UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/17 "2022-02-24T09:56:40Z")

</div>

Oke so putting everything inside the future submit works…  
I really dont understand it though, why were the get() and join() not waiting correctly?

```auto
 component.getSession().getPerspectiveContext().getExecutorService().submit(() -> {
            responsePayload.add("data", data);
            responsePayload.addProperty("invoked", extensionfunction.get().invoke(String.class, "Extension Default", data));
            fireEvent("invoking", responsePayload);
          });

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 24, 2022, 1:39pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/18 "2022-02-24T13:39:38Z")

</div>

There are many situations, and this appears to be one, where you **CANNOT WAIT**. The original thread does not permit blocking. Any kind of wait is **BLOCKING**. I’m glad you stumbled on a solution (putting the balance of the code in the executor), but it is frustrating that you can’t accept “Don’t wait/block/sleep” as the answer.

(You could also have put the balance of the code in a `.whenComplete` lambda on `CompletableFuture`.)

Yes, you made me shout. ):

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 24, 2022, 1:59pm UTC](https://forum.inductiveautomation.com/t/bug-v8-1-12-error-on-invoking-extension-function-noblockingworkallowedexception/55102/19 "2022-02-24T13:59:17Z")

</div>

Sorry i was very frustrated too ☹ I would have expected some kind of feedback erros or logs about what was happening, but it just got stuck.

There just had to be a way to know when it was ready to do something after it... And i didnt find anything other then "get()" in the java.util.concurrent.future class, which said it waited...

> [@pturmel](#):
>
> `whenComplete` lambda on `CompletableFuture` .

But seems this is proabably the thing i was looking for...
