How to access table items before shown in screen extending AbstractLookup?

Hello,

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()?

Thank you in advance.

Clemens

Hi Konstantin and Mario,

I appreciate your help. I am bussy with some other things at the moment. But if I find the time I will test it and give a feedback asap.

Hi,
you can do it in the

ready()

method of AbstractWindow. That should do the trick (see docs).
Bye
Mario

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();
    }
}

screen-ready.zip (30.4K)

1 Like

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 :wink:

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.

Thank you very much for your help :slight_smile: It´s working perfectly now

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.

Do you have any idea how to handle this problem?

Thank you in advance.

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);
}

Thank you again for your help :)!