blob: 355a2f186e4cd9930784a9c2b7bae730c2eddfd4 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001<!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<!--
11Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
12DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13
14This code is free software; you can redistribute it and/or modify it
15under the terms of the GNU General Public License version 2 only, as
16published by the Free Software Foundation. Sun designates this
17particular file as subject to the "Classpath" exception as provided
18by Sun in the LICENSE file that accompanied this code.
19
20This code is distributed in the hope that it will be useful, but WITHOUT
21ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23version 2 for more details (a copy is included in the LICENSE file that
24accompanied this code).
25
26You should have received a copy of the GNU General Public License version
272 along with this work; if not, write to the Free Software Foundation,
28Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29
30Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31CA 95054 USA or visit www.sun.com if you need additional information or
32have any questions.
33-->
34 <title>javax.sql.rowset.spi</title>
35
36</head>
37 <body bgcolor="#ffffff">
38
39The standard classes and interfaces that a third party vendor has to
40use in its implementation of a synchronization provider. These classes and
41interfaces are referred to as the Service Provider Interface (SPI). A vendor may
42have 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>.
44Doing this helps make developers aware of the implementation. To make it possible
45for a <code>RowSet</code> object to use an implementation, the vendor must register
46it with the <code>SyncFactory</code> singleton. (See the class comment for
47<code>SyncProvider</code> for a full explanation of the registration process and
48the 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>
62The following classes and interfaces make up the <code>javax.sql.rowset.spi</code>
63package:
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>
74The 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>
80A <code>SyncProvider</code> implementation provides a disconnected <code>RowSet</code>
81object with the mechanisms for reading data into it and for writing data that has been
82modified in it
83back 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>
86are called. A <i>writer</i>, a <code>RowSetWriter</code> or <code>XMLWriter</code>
87object, writes changes back to the underlying data source when the
88<code>CachedRowSet</code> method <code>acceptChanges</code> is called.
89<P>
90The process of writing changes in a <code>RowSet</code> object to its data source
91is 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
94referred to as <i>grades</i>.
95<P>
96The lower grades of synchronization are
97known as <i>optimistic</i> concurrency levels because they optimistically
98assume that there will be no conflicts or very few conflicts. A conflict exists when
99the same data modified in the <code>RowSet</code> object has also been modified
100in the data source. Using the optimistic concurrency model means that if there
101is a conflict, modifications to either the data source or the <code>RowSet</code>
102object will be lost.
103<P>
104Higher grades of synchronization are called <i>pessimistic</i> because they assume
105that others will be accessing the data source and making modifications. These
106grades set varying levels of locks to increase the chances that no conflicts
107occur.
108<P>
109The 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
111nothing to check for conflicts.
112If there is a conflict and the data
113source values are overwritten, the changes other parties have made by to the data
114source are lost.
115<P>
116The <code>RIXMLProvider</code> implementation uses the lowest level
117of synchronization and just writes <code>RowSet</code> changes to the data source.
118This is true because typically XML data sources do not enable transaction
119techniques for maintaining the integrity of data. However, specific standards
120groups 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>
125For the the next level up, the
126writer checks to see if there are any conflicts, and if there are,
127it does not write anything to the data source. The problem with this concurrency
128level is that if another party has modified the corresponding data in the data source
129since the <code>RowSet</code> object got its data,
130the changes made to the <code>RowSet</code> object are lost. The
131<code>RIOptimisticProvider</code> implementation uses this level of synchronization.
132<P>
133At higher levels of synchronization, referred to as pessimistic concurrency,
134the writer take steps to avoid conflicts by setting locks. Setting locks
135can vary from setting a lock on a single row to setting a lock on a table
136or the entire data source. The level of synchronization is therefore a tradeoff
137between the ability of users to access the data source concurrently and the ability
138of the writer to keep the data in the <code>RowSet</code> object and its data source
139synchronized.
140<P>
141It is a requirement that all disconnected <code>RowSet</code> objects
142(<code>CachedRowSet</code>, <code>FilteredRowSet</code>, <code>JoinRowSet</code>,
143and <code>WebRowSet</code> objects) obtain their <code>SyncProvider</code> objects
144from the <code>SyncFactory</code> mechanism.
145<P>
146The 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
171These <code>SyncProvider</code> implementations
172are 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
175registered with the <code>SyncFactory</code> singleton. When a <code>RowSet</code>
176object requests a provider, by specifying it in the constructor or as an argument to the
177<code>CachedRowSet</code> method <code>setSyncProvider</code>,
178the <code>SyncFactory</code> singleton
179checks to see if the requested provider has been registered with it.
180If it has, the <code>SyncFactory</code> creates an instance of it and passes it to the
181requesting <code>RowSet</code> object.
182If the <code>SyncProvider</code> implementation that is specified has not been registered,
183the <code>SyncFactory</code> singleton causes a <code>SyncFactoryException</code> object
184to be thrown. If no provider is specified,
185the <code>SyncFactory</code> singleton will create an instance of the default
186provider implementation, <code>RIOptimisticProvider</code>,
187and pass it to the requesting <code>RowSet</code> object.
188
189<P>
190If 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>.
192However, the constructor for <code>WebRowSet</code> is implemented to set the provider
193to the <code>RIXMLProvider</code>, which reads and writes a <code>RowSet</code> object
194in XML format.
195<P>
196See the <a href="SyncProvider.html">SyncProvider</a> class
197specification for further details.
198<p>
199Vendors may develop a <tt>SyncProvider</tt> implementation with any one of the possible
200levels of synchronization, thus giving <code>RowSet</code> objects a choice of
201synchronization mechanisms. A vendor can make its implementation available by
202registering 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>
210The Service Provider Interface provides a pluggable mechanism by which
211<code>SyncProvider</code> implementations can be registered and then generated when
212required. The lazy reference mechanism employed by the <code>SyncFactory</code> limits
213unnecessary resource consumption by not creating an instance until it is
214required by a disconnected
215<code>RowSet</code> object. The <code>SyncFactory</code> class also provides
216a standard API to configure logging options and streams that <b>may</b> be provided
217by a particular <code>SyncProvider</code> implementation.
218<p>
219<b>2.2 Registering with the <code>SyncFactory</code></b>
220<p>
221A third party <code>SyncProvider</code> implementation must be registered with the
222<code>SyncFactory</code> in order for a disconnected <code>RowSet</code> object
223to obtain it and thereby use its <code>javax.sql.RowSetReader</code> and
224<code>javax.sql.RowSetWriter</code>
225implementations. 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
229properties are set at run time and apply system-wide per invocation of the Java
230application. See the section <a href="#reldocs">"Related Documentation"</a>
231further related information.
232<p>
233<li><b>Property Files</b> - Properties specified in a standard property file.
234This can be specified using a System Property or by modifying a standard
235property file located in the platform run-time. The
236reference implementation of this technology includes a standard property
237file 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
240context. The <tt>SyncFactory</tt> will attempt to load <tt>SyncProvider</tt>
241objects bound to the context and register them with the factory. This
242context must be supplied to the <code>SyncFactory</code> for the mechanism to
243function correctly.
244</ul>
245<p>
246Details on how to specify the system properties or properties in a property file
247and 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>
252The <code>SyncFactory</code> generates a requested <code>SyncProvider</code>
253object if the provider has been correctly registered. The
254following policies are adhered to when either a disconnected <code>RowSet</code> object
255is instantiated with a specified <code>SyncProvider</code> implementation or is
256reconfigured 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>
259contains <i>no</i> reference to the provider, a <code>SyncFactoryException</code> is
260thrown.
261<p>
262<li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code>
263contains a reference to the provider, the requested provider is supplied.
264<p>
265<li> If no <code>SyncProvider</code> object is specified, the reference
266implementation provider <code>RIOptimisticProvider</code> is supplied.
267</ul>
268<p>
269These 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>
277A compliant <code>SyncProvider</code> implementation that is fully pluggable
278into the <code>SyncFactory</code> <b>must</b> extend and implement all
279abstract methods in the <a href="SyncProvider.html"><code>SyncProvider</code></a>
280class. In addition, an implementation <b>must</b> determine the
281grade, 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
284is expected that vendor implementations will offer a range of grade, locking, and
285updatable view capabilities.
286<p>
287Furthermore, the <code>SyncProvider</code> naming convention <b>must</b> be followed as
288detailed in the <a href="SyncProvider.html"><code>SyncProvider</code></a> class
289description.
290<p>
291<b>3.2 Grades</b>
292<p>
293JSR 114 defines a set of grades to describe the quality of synchronization
294a <code>SyncProvider</code> object can offer a disconnected <code>RowSet</code>
295object. 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
298provided. A <code>SyncProvider</code> implementation returning this grade will simply
299attempt to write any data that has changed in the <code>RowSet</code> object to the
300underlying data source, overwriting whatever is there. No attempt is made to compare
301original 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.
305A <code>SyncProvider</code> implementation returning this grade
306will check for conflicts in rows that have changed between the last synchronization
307and the current synchronization under way. Any changes in the originating data source
308that have been modified will not be reflected in the disconnected <code>RowSet</code>
309object. If there are no conflicts, changes in the <code>RowSet</code> object will be
310written to the data source. If there are conflicts, no changes are written.
311The <code>RIOptimisticProvider</code> implementation uses this grade.
312<p>
313<li><b>GRADE_CHECK_ALL_AT_COMMIT</b> - A high grade of optimistic synchronization.
314A <code>SyncProvider</code> implementation returning this grade
315will 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
317data source will be reflected in the disconnected <code>RowSet</code> object
318when 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
322the row in the originating data source that corresponds to the row being changed
323in the <code>RowSet</code> object to reduce the possibility of other
324processes modifying the same data in the data source.
325<p>
326<li><b>GRADE_LOCK_WHEN_LOADED</b> - A higher pessimistic synchronization grade.
327A <code>SyncProvider</code> implementation returning this grade will lock
328the entire view and/or table affected by the original query used to
329populate a <code>RowSet</code> object.
330</ul>
331<p>
332<b>3.3 Locks</b>
333<p>
334JSR 114 defines a set of constants that specify whether any locks have been
335placed on a <code>RowSet</code> object's underlying data source and, if so,
336on which constructs the locks are placed. These locks will remain on the data
337source while the <code>RowSet</code> object is disconnected from the data source.
338<P>
339These constants <b>should</b> be considered complementary to the
340grade constants. The default setting for the majority of grade settings requires
341that no data source locks remain when a <code>RowSet</code> object is disconnected
342from its data source.
343The grades <code>GRADE_LOCK_WHEN_MODIFIED</code> and
344<code>GRADE_LOCK_WHEN_LOADED</code> allow a disconnected <code>RowSet</code> object
345to 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.
348This is the default lock setting for all <code>SyncProvider</code> implementations
349unless 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
352the 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
355by the query that was used to populate the <code>RowSet</code> object.
356<p>
357<li><b>DATASOURCE_DB_LOCK</b>
358A lock is placed on the entire data source that is used by the <code>RowSet</code>
359object.
360</ul>
361<p>
362<b>3.4 Updatable Views</b>
363<p>
364A <code>RowSet</code> object may be populated with data from an SQL <code>VIEW</code>.
365The following constants indicate whether a <code>SyncProvider</code> object can
366update data in the table or tables from which the <code>VIEW</code> was derived.
367<ul>
368<li><b>UPDATABLE_VIEW_SYNC</b>
369Indicates that a <code>SyncProvider</code> implementation supports synchronization
370to the table or tables from which the SQL <code>VIEW</code> used to populate a
371a <code>RowSet</code> object is derived.
372<p>
373<li><b>NONUPDATABLE_VIEW_SYNC</b>
374Indicates that a <code>SyncProvider</code> implementation does <b>not</b> support
375synchronization to the table or tables from which the SQL <code>VIEW</code>
376used 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>
381In the example below, the reference <tt>CachedRowSetImpl</tt> implementation
382reconfigures 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
390by a disconnected <code>RowSet</code> object. It can also retrieve the
391grade of synchronization with which the provider was implemented and the degree of
392locking currently in use. In addition, an application has the flexibility to set
393the degree of locking to be used, which can increase the possibilities for successful
394synchronization. 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>
441implementations 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
451The interface <code>SyncResolver</code> provides a way for an application to
452decide manually what to do when a conflict occurs. When the <code>CachedRowSet</code>
453method <code>acceptChanges</code> finishes and has detected one or more conflicts,
454it throws a <code>SyncProviderException</code> object. An application can
455catch the exception and
456have it retrieve a <code>SyncResolver</code> object by calling the method
457<code>SyncProviderException.getSyncResolver()</code>.
458<P>
459A <code>SyncResolver</code> object, which is a special kind of
460<code>CachedRowSet</code> object or
461a <code>JdbcRowSet</code> object that has implemented the <code>SyncResolver</code>
462interface, 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
464from the data source this is causing a conflict. All of the other column values are
465set 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>
469The <code>SyncResolver</code> interface also
470provides 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>
479When the <code>CachedRowSet</code> method <code>acceptChanges</code> is called, it
480delegates to the <code>RowSet</code> object's <code>SyncProvider</code> object.
481How the writer provided by that <code>SyncProvider</code> object is implemented
482determines what level (grade) of checking for conflicts will be done. After all
483checking 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
485application can catch the exception and use it to obtain a <code>SyncResolver</code> object.
486<P>
487The application can then use <code>SyncResolver</code> methods to get information
488about each conflict and decide what to do. If the application logic or the user
489decides that a value in the <code>RowSet</code> object should be the one to
490persist, the application or user can overwrite the data source value with it.
491<P>
492The 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
498APIs</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
503properties</a>
504<li>Resource Files
505<li><a href="http://java.sun.com/tutorial/jdbc">DataSource for JDBC
506Connections</a>
507</ul>
508
509</body>
510</html>