The problem for me is :
When user expands jtree node(which represents table name) I must go to database and fetch column names + constraints data + triggers data.
The first two I managed to unite with union but to fetch triggers I need to create PreparedStatement again and execute second query.
According to data of ResultSet I need to construct children-nodes of node to expand.
That's why SwingWorker is not applicable. After I set it up I realised it and the reason is that SwingWorker is not EDT and thus my GUI is not updated.
I need to build GUI only after resultset is returned theerfore swingworker here is not applicable at all. That's why it waits for its time to do some job in parallel
but not sequentially.
BUT two queries with two PreparedStatements is not very quick in java and therefore user will experience a little delay before node with table name is expanded.
There are two possibilities: either use the SwingWorker's built-in facility to return intermediate results (the process()/publish() methods), or schedule your GUI updates onto the event-dispatch thread (using SwingUtilities.invokeLater()). You must make sure that the data you're using on the EDT during update are not modified by the SwingWorker at the same time, but that's all.
If you want to further discuss the SwingWorker, it would be better to create a topic in our Swing forum, though.
Volodymyr Levytskyi wrote:And I tried to call SwingUtitlities invokeLater in swingworker thread and I got exception : can't call invokeLater from not EDT thread.
That's strange. The invokeLater is designed to be called from non-EDT threads (it doesn't make much sense to call it from the EDT thread), and I use it routinely that way. The process/publish mechanism quite certainly uses invokeLater internally too.
Can you reproduce it in a small example (SSCCE)? Or at least post the exception you got?
You don't need to call invokeLater. Override the done() method to update the GUI. The done() method is called in EDT after the doInBackground completes. So no need to use invokeLater. Or you can use publish()/process() methods as suggested above to update the GUI with intermediate results. This is also called in EDT only.
I had understood that you wanted to update the tree with the results as soon as you're done processing them (and you're currently processing two resultsets), to provide some indication of the work in progress.
But even if you don't want to update the GUI during processing, you still should use SwingWorker. If you don't, the application will be unresponsive (won't be redrawn when user moves/resizes its window etc.) SwingWorker doesn't make waiting for results any shorter - it can't obviously - but the application "feels better" to the user. If you add some sort of a progress dialog (as you did, if I'm not mistaken), that would be even better.
I seems that implementing swingworker with publish and process is not worth the effort.
- wrong decision by default output from process, publish, setProgress, done notified EDT
Data is fetched from db as long operation which cannot be published and processed.
- you would need to create batch logics and to use process() with publish() of desired (by default in pct) number of database records/rows to Swing GUI, note you need to know number of records from JDBC before ResutSet is executed
So I do not have intermediate results using jdbc. And I go to db only twice thus I do not think it is worthy to publish results only twice as I have two separate ResultSets.
- right and correct output
- here is everything, JProgressBar (as XxxTableCellRenderer) simulating JDBC ResultSet, sure nicer will be by implements batch logics
As suggested by @Martin I added SwingWorker .
Now I execute access to db in doInBackground method and then method done is called automatically where I update GUI according to retrieved data.
Unfortunately the problem arised. I call method that fetches data of db in doInBackground and builds nodes in done from within TreeWillExpandListener that is whenever user expands node I go to db and create children from retrieved data. It happenned that my node is not expanded as a result of populating node in SwingWorker's done method. Node is populated with all children correctly but it is not expanded. But if I populate node without SwingWorker's done method then node is expanded.
But my swingworker is good because it splashes progressbar when task takes longer 300ms.
you would need to create batch logics
What that means? Now I see that I can execute only one query with one method call PreparedStatement.executeQuery().
I must thank @Martin again as he moved me in right direction.
Because I execute access to db and build nodes in corresponding separate SwingWorker I have my two PreparedStatements run in parallel. This is not what It seems this is what I see when I expand node. At first one SwingWoker finishes its job and I see only one node added and after particles of seconds I see that two others nodes are added as a result of query that runs longer.
Therefore I have a miracle. Now I construct children of the same node in parallel which is proved by my eyes.