Hi all,
I’m experiencing an intermittent “endless loading” issue in my Vaadin (Flow) view (ScenarioDetailsView
). The main progress bar sometimes never disappears, and the content doesn’t load.
- This happens most often right after server startup.
- A temporary workaround is to navigate back, open a different scenario (which usually loads quickly), and then try the original scenario again – it might then load correctly. The issue can still reappear later.
View Logic Overview:
My ScenarioDetailsView
is a Composite<VerticalLayout>
implementing HasUrlParameter
and BeforeEnterObserver
.
setParameter(id)
: Validates and stores the scenario ID from the URL.beforeEnter()
: CallsloadScenarioData()
.loadScenarioData()
:- Clears previous content and shows a global
ProgressBar
. - Submits a main loading task to an
ExecutorService
(created withExecutors.newVirtualThreadPerTaskExecutor()
). - This task uses
CompletableFuture.supplyAsync()
to fetch the mainScenario
object (with a 15s timeout). - Upon successful fetch, it uses
ui.access()
to:- Hide the global
ProgressBar
. - Build the UI: a header, scenario metadata, and an
Accordion
. - Nested Async for Accordion Panels: For each
AccordionPanel
(e.g., “General Info”, “Patient State”), a new asynchronous task is submitted to the sameexecutorService
. This task fetches panel-specific data and then updates the panel’s content, again usingui.access()
. Each panel initially shows its own loading placeholder.
- Hide the global
- Clears previous content and shows a global
onDetach()
: Shuts down theexecutorService
(shutdownNow()
andawaitTermination()
).- Backup Timeout:
loadScenarioData()
also starts a 20-second backup timer. If the main loading isn’t complete by then, it tries to show an error and navigate away.
Code Snippet (Pattern for Accordion Panel Loading):
This pattern is used for several accordion panels, all triggered after the main scenario data is loaded and the basic UI structure is built within the first ui.access()
call.
// Inside addAccordionToContent, after main scenario object is confirmed to be loaded
private void createAndAddGeneralInfoPanel(Accordion accordion, UI ui) {
AccordionPanel panel = accordion.add("General Info", createLoadingPlaceholder("Loading..."));
// 'scenario' (main object) is available here
loadGeneralSupportDataAsync(ui, panel, scenario, ...); // Starts another async task
}
private void loadGeneralSupportDataAsync(UI ui, AccordionPanel panelToUpdate, Scenario currentScenario, ...) {
executorService.submit(() -> {
try {
// ... Fetch data for this panel (e.g., String details = someService.getDetails(currentScenario.getId())) ...
if (detached.get() || ui.isClosing()) return;
ui.access(() -> {
// ... Update panelToUpdate.setContent(detailsComponent) ...
});
} catch (Exception e_task) {
// ... Log error and update panel with error message via ui.access() ...
}
});
}
Questions:
- What are common causes for this kind of intermittent endless loading, especially on initial server startup, given the nested asynchronous operations and ui.access() calls?
- Could there be race conditions or issues with the ExecutorService (especially with virtual threads) or UI/session readiness that lead to the ui.access() callbacks not firing or an underlying task getting stuck?
- Any suggestions for debugging this effectively? The issue is hard to reproduce consistently.
Thanks for any insights!