There is some heavy operation going on in a PreCommitEvent method and I want to show an indeterminate progress dialog. The logic sometimes require the UI thread so a background work dialog is not ideal.
Another option is to override the closeWithCommit() method of the editor screen controller and return OperationResult.fail() from it, then commit and close when the background operation is done:
@UiController("Customer.edit")
@UiDescriptor("customer-edit.xml")
@EditedEntityContainer("customerDc")
public class CustomerEdit extends StandardEditor<Customer> {
@Autowired
private Dialogs dialogs;
@Override
public OperationResult closeWithCommit() {
dialogs.createBackgroundWorkDialog(this, new LongTask())
.withCaption("Please wait...")
.withMessage("Saving data...")
.show();
return OperationResult.fail();
}
private class LongTask extends BackgroundTask<Integer, Void> {
protected LongTask() {
super(100, CustomerEdit.this);
}
@Override
public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
Thread.sleep(3000);
return null;
}
@Override
public void done(Void result) {
CustomerEdit.this.commitChanges()
.then(() -> CustomerEdit.this.close(StandardOutcome.COMMIT));
}
}
}
After a while, I realized that I didn’t actually answered your question. You want to interact with UI in your long task, so if you use a background task, it’s quite difficult - you can do it only in progress() and done() methods.
So we need to interrupt the commit process, show the progress bar and then resume the process somehow in a different client request. I think the latter part can be done with the Timer facet:
Thanks @krivopustov , do you maybe have more documentation for the request lifecycle? I’m using CUBA and Jmix now for quite some time, but I still don’t know when exactly the UI gets refreshed. I guess this information is somewhere in the Vaadin docs or am I missing something in the Jmix docs?
The rule of thumb is:
For any client request, e.g. clicking OK button in an editor, the user will see changes in UI only when all backend Java code is executed (unless you use background tasks).
That’s why you didn’t see your ProgressBar - it was created on the backend, but when the request was completed, the screen which contained the ProgressBar was already closed. If you rendered the component outside the editor screen (e.g. on the main screen), you would see it after your long-running task was completed.