|
Replies:
6
-
Last Post:
Jun 12, 2007 12:00 PM
by: jvaudry
|
|
|
|
|
|
|
swingWorker question (application decoupling)
Posted:
Jun 7, 2007 9:27 AM
|
|
|
Hi, I've got a question regarding threading and application decoupling. Most of the time swingWorker examples are very simplistic and the GUI part and the business logic part reside in the same class.
But what if i wanted to move the lengthy task to another class responsible of business logic? There are a couple of things i don't like, for example, the lengthy calculation needs to know about the thread's state (because it may be cancelled) and there are some swing specific methods such as setProgress or "done" as well. What if i change my mind and decide using SWT instead of Swing?
So, basically i think that business logic should not care about how is it being executed but on the other hand i need a way to cancel it , knowing if it has finished it's job and reporting progress so that the GUI can be updated accordingly.
Which would be the best approach in this case? Maybe stroring what the task is doing in some variables in the business logic class and create a Timer in the GUI part that queries those variables?
Thanks in advance.
|
|
|
|
|
|
|
Re: swingWorker question (application decoupling)
Posted:
Jun 8, 2007 6:27 AM
in response to: phantom22
|
|
|
I never was convinced that SwingWorker was giving me anything I couldn't otherwise program more flexibly.. but that's just me.. I was familiar with threads from before SwingWorker...
The new API in 6.0 for concurrency is very very strong... if you have a threading problem just take it as an excuse to buck up and really learn concurrency which will pay you handsome dividends forevermore.... especially since multicore CPUs are now becoming the norm...
This is the best Java book on that subject: http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=pd_bbs_sr_2/104-9637063-1595167?ie=UTF8&s=books&qid=1181308707&sr=8-2
it's a read and a study, yeah OK, but you're always advancing your skill set anyways, right? Concurrency and threading can be applied to a great many things.
|
|
|
|
|
|
|
|
Re: swingWorker question (application decoupling)
Posted:
Jun 9, 2007 11:12 PM
in response to: phantom22
|
|
|
The general approach is to build a framework around SwingWorker that minimizes the work involved in reusing it for diverse purposes.
The main architectural goal is to decouple all the “domain logic� from the “framework logic�. Domain logic is the stuff inside doInBackground() and done(). Framework logic is the code that sends and receives progress updates, cancellations, etc.
This involves defining a set of interfaces and abstract base classes for models that provide cancelable tasks or progress updates. The main design goal here is to minimize the complexity of writing models that offer cancelable tasks or progress updates. Some of this is already done in the concurrency framework (as the other poster has exaplined).
We integrate those interfaces with the Swing Worker. This results in SwingWorker subclasses that can “plug-in� to those interfaces/base classes and work with them. That creates a clean layer of separation between the domain tasks and the machinery to send or receive cancellation & progress messages.
Another useful addition is a library of various swing worker subclasses. For example, the following subclasses are helpful: 1) A SwingWorker that blocks user input while it performs the long running task using: a. A blocking glass pane and an hourglass cursor, b. A modal dialog with an indeterminate progress bar, c. A modal dialog with a determinate progress bar, d. A modal dialog with an indeterminate progress bar and a cancel button, e. A modal dialog with a determinate progress bar and a cancel button. 2) A SwingWorker specifically for constructing and showing windows. 3) A SwingWorker specifically for constructing and showing internal frames. 4) A SwingWorker specifically for polling resources in the background. 5) A SwingWorker specifically for updating tables. 6) A composite SwingWorker that can “chain-together� multiple swing workers while keeping user input blocked through-out until the entire chain completes. 7) Etc, etc, etc.
The idea is to “pull-up� the general or repeated logic and migrate it into your framework. When using a Swing Worker, we just implement doInBackground(), done(), and a couple other methods from the framework interfaces and we get all the progress updating, etc, for free because it is now part of the framework.
If done right, it will take several months to develop a good framework. But the result is that it should only take a new developer a few minutes to use the framework classes to create a long running task that is both cancellable and provides progress updates.
|
|
|
|
|
|
|
|
Re: swingWorker question (application decoupling)
Posted:
Jun 11, 2007 1:22 AM
in response to: jvaudry
|
|
|
My swing classes use swingworker internally, and then publish domain specific updates (propertychangeevents). I haven't felt the need to publish percentages, but i've used started and finished updates. I think that this works better for users of a library than exposing interfaces (that are invariably different) or using swingworker themselves. In fact i'm suspicious of anything more complicated for what is basically a glorified callback.
|
|
|
|
|
|
|
|
Re: swingWorker question (application decoupling)
Posted:
Jun 11, 2007 10:28 AM
in response to: i30817
|
|
|
Just out of curiosity, which tasks do you use a swing worker?
I just did a quick search for places in the code that call the swing worker constructors, and found 278 places we instantiate them. Here is a breakdown:
140 general purpose (communication with a remote server) 77 dialog construction 35 special purposes (constructing wizards, file choosers, etc) 26 internal frame construction
Out of these, about 70% are anonymous subclasses.
As well, we don't use Sun's swing worker. We use the one called SwingWorkerVariant. http://www.javaworld.com/javaworld/jw-06-2003/jw-0606-swingworker.html
We use the "variant" because 90% of our long-running operations take about 0.5 to 3 seconds (not long enough for a progress bar, but OK for showing an hourglass).
|
|
|
|
|
|
|
|
Re: swingWorker question (application decoupling)
Posted:
Jun 12, 2007 8:48 AM
in response to: jvaudry
|
|
|
I bow to your superior experience. I mostly just use swingworker either for sockets with swing, or while parsing a document for swing again. The example i was thinking of is a text jcomponent make that uses swing worker internally to parse text and then update the model. As i wanted to be able to keep swingworker hidden, i just did it internally and sent property changes on starting the swingworker, and ending the swingworker. Then the client code creates listeners for those properties, creating a wait glasspane, and associated domain indicators. Maybe Swing takes another approach because not all uses are mapped by the properties a class implementer made, so they decided to enlarge the granularity of the callbacks. I prefer this approach since it leads to inner classes with clear origin : "do this when this happens".
|
|
|
|
|
|
|
|
Re: swingWorker question (application decoupling)
Posted:
Jun 12, 2007 12:00 PM
in response to: i30817
|
|
|
Your approach sounds very clean and concise :^)
|
|
|
|
|