I have a table of linux hosts. Before they are shown on the Browse Screen, I would love to ping them and show the result in the table. Is there a possbility to access the table items before the browse screen displays them? Or shall i use sth like a background task and refresh the table somehow in done()?
Hi Clemens,
First of all, create a transient attribute in your Host entity, so you can display it in the table.
The question is when to fill it with the host status. The simplest way would be to do it in a BeforeDetachEntityListener, but as it involves a network operation, it could unpredictably slow down the loading of the entity. So it’s better to do it asynchronously, as you mentioned, in a background task. Try to start the task in screen’s ready() and update corresponding attributes of all instances in task’s done(). No need to refresh the table - it should show the values as soon as you update them.
Let us know if it doesn’t work for you.
Hi Konstatin,
I had a bit time now. So I tried your idea. But I think I am not doing it right until now.
In the ready() method I get all my hosts DataManager and a LoadText:
private List<Host> loadHosts() {
LoadContext<Host> loadContext = LoadContext.create(Host.class)
.setQuery(LoadContext.createQuery("select e from test$Host e"))
.setView("hosts");
return dataManager.loadList(loadContext);
}
Then I am able to ping all the servers and set the boolean right. I get it that I have to “update” the table in the done() method, but I have no idea at the moment how.
See the attached project. If you run it and open Hosts screen, you will see that the Ping column is updated with a delay. The implementation uses a background task started in the done() method:
public class HostBrowse extends AbstractLookup {
@Inject
private GroupDatasource<Host, UUID> hostsDs;
@Inject
private BackgroundWorker backgroundWorker;
private Map<Host, Boolean> results = new HashMap<>();
@Override
public void ready() {
for (Host host : hostsDs.getItems()) {
results.put(host, false);
}
BackgroundTask<Integer, Void> task = new BackgroundTask<Integer, Void>(10, this) {
@Override
public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
// This is a background thread, you cannot work with datasources and UI components here
for (Map.Entry<Host, Boolean> entry : results.entrySet()) {
Thread.sleep(1000);
// Moreover, you cannot update entities containing in datasources, because they are connected
// to UI components. So just save values in the map.
entry.setValue(true);
}
return null;
}
@Override
public void canceled() {
}
@Override
public void done(Void result) {
// This is the request thread. You can update entities here and the new values will be shown
// in UI components
for (Map.Entry<Host, Boolean> entry : results.entrySet()) {
Host host = entry.getKey();
host.setPing(entry.getValue());
}
}
@Override
public void progress(List<Integer> changes) {
}
};
// Get task handler object and run the task
BackgroundTaskHandler taskHandler = backgroundWorker.handle(task);
taskHandler.execute();
}
}
Thank you very much for your work and the fast answer! It works great now. I just have one question. When I close the screen I get the question if I want do discard unsaved changes.
Where does this come from?
I already tried to commit the Host after I set the bool, but this doesnt work.
And makes no sense when i think about it, as the bool is a transient attribute
You modify entities contained in a datasource, so the datasource gets “modified” too and wants to be committed. Deselect the “Allow commit” checkbox for the datasource in Studio or set allowCommit=“false” in XML descriptor.
I just recognized that I have a problem when I dont allow the screen to commit data.
The screen where the hosts are listed is a lookup screen and I have to be able to delete entries.
Oops. You are right, deletion won’t work if the datasource is not committed.
Then remove the allowCommit=“false” flag and reset the modification status programmatically:
@Override
public void done(Void result) {
// This is the request thread. You can update entities here and the new values will be shown
// in UI components
for (Map.Entry<Host, Boolean> entry : results.entrySet()) {
Host host = entry.getKey();
host.setPing(entry.getValue());
}
// Make the datasource not modified again
((DatasourceImplementation) hostsDs).setModified(false);
}