ViewVC logotype

Contents of /libspin-java/trunk/src/site/xdoc/solution.xml

Parent Directory Parent Directory | Revision Log Revision Log

Revision 682 - (show annotations)
Sun Apr 1 14:26:27 2007 UTC (14 years, 4 months ago) by gregoa
File MIME type: text/xml
File size: 14038 byte(s)
* New upstream release.
* Fix debian/watch.
1 <document>
2 <properties>
3 <author email="sven@users.sourceforge.net">Sven Meier</author>
4 <title>Spin your Swing</title>
5 </properties>
6 <body>
7 <section name="Solution">
8 <subsection name="Spin">
9 <p>
10 Now let's take a look at the <em>Spin</em> solution. Here's the code:
11 </p>
13 <!--
14 public void actionPerformed(ActionEvent e)
15 {
16 label.setText("...");
17 label.setText(bean.getValue());
18 }
20 public void propertyChange(PropertyChangeEvent ev)
21 {
22 label.setText((String)ev.getNewValue());
23 }
24 -->
25 <div class="java left">
26 <h3 class="java">GUI.java</h3>
27 <code class="java"><span class="java4">public </span><span class="java9">void </span><span class="java10">actionPerformed</span><span class="java8">(</span><span class="java10">ActionEvent e</span><span class="java8">)<br />
28 {</span><br />
29 <span class="onEDT">&#xA0; <span class="java10">label.setText</span><span class="java8">(</span><span class="java5">&#34;...&#34;</span><span class="java8">)</span><span class="java10">;<br />
30 &#xA0; label.setText</span><span class="java8">(</span><span class="java10">bean.getValue</span><span class="java8">())</span><span class="java10">;</span></span><br />
31 <span class="java8">}<br />
32 <br />
33 <br />
34 </span><span class="java4">public </span><span class="java9">void </span><span class="java10">propertyChange</span><span class="java8">(</span><span class="java10">PropertyChangeEvent ev</span><span class="java8">)<br />
35 {</span><br />
36 <span class="onEDT">&#xA0; <span class="java10">label.setText</span><span class="java8">((</span><span class="java10">String</span><span class="java8">)</span><span class="java10">ev.getNewValue</span><span class="java8">())</span><span class="java10">;</span></span><br />
37 <span class="java8">}</span>
38 <br />&#xA0;</code></div>
40 <!--
41 public String getValue()
42 {
43 String value;
44 // extensive calculation
45 return value;
46 }
48 public void setValue(String value)
49 {
50 this.value = value;
51 firePropertyChange(value);
52 }
53 -->
54 <div class="java right">
55 <h3 class="java">BeanImpl.java</h3>
56 <code class="java"><span class="java4">public </span><span class="java10">String getValue</span><span class="java8">()<br />
57 {</span><br />
58 <span class="offEDT">&#xA0; <span class="java10">String value;<br />
59 &#xA0; </span><span class="java3">// extensive calculation<br />
60 &#xA0; </span><span class="java4">return </span><span class="java10">value;</span></span><br />
61 <span class="java8">}<br />
62 <br />
63 </span><span class="java4">public </span><span class="java9">void </span><span class="java10">setValue</span><span class="java8">(</span><span class="java10">String value</span><span class="java8">)<br />
64 {</span><br />
65 <span class="offEDT">&#xA0; <span class="java4">this</span><span class="java10">.value = value;<br />
66 &#xA0; firePropertyChange</span><span class="java8">(</span><span class="java10">value</span><span class="java8">)</span><span class="java10">;</span></span><br />
67 <span class="java8">}</span></code></div>
69 <div class="clear"/>
71 <p>
72 Hey wait a minute! It's the same code as shown in the previous section <a href="problem.html#Standard Swing">Standard Swing</a>. But the colors have changed - <code>GUI.java</code> is <span class="onEDT">completely green</span> and <code>BeanImpl.java</code> is <span class="offEDT">completely red</span> - how can this be?
73 </p>
74 <p>
75 <em>Spin</em> makes this solution possible - as you can see with no impact on the old code. An invisible layer between these two classes handles all threading issues transparently.<br/>
76 All we have to do is to <em>spin-off</em> the bean from the <acronym title="Event Dispatch Thread">EDT</acronym>. For this we wrap the bean in an instance of type <code>Spin</code>. The result can safely be casted to any interface the bean (or one of its superclasses) implements. The best place to do this is before a reference to this bean is passed to a <acronym title="Graphical user interface">GUI</acronym> component (why bother the programmer of the <acronym title="Graphical user interface">GUI</acronym> with this little detail):
77 </p>
78 <blockquote>
79 <code>bean = (Bean)Spin.off(bean);</code>
80 </blockquote>
81 <p>
82 The only restriction here is that the Bean has to be broken into interface and implementation. The <acronym title="Graphical user interface">GUI</acronym> components will only use the interface! The following picture shows how <em>Spin</em> connects the <acronym title="Graphical user interface">GUI</acronym> and the bean. Calls on the <acronym title="Event Dispatch Thread">EDT</acronym> from the <acronym title="Graphical user interface">GUI</acronym> to the bean are brokered to other threads invocating the beans functionality:
84 <span class="centeredImage">
85 <img src="images/spinoff.gif" alt="Spin off"/>
86 </span>
87 </p>
88 <p>
89 The need for an interface isn't really a restriction:
90 </p>
91 <ul>
92 <li>
93 It is generally recommended to separate an application in different layers which communicate through well defined interfaces. The <acronym title="Graphical user interface">GUI</acronym> of an application is certainly part of another layer than extensive calculations or I/O operations.
94 </li>
95 <li>
96 If you don't want to or are unable to use an interface you can <a href="acknowledgement.html#CGLib">utilize CGLib instead of JDK proxies</a>.
97 </li>
98 </ul>
99 <p>
100 For the notification of changes to the bean we use an inverse technique.<br/>
101 We must <em>spin-over</em> any invocation of a <acronym title="Graphical user interface">GUI</acronym> callback-method on another thread to the <acronym title="Event Dispatch Thread">EDT</acronym>. This time we wrap the <acronym title="Graphical user interface">GUI</acronym> in a <code>Spin</code> instance assuming that the bean allows for an <code>PropertyChangeListener</code> to be added as a callback (this could be any interface like foo.DataChangedListener):
102 </p>
103 <blockquote>
104 <code>bean.addPropertyChangeListener((PropertyChangeListener)Spin.over(gui);</code>
105 </blockquote>
106 <p>
107 <span class="centeredImage">
108 <img src="images/spinover.gif" alt="Spin over"/>
109 </span>
110 </p>
111 <p>
112 This is all you have to know to get <em>Spin</em> to work in your project. If you're interested in the internals of <em>Spin</em> go on to the next section.
113 </p>
114 </subsection>
115 <subsection name="Internals">
116 <p>
117 <em>Spin</em> is built on top of virtual proxies and a technique borrowed from the java.awt.Dialog component. While a modal dialog has to wait for user input, the <acronym title="Event Dispatch Thread">EDT</acronym> is rerouted to the swing event processing to handle further events.
118 </p>
119 <p>
120 The following diagram shows how this is used in <em>Spin</em>. Each invocation of a bean's method is intercepted and handled by a <a href="./apidocs/spin/off/SpinOffEvaluator.html">SpinOffEvaluator</a>:<br/>
121 getValue() is evaluated asynchronously on another thread (customizable with a <a href="./apidocs/spin/off/Starter.html">Starter</a>) while Swing events are dispatched through a <a href="./apidocs/spin/off/Dispatcher.html">Dispatcher</a>. Once the call to the bean returns the dispatching of events is stopped and the <acronym title="Event Dispatch Thread">EDT</acronym> is free to return to the standard event processing:
123 <span class="centeredImage">
124 <img src="images/sequencespinoff.gif" alt="Spin off sequence"/>
125 </span>
126 </p>
127 <p>
128 For asynchronous notifications from the bean to the <acronym title="Graphical user interface">GUI</acronym> we reuse the technique introduced in the previous sections. But this time the call to <code>invokeAndWait()</code> is encapsulated by <em>Spin</em> with a <a href="./apidocs/spin/over/SpinOverEvaluator.html">SpinOverEvaluator</a>:
130 <span class="centeredImage">
131 <img src="images/sequencespinover.gif" alt="Spin over sequence"/>
132 </span>
133 </p>
134 <p>
135 Please take a look at the full <a href="./apidocs/index.html">API</a> for details on how to customize <em>Spin</em>.
136 </p>
137 </subsection>
138 <subsection name="Caveats">
139 <p>
140 Although <em>Spin</em> handles threading transparently there are caveats with <em>spin-off</em> that you should be aware of:
141 </p>
142 <dl>
143 <dt>Security</dt>
144 <dd>
145 For dispatching <em>Spin</em> needs access to AWT internals that are not available in applets or untrusted JavaWebStart applications due to security restrictions. This will hopefully change once AWT offers an official way to dispatch events.<br/>
146 Meanwhile <em>Spin</em> offers alternative solutions which are less performant but also work in a secured environment. Please take a look at <a href="./apidocs/spin/off/DialogDispatcherFactory.html"> DialogDispatcherFactory</a> and <a href="./apidocs/spin/off/InternalOptionPaneDispatcherFactory.html"> InternalOptionPaneDispatcherFactory</a>.
147 </dd>
148 <dt>Reference backdoor</dt>
149 <dd>
150 If your <acronym title="Graphical user interface">GUI</acronym> hands over references to parts of its swing models (e.g. TreeModel, TableModel) in method calls to your bean, these could possibly be altered on another thread than the <acronym title="Event Dispatch Thread">EDT</acronym> thus VIOLATING THE SWING SINGLE THREADING RULE.
151 </dd>
152 <dt>Bean threadsafety</dt>
153 <dd>
154 If your <acronym title="Graphical user interface">GUI</acronym> doesn't disable all further actions while an invocation on your bean is being processed, the event dispatching may cause a second concurrent call to the bean. In cases where this is desired the BEAN MUST BE THREADSAFE.
155 </dd>
156 <dt>Asynchronous<a name="asynchronous"/></dt>
157 <dd>
158 Whenever your <acronym title="Graphical user interface">GUI</acronym> calls a beans method through <em>Spin</em>, further actions should be allowed only if they are related to the current <em>Spin</em> invocation. This includes <code>Cancel</code> functionality and the retrieval of the current state of invocation or intermediate results (e.g. for updating a progress bar or incremental filling of a table).<br/>
159 You're running into problems if you're using <em>Spin</em> for real asynchronous executions. Let me give an example:<br/>
160 File tranfers of an Explorer-like application wich can be arbitrarily started and stopped while others are independently continuing are NOT A RECOMMENDED USAGE for <em>Spin</em>. Nevertheless <em>Spin</em> can be used to <em>spin-over</em> events from the transfers (e.g. completion notification) to the <acronym title="Event Dispatch Thread">EDT</acronym>.
161 </dd>
162 <dt>Incomplete Event Handling</dt>
163 <dd>
164 An event that triggers <em>Spin</em> will not be completely precessed until the return of the <em>Spin</em> invocation.<br/>
165 This might lead to minor visual annoyances, e.g. a JComboBox that does not close its popup or a JButton that stays depressed while <em>Spin</em> is running. But this behaviour could also result in other unexpected behaviours that you should be aware of.<br/>
166 Because of this <em>Swing</em> developers have expressed their concern about <em>Spin</em> and similar techniques, stating that '<em>Swing</em> is not completely reentrant'.<br/>
167 While this may be true, the same objection could be brought forward against any modal dialog or modal internal frame. If you're using these in your application there is no reason to be afraid of <em>Spin</em>.
168 </dd>
169 </dl>
170 </subsection>
171 <subsection name="Conclusion">
172 <p>
173 <em>Spin</em> is a small library that concentrates on offering a powerful solution to build non-freezing Swing applications. <em>Spin</em> enforces good application design by separating the <acronym title="Graphical user interface">GUI</acronym> and non-visual components through interfaces. If it is used wisely in an application framework, the <acronym title="Graphical user interface">GUI</acronym> programmers will never have to think about threads again.
174 </p>
175 <p>
176 <em>Spin</em> comes with several demonstration classes that show how to solve formerly challenging Swing programming problems with ease:
177 </p>
178 <ul>
179 <li>spin.demo.SpinOffGUI - shows how to execute extensive calculations without "freeze"</li>
180 <li>spin.demo.SpinOverGUI - demonstrates asynchronous event notification without pain</li>
181 <li>spin.demo.exception.ExceptionGUI - proves the transparent exception handling offered by Spin</li>
182 <li>spin.demo.pogress.PullGUI - shows how to handle visual progress while extensive calculations are executed</li>
183 <li>spin.demo.pogress.PushGUI - uses asynchronous event notification to update a progressbar</li>
184 <li>spin.demo.prompt.CallGUI - explains how to prompt the user between multiple extensive calculations</li>
185 <li>spin.demo.prompt.CallbackGUI - prompts the user for input which is triggered by callbacks from an extensive calculation</li>
186 <li>spin.demo.async.AsyncGUI - starts asynchronous calculations transparently through Spin</li>
187 <li>spin.demo.dispatcher.DispatcherGUI - test different dispatchers</li>
188 </ul>
189 <p>
190 We have successfully used <em>Spin</em> successfully in several projects to wrap all remote communication (RMI) between rich-clients and the application server.
191 </p>
192 </subsection>
193 </section>
194 </body>
195 </document>

  ViewVC Help
Powered by ViewVC 1.1.26