This is a short post in which I describe what is the behavior of background threads in MAF in regards to the context of the features.
Background threads – best practices
The best practice when doing intensive work in a mobile application is to start a new background thread, do the work there and show the results to the user in the primary thread. This is mainly because the user does not have to see the User Interface freezing until the work is done, as it may be an operation which takes seconds or minutes.
Because MAF uses Java for back-end logic, you can start a background thread just like you would in Java. However, it is advisable to use a thread pool with a limited number of threads (ideally 1) and queue the execution of the threads in that pool. This is to avoid burdening the system with spawning too much threads.
For this task, you can use ThreadPoolExecutor which has a built-in Queuing mechanism.
You instantiate it like this:
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILISECONDS, new LinkedBlockingQueue<Runnable>());
Reading from the Java docs, the parameters are:
corePoolSize – the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set
maximumPoolSize – the maximum number of threads to allow in the pool
keepAliveTime – when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
unit – the time unit for the keepAliveTime argument
workQueue – the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
Basically, you are creating a pool of threads with a capacity of 1. All other threads which are submitted for execution, are queued. You access the queue with getQueue() method of the executor.
Features’ context in a background thread
When creating a new background thread, you will lose the context of the feature from where the thread was started. The thread’s feature context will be reset to the first feature in the list of feature references (as it is displayed in maf-application.xml). Example: If you start a new background thread – say, from a backing bean method – from a feature called Departments, in the background thread, if you invoke AdfmfJavaUtilities.getFeatureId() you will not get “Departments” string back. You will get the ID of the first feature references in maf-application.xml.
Additionally, if you perform navigate inside the background thread with AdfmfContainerUtilities.gotoFeature(String featureId) this happens only in the background thread, not in the frontend application (So what the user sees is not affected). That means, in the above scenario, the User Interface will not navigate away from the Departments feature.
Interestingly, if you are in the same feature in the primary thread and also in the background thread (by navigating as shown above), there are separate instances of Bindings, so you cannot modify the bindings from the background thread and see the effects in the primary thread.
Useful tip: You can check with AdfmfJavaUtilities.isPrimaryRequestThread() if the current thread is the one which is running to UI also, or is a background thread.