|
1 <!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en"> |
|
2 <html> |
|
3 <head> |
|
4 |
|
5 <meta http-equiv="Content-Type" |
|
6 content="text/html; charset=iso-8859-1"> |
|
7 |
|
8 <meta name="GENERATOR" |
|
9 content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]"> |
|
10 <!-- |
|
11 Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. |
|
12 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
13 |
|
14 This code is free software; you can redistribute it and/or modify it |
|
15 under the terms of the GNU General Public License version 2 only, as |
|
16 published by the Free Software Foundation. Sun designates this |
|
17 particular file as subject to the "Classpath" exception as provided |
|
18 by Sun in the LICENSE file that accompanied this code. |
|
19 |
|
20 This code is distributed in the hope that it will be useful, but WITHOUT |
|
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
22 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
23 version 2 for more details (a copy is included in the LICENSE file that |
|
24 accompanied this code). |
|
25 |
|
26 You should have received a copy of the GNU General Public License version |
|
27 2 along with this work; if not, write to the Free Software Foundation, |
|
28 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
29 |
|
30 Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
31 CA 95054 USA or visit www.sun.com if you need additional information or |
|
32 have any questions. |
|
33 --> |
|
34 <title>javax.sql.rowset.spi</title> |
|
35 |
|
36 </head> |
|
37 <body bgcolor="#ffffff"> |
|
38 |
|
39 The standard classes and interfaces that a third party vendor has to |
|
40 use in its implementation of a synchronization provider. These classes and |
|
41 interfaces are referred to as the Service Provider Interface (SPI). A vendor may |
|
42 have its implementation included on the JDBC web page that lists available |
|
43 <code>SyncProvider</code> implementations by sending email to <code>jdbc@sun.com</code>. |
|
44 Doing this helps make developers aware of the implementation. To make it possible |
|
45 for a <code>RowSet</code> object to use an implementation, the vendor must register |
|
46 it with the <code>SyncFactory</code> singleton. (See the class comment for |
|
47 <code>SyncProvider</code> for a full explanation of the registration process and |
|
48 the naming convention to be used.) |
|
49 <P> |
|
50 <h2>Table of Contents</h2> |
|
51 <ul> |
|
52 <li><a href="#pkgspec">1.0 Package Specification</a> |
|
53 <li><a href="#arch">2.0 Service Provider Architecture</a> |
|
54 <li><a href="#impl">3.0 Implementer's Guide</a> |
|
55 <li><a href="#resolving">4.0 Resolving Synchronization Conflicts</a> |
|
56 <li><a href="#relspec">5.0 Related Specifications</a> |
|
57 <li><a href="#reldocs">6.0 Related Documentation</a> |
|
58 </ul> |
|
59 |
|
60 <h3><a name="pkgspec">1.0 Package Specification</h3> |
|
61 <P> |
|
62 The following classes and interfaces make up the <code>javax.sql.rowset.spi</code> |
|
63 package: |
|
64 <UL> |
|
65 <LI><code>SyncFactory</code> |
|
66 <LI><code>SyncProvider</code> |
|
67 <LI><code>SyncFactoryException</code> |
|
68 <LI><code>SyncProviderException</code> |
|
69 <LI><code>SyncResolver</code> |
|
70 <LI><code>XmlReader</code> |
|
71 <LI><code>XmlWriter</code> |
|
72 <LI><code>TransactionalWriter</code> |
|
73 </UL> |
|
74 The following interfaces, in the <code>javax.sql</code> package, are also part of the SPI: |
|
75 <UL> |
|
76 <LI><code>RowSetReader</code> |
|
77 <LI><code>RowSetWriter</code> |
|
78 </UL> |
|
79 <P> |
|
80 A <code>SyncProvider</code> implementation provides a disconnected <code>RowSet</code> |
|
81 object with the mechanisms for reading data into it and for writing data that has been |
|
82 modified in it |
|
83 back to the underlying data source. A <i>reader</i>, a <code>RowSetReader</code> or |
|
84 <code>XMLReader</code> object, reads data into a <code>RowSet</code> object when the |
|
85 <code>CachedRowSet</code> methods <code>execute</code> or <code>populate</code> |
|
86 are called. A <i>writer</i>, a <code>RowSetWriter</code> or <code>XMLWriter</code> |
|
87 object, writes changes back to the underlying data source when the |
|
88 <code>CachedRowSet</code> method <code>acceptChanges</code> is called. |
|
89 <P> |
|
90 The process of writing changes in a <code>RowSet</code> object to its data source |
|
91 is known as <i>synchronization</i>. The <code>SyncProvider</code> implementation that a |
|
92 <code>RowSet</code> object is using determines the level of synchronization that the |
|
93 <code>RowSet</code> object's writer uses. The various levels of synchronization are |
|
94 referred to as <i>grades</i>. |
|
95 <P> |
|
96 The lower grades of synchronization are |
|
97 known as <i>optimistic</i> concurrency levels because they optimistically |
|
98 assume that there will be no conflicts or very few conflicts. A conflict exists when |
|
99 the same data modified in the <code>RowSet</code> object has also been modified |
|
100 in the data source. Using the optimistic concurrency model means that if there |
|
101 is a conflict, modifications to either the data source or the <code>RowSet</code> |
|
102 object will be lost. |
|
103 <P> |
|
104 Higher grades of synchronization are called <i>pessimistic</i> because they assume |
|
105 that others will be accessing the data source and making modifications. These |
|
106 grades set varying levels of locks to increase the chances that no conflicts |
|
107 occur. |
|
108 <P> |
|
109 The lowest level of synchronization is simply writing any changes made to the |
|
110 <code>RowSet</code> object to its underlying data source. The writer does |
|
111 nothing to check for conflicts. |
|
112 If there is a conflict and the data |
|
113 source values are overwritten, the changes other parties have made by to the data |
|
114 source are lost. |
|
115 <P> |
|
116 The <code>RIXMLProvider</code> implementation uses the lowest level |
|
117 of synchronization and just writes <code>RowSet</code> changes to the data source. |
|
118 This is true because typically XML data sources do not enable transaction |
|
119 techniques for maintaining the integrity of data. However, specific standards |
|
120 groups have considered offering XML-based synchronization. For details, see |
|
121 <PRE> |
|
122 <a href="http://www.syncml.org">http://www.syncml.org</a> |
|
123 </PRE> |
|
124 <P> |
|
125 For the the next level up, the |
|
126 writer checks to see if there are any conflicts, and if there are, |
|
127 it does not write anything to the data source. The problem with this concurrency |
|
128 level is that if another party has modified the corresponding data in the data source |
|
129 since the <code>RowSet</code> object got its data, |
|
130 the changes made to the <code>RowSet</code> object are lost. The |
|
131 <code>RIOptimisticProvider</code> implementation uses this level of synchronization. |
|
132 <P> |
|
133 At higher levels of synchronization, referred to as pessimistic concurrency, |
|
134 the writer take steps to avoid conflicts by setting locks. Setting locks |
|
135 can vary from setting a lock on a single row to setting a lock on a table |
|
136 or the entire data source. The level of synchronization is therefore a tradeoff |
|
137 between the ability of users to access the data source concurrently and the ability |
|
138 of the writer to keep the data in the <code>RowSet</code> object and its data source |
|
139 synchronized. |
|
140 <P> |
|
141 It is a requirement that all disconnected <code>RowSet</code> objects |
|
142 (<code>CachedRowSet</code>, <code>FilteredRowSet</code>, <code>JoinRowSet</code>, |
|
143 and <code>WebRowSet</code> objects) obtain their <code>SyncProvider</code> objects |
|
144 from the <code>SyncFactory</code> mechanism. |
|
145 <P> |
|
146 The reference implementation (RI) provides two synchronization providers. |
|
147 <UL> |
|
148 <LI><b><tt>RIOptimisticProvider</tt></b> <br> |
|
149 The default provider that the <code>SyncFactory</code> instance will |
|
150 supply to a disconnected <code>RowSet</code> object when no provider |
|
151 implementation is specified.<BR> |
|
152 This synchronization provider uses an optimistic concurrency model, |
|
153 assuming that there will be few conflicts among users |
|
154 who are accessing the same data in a database. It avoids |
|
155 using locks; rather, it checks to see if there is a conflict |
|
156 before trying to synchronize the <code>RowSet</code> object and the |
|
157 data source. If there is a conflict, it does nothing, meaning that |
|
158 changes to the <code>RowSet</code> object are not persisted to the data |
|
159 source. |
|
160 <LI><B><tt>RIXMLProvider</tt></B> <BR> |
|
161 A synchronization provider that can be used with a |
|
162 <code>WebRowSet</code> object, which is a rowset that can be written |
|
163 in XML format or read from XML format. The |
|
164 <code>RIXMLProvider</code> implementation does no checking at all for |
|
165 conflicts and simply writes any updated data in the |
|
166 <code>WebRowSet</code> object to the underlying data source. |
|
167 <code>WebRowSet</code> objects use this provider when they are |
|
168 dealing with XML data. |
|
169 </UL> |
|
170 |
|
171 These <code>SyncProvider</code> implementations |
|
172 are bundled with the reference implementation, which makes them always available to |
|
173 <code>RowSet</code> implementations. |
|
174 <code>SyncProvider</code> implementations make themselves available by being |
|
175 registered with the <code>SyncFactory</code> singleton. When a <code>RowSet</code> |
|
176 object requests a provider, by specifying it in the constructor or as an argument to the |
|
177 <code>CachedRowSet</code> method <code>setSyncProvider</code>, |
|
178 the <code>SyncFactory</code> singleton |
|
179 checks to see if the requested provider has been registered with it. |
|
180 If it has, the <code>SyncFactory</code> creates an instance of it and passes it to the |
|
181 requesting <code>RowSet</code> object. |
|
182 If the <code>SyncProvider</code> implementation that is specified has not been registered, |
|
183 the <code>SyncFactory</code> singleton causes a <code>SyncFactoryException</code> object |
|
184 to be thrown. If no provider is specified, |
|
185 the <code>SyncFactory</code> singleton will create an instance of the default |
|
186 provider implementation, <code>RIOptimisticProvider</code>, |
|
187 and pass it to the requesting <code>RowSet</code> object. |
|
188 |
|
189 <P> |
|
190 If a <code>WebRowSet</code> object does not specify a provider in its constructor, the |
|
191 <code>SyncFactory</code> will give it an instance of <code>RIOptimisticProvider</code>. |
|
192 However, the constructor for <code>WebRowSet</code> is implemented to set the provider |
|
193 to the <code>RIXMLProvider</code>, which reads and writes a <code>RowSet</code> object |
|
194 in XML format. |
|
195 <P> |
|
196 See the <a href="SyncProvider.html">SyncProvider</a> class |
|
197 specification for further details. |
|
198 <p> |
|
199 Vendors may develop a <tt>SyncProvider</tt> implementation with any one of the possible |
|
200 levels of synchronization, thus giving <code>RowSet</code> objects a choice of |
|
201 synchronization mechanisms. A vendor can make its implementation available by |
|
202 registering the fully qualified class name with Sun Microsystems at |
|
203 <code>jdbc@sun.com</code>. This process is discussed in further detail below. |
|
204 <P> |
|
205 |
|
206 <a name="arch"><h3>2.0 Service Provider Interface Architecture</h3> |
|
207 <ul> |
|
208 <b>2.1 Overview</b> |
|
209 <p> |
|
210 The Service Provider Interface provides a pluggable mechanism by which |
|
211 <code>SyncProvider</code> implementations can be registered and then generated when |
|
212 required. The lazy reference mechanism employed by the <code>SyncFactory</code> limits |
|
213 unnecessary resource consumption by not creating an instance until it is |
|
214 required by a disconnected |
|
215 <code>RowSet</code> object. The <code>SyncFactory</code> class also provides |
|
216 a standard API to configure logging options and streams that <b>may</b> be provided |
|
217 by a particular <code>SyncProvider</code> implementation. |
|
218 <p> |
|
219 <b>2.2 Registering with the <code>SyncFactory</code></b> |
|
220 <p> |
|
221 A third party <code>SyncProvider</code> implementation must be registered with the |
|
222 <code>SyncFactory</code> in order for a disconnected <code>RowSet</code> object |
|
223 to obtain it and thereby use its <code>javax.sql.RowSetReader</code> and |
|
224 <code>javax.sql.RowSetWriter</code> |
|
225 implementations. The following registration mechanisms are available to all |
|
226 <code>SyncProvider</code> implementations: |
|
227 <ul> |
|
228 <li><b>System properties</b> - Properties set at the command line. These |
|
229 properties are set at run time and apply system-wide per invocation of the Java |
|
230 application. See the section <a href="#reldocs">"Related Documentation"</a> |
|
231 further related information. |
|
232 <p> |
|
233 <li><b>Property Files</b> - Properties specified in a standard property file. |
|
234 This can be specified using a System Property or by modifying a standard |
|
235 property file located in the platform run-time. The |
|
236 reference implementation of this technology includes a standard property |
|
237 file than can be edited to add additional <code>SyncProvider</code> objects. |
|
238 <p> |
|
239 <li><b>JNDI Context</b> - Available providers can be registered on a JNDI |
|
240 context. The <tt>SyncFactory</tt> will attempt to load <tt>SyncProvider</tt> |
|
241 objects bound to the context and register them with the factory. This |
|
242 context must be supplied to the <code>SyncFactory</code> for the mechanism to |
|
243 function correctly. |
|
244 </ul> |
|
245 <p> |
|
246 Details on how to specify the system properties or properties in a property file |
|
247 and how to configure the JNDI Context are explained in detail in the |
|
248 <a href="SyncFactory.html"><code>SyncFactory</code></a> class description. |
|
249 <p> |
|
250 <b>2.3 SyncFactory Provider Instance Generation Policies</b> |
|
251 <p> |
|
252 The <code>SyncFactory</code> generates a requested <code>SyncProvider</code> |
|
253 object if the provider has been correctly registered. The |
|
254 following policies are adhered to when either a disconnected <code>RowSet</code> object |
|
255 is instantiated with a specified <code>SyncProvider</code> implementation or is |
|
256 reconfigured at runtime with an alternative <code>SyncProvider</code> object. |
|
257 <ul> |
|
258 <li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code> |
|
259 contains <i>no</i> reference to the provider, a <code>SyncFactoryException</code> is |
|
260 thrown. |
|
261 <p> |
|
262 <li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code> |
|
263 contains a reference to the provider, the requested provider is supplied. |
|
264 <p> |
|
265 <li> If no <code>SyncProvider</code> object is specified, the reference |
|
266 implementation provider <code>RIOptimisticProvider</code> is supplied. |
|
267 </ul> |
|
268 <p> |
|
269 These policies are explored in more detail in the <a href="SyncFactory.html"> |
|
270 <code>SyncFactory</code></a> class. |
|
271 </ul> |
|
272 |
|
273 <li><a name="impl"><h3>3.0 SyncProvider Implementer's Guide</h3> |
|
274 <ul> |
|
275 <b>3.1 Requirements</b> |
|
276 <p> |
|
277 A compliant <code>SyncProvider</code> implementation that is fully pluggable |
|
278 into the <code>SyncFactory</code> <b>must</b> extend and implement all |
|
279 abstract methods in the <a href="SyncProvider.html"><code>SyncProvider</code></a> |
|
280 class. In addition, an implementation <b>must</b> determine the |
|
281 grade, locking and updatable view capabilities defined in the |
|
282 <code>SyncProvider</code> class definition. One or more of the |
|
283 <code>SyncProvider</code> description criteria <b>must</b> be supported. It |
|
284 is expected that vendor implementations will offer a range of grade, locking, and |
|
285 updatable view capabilities. |
|
286 <p> |
|
287 Furthermore, the <code>SyncProvider</code> naming convention <b>must</b> be followed as |
|
288 detailed in the <a href="SyncProvider.html"><code>SyncProvider</code></a> class |
|
289 description. |
|
290 <p> |
|
291 <b>3.2 Grades</b> |
|
292 <p> |
|
293 JSR 114 defines a set of grades to describe the quality of synchronization |
|
294 a <code>SyncProvider</code> object can offer a disconnected <code>RowSet</code> |
|
295 object. These grades are listed from the lowest quality of service to the highest. |
|
296 <ul> |
|
297 <li><b>GRADE_NONE</b> - No synchronization with the originating data source is |
|
298 provided. A <code>SyncProvider</code> implementation returning this grade will simply |
|
299 attempt to write any data that has changed in the <code>RowSet</code> object to the |
|
300 underlying data source, overwriting whatever is there. No attempt is made to compare |
|
301 original values with current values to see if there is a conflict. The |
|
302 <code>RIXMLProvider</code> is implemented with this grade. |
|
303 <p> |
|
304 <li><b>GRADE_CHECK_MODIFIED_AT_COMMIT</b> - A low grade of optimistic synchronization. |
|
305 A <code>SyncProvider</code> implementation returning this grade |
|
306 will check for conflicts in rows that have changed between the last synchronization |
|
307 and the current synchronization under way. Any changes in the originating data source |
|
308 that have been modified will not be reflected in the disconnected <code>RowSet</code> |
|
309 object. If there are no conflicts, changes in the <code>RowSet</code> object will be |
|
310 written to the data source. If there are conflicts, no changes are written. |
|
311 The <code>RIOptimisticProvider</code> implementation uses this grade. |
|
312 <p> |
|
313 <li><b>GRADE_CHECK_ALL_AT_COMMIT</b> - A high grade of optimistic synchronization. |
|
314 A <code>SyncProvider</code> implementation returning this grade |
|
315 will check all rows, including rows that have not changed in the disconnected |
|
316 <code>RowSet</code> object. In this way, any changes to rows in the underlying |
|
317 data source will be reflected in the disconnected <code>RowSet</code> object |
|
318 when the synchronization finishes successfully. |
|
319 <p> |
|
320 <li><b>GRADE_LOCK_WHEN_MODIFIED</b> - A pessimistic grade of synchronization. |
|
321 <code>SyncProvider</code> implementations returning this grade will lock |
|
322 the row in the originating data source that corresponds to the row being changed |
|
323 in the <code>RowSet</code> object to reduce the possibility of other |
|
324 processes modifying the same data in the data source. |
|
325 <p> |
|
326 <li><b>GRADE_LOCK_WHEN_LOADED</b> - A higher pessimistic synchronization grade. |
|
327 A <code>SyncProvider</code> implementation returning this grade will lock |
|
328 the entire view and/or table affected by the original query used to |
|
329 populate a <code>RowSet</code> object. |
|
330 </ul> |
|
331 <p> |
|
332 <b>3.3 Locks</b> |
|
333 <p> |
|
334 JSR 114 defines a set of constants that specify whether any locks have been |
|
335 placed on a <code>RowSet</code> object's underlying data source and, if so, |
|
336 on which constructs the locks are placed. These locks will remain on the data |
|
337 source while the <code>RowSet</code> object is disconnected from the data source. |
|
338 <P> |
|
339 These constants <b>should</b> be considered complementary to the |
|
340 grade constants. The default setting for the majority of grade settings requires |
|
341 that no data source locks remain when a <code>RowSet</code> object is disconnected |
|
342 from its data source. |
|
343 The grades <code>GRADE_LOCK_WHEN_MODIFIED</code> and |
|
344 <code>GRADE_LOCK_WHEN_LOADED</code> allow a disconnected <code>RowSet</code> object |
|
345 to have a fine-grained control over the degree of locking. |
|
346 <ul> |
|
347 <li><b>DATASOURCE_NO_LOCK</b> - No locks remain on the originating data source. |
|
348 This is the default lock setting for all <code>SyncProvider</code> implementations |
|
349 unless otherwise directed by a <code>RowSet</code> object. |
|
350 <p> |
|
351 <li><b>DATASOURCE_ROW_LOCK</b> - A lock is placed on the rows that are touched by |
|
352 the original SQL query used to populate the <code>RowSet</code> object. |
|
353 <p> |
|
354 <li><b>DATASOURCE_TABLE_LOCK</b> - A lock is placed on all tables that are touched |
|
355 by the query that was used to populate the <code>RowSet</code> object. |
|
356 <p> |
|
357 <li><b>DATASOURCE_DB_LOCK</b> |
|
358 A lock is placed on the entire data source that is used by the <code>RowSet</code> |
|
359 object. |
|
360 </ul> |
|
361 <p> |
|
362 <b>3.4 Updatable Views</b> |
|
363 <p> |
|
364 A <code>RowSet</code> object may be populated with data from an SQL <code>VIEW</code>. |
|
365 The following constants indicate whether a <code>SyncProvider</code> object can |
|
366 update data in the table or tables from which the <code>VIEW</code> was derived. |
|
367 <ul> |
|
368 <li><b>UPDATABLE_VIEW_SYNC</b> |
|
369 Indicates that a <code>SyncProvider</code> implementation supports synchronization |
|
370 to the table or tables from which the SQL <code>VIEW</code> used to populate a |
|
371 a <code>RowSet</code> object is derived. |
|
372 <p> |
|
373 <li><b>NONUPDATABLE_VIEW_SYNC</b> |
|
374 Indicates that a <code>SyncProvider</code> implementation does <b>not</b> support |
|
375 synchronization to the table or tables from which the SQL <code>VIEW</code> |
|
376 used to populate a <code>RowSet</code> object is derived. |
|
377 </ul> |
|
378 <p> |
|
379 <b>3.5 Usage of <code>SyncProvider</code> Grading and Locking</b> |
|
380 <p> |
|
381 In the example below, the reference <tt>CachedRowSetImpl</tt> implementation |
|
382 reconfigures its current <tt>SyncProvider</tt> object by calling the |
|
383 <tt>setSyncProvider</tt> method.<br> |
|
384 |
|
385 <PRE> |
|
386 CachedRowSetImpl crs = new CachedRowSetImpl(); |
|
387 crs.setSyncProvider("com.foo.bar.HASyncProvider"); |
|
388 </PRE> |
|
389 An application can retrieve the <tt>SyncProvider</tt> object currently in use |
|
390 by a disconnected <code>RowSet</code> object. It can also retrieve the |
|
391 grade of synchronization with which the provider was implemented and the degree of |
|
392 locking currently in use. In addition, an application has the flexibility to set |
|
393 the degree of locking to be used, which can increase the possibilities for successful |
|
394 synchronization. These operation are shown in the following code fragment. |
|
395 <PRE> |
|
396 SyncProvider sync = crs.getSyncProvider(); |
|
397 |
|
398 switch (sync.getProviderGrade()) { |
|
399 case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT |
|
400 //A high grade of optimistic synchronization |
|
401 break; |
|
402 case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT |
|
403 //A low grade of optimistic synchronization |
|
404 break; |
|
405 case: SyncProvider.GRADE_LOCK_WHEN_LOADED |
|
406 // A pessimistic synchronization grade |
|
407 break; |
|
408 case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED |
|
409 // A pessimistic synchronization grade |
|
410 break; |
|
411 case: SyncProvider.GRADE_NONE |
|
412 // No synchronization with the originating data source provided |
|
413 break; |
|
414 } |
|
415 |
|
416 switch (sync.getDataSourcLock() { |
|
417 case: SyncProvider.DATASOURCE_DB_LOCK |
|
418 // A lock is placed on the entire datasource that is used by the |
|
419 // <code>RowSet</code> object |
|
420 break; |
|
421 |
|
422 case: SyncProvider.DATASOURCE_NO_LOCK |
|
423 // No locks remain on the originating data source. |
|
424 break; |
|
425 |
|
426 case: SyncProvider.DATASOURCE_ROW_LOCK |
|
427 // A lock is placed on the rows that are touched by the original |
|
428 // SQL statement used to populate |
|
429 // the RowSet object that is using the SyncProvider |
|
430 break; |
|
431 |
|
432 case: DATASOURCE_TABLE_LOCK |
|
433 // A lock is placed on all tables that are touched by the original |
|
434 // SQL statement used to populated |
|
435 // the RowSet object that is using the SyncProvider |
|
436 break; |
|
437 |
|
438 </PRE> |
|
439 It is also possible using the static utility method in the |
|
440 <code>SyncFactory</code> class to determine the list of <code>SyncProvider</code> |
|
441 implementations currently registered with the <code>SyncFactory</code>. |
|
442 |
|
443 <pre> |
|
444 Enumeration e = SyncFactory.getRegisteredProviders(); |
|
445 </pre> |
|
446 |
|
447 </ul> |
|
448 |
|
449 <h3><a name="resolving">4.0 Resolving Synchronization Conflicts</h3> |
|
450 |
|
451 The interface <code>SyncResolver</code> provides a way for an application to |
|
452 decide manually what to do when a conflict occurs. When the <code>CachedRowSet</code> |
|
453 method <code>acceptChanges</code> finishes and has detected one or more conflicts, |
|
454 it throws a <code>SyncProviderException</code> object. An application can |
|
455 catch the exception and |
|
456 have it retrieve a <code>SyncResolver</code> object by calling the method |
|
457 <code>SyncProviderException.getSyncResolver()</code>. |
|
458 <P> |
|
459 A <code>SyncResolver</code> object, which is a special kind of |
|
460 <code>CachedRowSet</code> object or |
|
461 a <code>JdbcRowSet</code> object that has implemented the <code>SyncResolver</code> |
|
462 interface, examines the conflicts row by row. It is a duplicate of the |
|
463 <code>RowSet</code> object being synchronized except that it contains only the data |
|
464 from the data source this is causing a conflict. All of the other column values are |
|
465 set to <code>null</code>. To navigate from one conflict value to another, a |
|
466 <code>SyncResolver</code> object provides the methods <code>nextConflict</code> and |
|
467 <code>previousConflict</code>. |
|
468 <P> |
|
469 The <code>SyncResolver</code> interface also |
|
470 provides methods for doing the following: |
|
471 <UL> |
|
472 <LI>finding out whether the conflict involved an update, a delete, or an insert |
|
473 <LI>getting the value in the data source that caused the conflict |
|
474 <LI>setting the value that should be in the data source if it needs to be changed |
|
475 or setting the value that should be in the <code>RowSet</code> object if it needs |
|
476 to be changed |
|
477 </UL> |
|
478 <P> |
|
479 When the <code>CachedRowSet</code> method <code>acceptChanges</code> is called, it |
|
480 delegates to the <code>RowSet</code> object's <code>SyncProvider</code> object. |
|
481 How the writer provided by that <code>SyncProvider</code> object is implemented |
|
482 determines what level (grade) of checking for conflicts will be done. After all |
|
483 checking for conflicts is completed and one or more conflicts has been found, the method |
|
484 <code>acceptChanges</code> throws a <code>SyncProviderException</code> object. The |
|
485 application can catch the exception and use it to obtain a <code>SyncResolver</code> object. |
|
486 <P> |
|
487 The application can then use <code>SyncResolver</code> methods to get information |
|
488 about each conflict and decide what to do. If the application logic or the user |
|
489 decides that a value in the <code>RowSet</code> object should be the one to |
|
490 persist, the application or user can overwrite the data source value with it. |
|
491 <P> |
|
492 The comment for the <code>SyncResolver</code> interface has more detail. |
|
493 |
|
494 <a name="relspec"><h3>5.0 Related Specifications</h3> |
|
495 <ul> |
|
496 <li><a href="http://java.sun.com/products/jndi">JNDI 1.3</a> |
|
497 <li><a href="{@docRoot}/../technotes/guides/logging/index.html">Java Logging |
|
498 APIs</a> |
|
499 </ul> |
|
500 <a name="reldocs"><h3>6.0 Related Documentation</h3> |
|
501 <ul> |
|
502 <li><a href="{@docRoot}/../technotes/tools/index.html#basic">System |
|
503 properties</a> |
|
504 <li>Resource Files |
|
505 <li><a href="http://java.sun.com/tutorial/jdbc">DataSource for JDBC |
|
506 Connections</a> |
|
507 </ul> |
|
508 |
|
509 </body> |
|
510 </html> |