Clarification on BackgroundTask done() Thread Handling (Jmix 2.4.3 with OAuth2)

Hi,

I’m a bit confused about how thread handling works for background tasks in Jmix (version 2.4.3).

I have a background task that can take a couple of seconds to complete. In its done() method, I navigate to a different view. My expectation (based on the documentation) is that done() should always be called on the UI thread. However, I’ve noticed that sometimes done() appears to be invoked on a background thread instead.

From my observations:

  • If the task finishes almost immediately, done() seems to run on the UI thread.
  • If the task takes a few seconds, done() seems to be executed on a background thread.

When done() runs on a background thread, RequestContextHolder.getRequestAttributes() returns null, and attempting to navigate causes Spring’s DefaultOAuth2AuthorizedClientManager to throw an error.

My questions are:

  • What determines which thread done() is invoked on?
  • Is there a recommended way to ensure that navigation and security context-dependent operations happen safely after a background task finishes? ( Right now I’m thinking of simply using Spring’s AuthorizedClientServiceOAuth2AuthorizedClientManager when getRequestAttributes are null. )

Thanks in advance for any clarification!

Hello!

The done() method is called from background task thread. However, the call to done() is wrapped inside UI.access() in order to to access the UI state, components and so on. That is why we can update user interface in this method (and name it UI thread). Since this is still background thread, we set actual authentication and store session attributes in ThreadLocalSessionData.

However, if you invoke getResult(), the background task becomes synchronous and done() method will be called from the UI thread where the task started.

I created an issue to update docs: Clarify from which thread the BackgroundTask done method called · Issue #1000 · jmix-framework/jmix-docs · GitHub

From my observations:

  • If the task finishes almost immediately, done() seems to run on the UI thread.
  • If the task takes a few seconds, done() seems to be executed on a background thread.

Could you share an example that reproduces the problem?

Hello!

Thanks a lot for the clarification. The weird thing is that it does seem to me, that done is not always on the background thread. I uploaded a simple project that reproduces the problem.
backgroundtask.zip (1.2 MB)
The project has two buttons, one starts a job that runs very fast, the other starts a slow task where I use Thread.sleep to simulate the slowness. Then I print out the thread name and the request attributes inside done() :

System.out.println("thread: " + Thread.currentThread().getName());
System.out.println("RequestContextHolder: " + RequestContextHolder.getRequestAttributes());

The fast task says its on http-nio-8080-exec-3 thread, which to me seems like the ui thread, and the slow task says BackgroundTask-1-admin.