Can't access ClickListener from another thread

Hi
I got a slow process, loading data from a db to some tables. During this, I add a indicator window with a cancel button. I managed to set up the loading mechano in an own thread and do the window detach handling right, using the UI.acces method. But now the press the cancel button, and nothing happens. Somehow all interaction with the whole indicator window is ignored. Here is the code:

The search button to start the query:

  private class SearchButtonListener implements ClickListener {

    @Override
    public void buttonClick(ClickEvent event) {
      getUI().setPollInterval(200);
      getUI().addWindow(blockerWindow); //see below
      workThread = new WorkThread(); //see below
      workThread.start();
    }
  }

The thread doing all the work:

  private class WorkThread extends Thread {

    @Override
    public void run() {
      getUI().access(new Runnable() {

        @Override
        public void run() {
          boolean noResult = loadResult(searchField.getValue()); // do the query
          getUI().setPollInterval(-1);
          getUI().removeWindow(blockerWindow);
        }
      });
    }
  }

And the indicator window with the clickListener:[code]
private class BlockerWindow extends Window {

public BlockerWindow() {
  this.setCaption("Query is running");


mainLayout.addComponent(new Label(“Please wait while the Query is running.”));
Button cancelButton = new Button(“Cancel”);
mainLayout.addComponent(cancelButton);

   cancelButton.addClickListener(new ClickListener() {
    
    @Override
    public void buttonClick(ClickEvent event) {
      cancelQuery(); // using PreparedStatment.cancel()
    }
  });
  this.setContent(mainLayout);
}

}
[/code]Does anyone have an idea, why I don’t reach the cancelButton.buttonClick() during the thread is running? Is there a way to reach it, in order to cancel running requests?

Cheers,
Stefan

Hi, your code is almost correct. The problem is, in WorkThread.run, you’re doing the long DB query inside the access() block and thus holding the session lock during the whole time, so arriving requests just block waiting on the lock. You might need multiple access blocks to do all the UI-touching stuff (like the searchField.getValue() call) while holding the lock but keeping the loadResult call outside the critical sections. In this case, it might be useful to lock and unlock stuff explicitly:

  private class WorkThread extends Thread {
    @Override
    public void run() {
      String searchTerm;
      getSession().lock();
      try {
        searchTerm = searchField.getValue();
      } finally {
        getSession().unlock();
      }
      // do the query while the session is not locked
      boolean noResult = loadResult(searchField.getValue());
      getSession().lock();
      try {
          getUI().setPollInterval(-1);
          getUI().removeWindow(blockerWindow);
      } finally {
        getSession().unlock();
      }
    }
  }

A bit cleaner solution would be passing the search term as a constructor parameter to WorkThread.

Hi Johannes
I tries with the SessionLock and it works pertfectly. Thanks a lot :slight_smile:
I had some issues in loadResult(searchTerm); because some tables are filled inside this call. I also had to lock them.

Thanks a lot
Stefan