<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en"><html><head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]"><!--Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. This code is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License version 2 only, aspublished by the Free Software Foundation. Oracle designates thisparticular file as subject to the "Classpath" exception as providedby Oracle in the LICENSE file that accompanied this code. This code is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licenseversion 2 for more details (a copy is included in the LICENSE file thataccompanied this code). You should have received a copy of the GNU General Public License version2 along with this work; if not, write to the Free Software Foundation,Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USAor visit www.oracle.com if you need additional information or have anyquestions.--> <title>javax.sql.rowset.spi</title> </head> <body bgcolor="#ffffff"> The standard classes and interfaces that a third party vendor has touse in its implementation of a synchronization provider. These classes and interfaces are referred to as the Service Provider Interface (SPI). A vendor may have its implementation included on the JDBC web page that lists available<code>SyncProvider</code> implementations by sending email to <code>jdbc@sun.com</code>.Doing this helps make developers aware of the implementation. To make it possiblefor a <code>RowSet</code> object to use an implementation, the vendor must registerit with the <code>SyncFactory</code> singleton. (See the class comment for<code>SyncProvider</code> for a full explanation of the registration process and the naming convention to be used.)<P><h2>Table of Contents</h2><ul><li><a href="#pkgspec">1.0 Package Specification</a><li><a href="#arch">2.0 Service Provider Architecture</a><li><a href="#impl">3.0 Implementer's Guide</a><li><a href="#resolving">4.0 Resolving Synchronization Conflicts</a><li><a href="#relspec">5.0 Related Specifications</a><li><a href="#reldocs">6.0 Related Documentation</a></ul> <h3><a name="pkgspec">1.0 Package Specification</h3><P>The following classes and interfaces make up the <code>javax.sql.rowset.spi</code>package:<UL> <LI><code>SyncFactory</code> <LI><code>SyncProvider</code> <LI><code>SyncFactoryException</code> <LI><code>SyncProviderException</code> <LI><code>SyncResolver</code> <LI><code>XmlReader</code> <LI><code>XmlWriter</code> <LI><code>TransactionalWriter</code></UL>The following interfaces, in the <code>javax.sql</code> package, are also part of the SPI:<UL> <LI><code>RowSetReader</code> <LI><code>RowSetWriter</code></UL><P>A <code>SyncProvider</code> implementation provides a disconnected <code>RowSet</code>object with the mechanisms for reading data into it and for writing data that has beenmodified in itback to the underlying data source. A <i>reader</i>, a <code>RowSetReader</code> or<code>XMLReader</code> object, reads data into a <code>RowSet</code> object when the <code>CachedRowSet</code> methods <code>execute</code> or <code>populate</code> are called. A <i>writer</i>, a <code>RowSetWriter</code> or <code>XMLWriter</code>object, writes changes back to the underlying data source when the <code>CachedRowSet</code> method <code>acceptChanges</code> is called.<P>The process of writing changes in a <code>RowSet</code> object to its data sourceis known as <i>synchronization</i>. The <code>SyncProvider</code> implementation that a<code>RowSet</code> object is using determines the level of synchronization that the<code>RowSet</code> object's writer uses. The various levels of synchronization arereferred to as <i>grades</i>.<P>The lower grades of synchronization areknown as <i>optimistic</i> concurrency levels because they optimisticallyassume that there will be no conflicts or very few conflicts. A conflict exists whenthe same data modified in the <code>RowSet</code> object has also been modified in the data source. Using the optimistic concurrency model means that if thereis a conflict, modifications to either the data source or the <code>RowSet</code> object will be lost.<P>Higher grades of synchronization are called <i>pessimistic</i> because they assumethat others will be accessing the data source and making modifications. Thesegrades set varying levels of locks to increase the chances that no conflictsoccur.<P>The lowest level of synchronization is simply writing any changes made to the <code>RowSet</code> object to its underlying data source. The writer doesnothing to check for conflicts. If there is a conflict and the datasource values are overwritten, the changes other parties have made by to the datasource are lost. <P>The <code>RIXMLProvider</code> implementation uses the lowest level of synchronization and just writes <code>RowSet</code> changes to the data source.This is true because typically XML data sources do not enable transactiontechniques for maintaining the integrity of data. However, specific standards groups have considered offering XML-based synchronization. For details, see<PRE> <a href="http://www.syncml.org">http://www.syncml.org</a></PRE><P>For the the next level up, thewriter checks to see if there are any conflicts, and if there are, it does not write anything to the data source. The problem with this concurrencylevel is that if another party has modified the corresponding data in the data source since the <code>RowSet</code> object got its data,the changes made to the <code>RowSet</code> object are lost. The<code>RIOptimisticProvider</code> implementation uses this level of synchronization.<P>At higher levels of synchronization, referred to as pessimistic concurrency,the writer take steps to avoid conflicts by setting locks. Setting lockscan vary from setting a lock on a single row to setting a lock on a table or the entire data source. The level of synchronization is therefore a tradeoff between the ability of users to access the data source concurrently and the abilityof the writer to keep the data in the <code>RowSet</code> object and its data sourcesynchronized.<P>It is a requirement that all disconnected <code>RowSet</code> objects (<code>CachedRowSet</code>, <code>FilteredRowSet</code>, <code>JoinRowSet</code>, and <code>WebRowSet</code> objects) obtain their <code>SyncProvider</code> objectsfrom the <code>SyncFactory</code> mechanism. <P>The reference implementation (RI) provides two synchronization providers. <UL> <LI><b><tt>RIOptimisticProvider</tt></b> <br> The default provider that the <code>SyncFactory</code> instance will supply to a disconnected <code>RowSet</code> object when no provider implementation is specified.<BR> This synchronization provider uses an optimistic concurrency model, assuming that there will be few conflicts among users who are accessing the same data in a database. It avoids using locks; rather, it checks to see if there is a conflict before trying to synchronize the <code>RowSet</code> object and the data source. If there is a conflict, it does nothing, meaning that changes to the <code>RowSet</code> object are not persisted to the data source. <LI><B><tt>RIXMLProvider</tt></B> <BR> A synchronization provider that can be used with a <code>WebRowSet</code> object, which is a rowset that can be written in XML format or read from XML format. The <code>RIXMLProvider</code> implementation does no checking at all for conflicts and simply writes any updated data in the <code>WebRowSet</code> object to the underlying data source. <code>WebRowSet</code> objects use this provider when they are dealing with XML data. </UL> These <code>SyncProvider</code> implementationsare bundled with the reference implementation, which makes them always available to<code>RowSet</code> implementations. <code>SyncProvider</code> implementations make themselves available by beingregistered with the <code>SyncFactory</code> singleton. When a <code>RowSet</code> object requests a provider, by specifying it in the constructor or as an argument to the<code>CachedRowSet</code> method <code>setSyncProvider</code>, the <code>SyncFactory</code> singletonchecks to see if the requested provider has been registered with it.If it has, the <code>SyncFactory</code> creates an instance of it and passes it to therequesting <code>RowSet</code> object. If the <code>SyncProvider</code> implementation that is specified has not been registered,the <code>SyncFactory</code> singleton causes a <code>SyncFactoryException</code> objectto be thrown. If no provider is specified,the <code>SyncFactory</code> singleton will create an instance of the defaultprovider implementation, <code>RIOptimisticProvider</code>,and pass it to the requesting <code>RowSet</code> object. <P>If a <code>WebRowSet</code> object does not specify a provider in its constructor, the<code>SyncFactory</code> will give it an instance of <code>RIOptimisticProvider</code>.However, the constructor for <code>WebRowSet</code> is implemented to set the provider to the <code>RIXMLProvider</code>, which reads and writes a <code>RowSet</code> objectin XML format.<P>See the <a href="SyncProvider.html">SyncProvider</a> classspecification for further details.<p>Vendors may develop a <tt>SyncProvider</tt> implementation with any one of the possiblelevels of synchronization, thus giving <code>RowSet</code> objects a choice ofsynchronization mechanisms. A vendor can make its implementation available by registering the fully qualified class name with Oracle Corporation at<code>jdbc@sun.com</code>. This process is discussed in further detail below. <P> <a name="arch"><h3>2.0 Service Provider Interface Architecture</h3><ul><b>2.1 Overview</b><p>The Service Provider Interface provides a pluggable mechanism by which<code>SyncProvider</code> implementations can be registered and then generated whenrequired. The lazy reference mechanism employed by the <code>SyncFactory</code> limitsunnecessary resource consumption by not creating an instance until it is required by a disconnected<code>RowSet</code> object. The <code>SyncFactory</code> class also providesa standard API to configure logging options and streams that <b>may</b> be providedby a particular <code>SyncProvider</code> implementation.<p><b>2.2 Registering with the <code>SyncFactory</code></b><p>A third party <code>SyncProvider</code> implementation must be registered with the <code>SyncFactory</code> in order for a disconnected <code>RowSet</code> object to obtain it and thereby use its <code>javax.sql.RowSetReader</code> and <code>javax.sql.RowSetWriter</code>implementations. The following registration mechanisms are available to all <code>SyncProvider</code> implementations:<ul><li><b>System properties</b> - Properties set at the command line. Theseproperties are set at run time and apply system-wide per invocation of the Javaapplication. See the section <a href="#reldocs">"Related Documentation"</a>further related information.<p><li><b>Property Files</b> - Properties specified in a standard property file.This can be specified using a System Property or by modifying a standardproperty file located in the platform run-time. Thereference implementation of this technology includes a standard propertyfile than can be edited to add additional <code>SyncProvider</code> objects.<p> <li><b>JNDI Context</b> - Available providers can be registered on a JNDIcontext. The <tt>SyncFactory</tt> will attempt to load <tt>SyncProvider</tt>objects bound to the context and register them with the factory. Thiscontext must be supplied to the <code>SyncFactory</code> for the mechanism to function correctly.</ul><p>Details on how to specify the system properties or properties in a property fileand how to configure the JNDI Context are explained in detail in the<a href="SyncFactory.html"><code>SyncFactory</code></a> class description.<p><b>2.3 SyncFactory Provider Instance Generation Policies</b><p>The <code>SyncFactory</code> generates a requested <code>SyncProvider</code>object if the provider has been correctly registered. Thefollowing policies are adhered to when either a disconnected <code>RowSet</code> objectis instantiated with a specified <code>SyncProvider</code> implementation or is reconfigured at runtime with an alternative <code>SyncProvider</code> object.<ul><li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code>contains <i>no</i> reference to the provider, a <code>SyncFactoryException</code> is thrown.<p><li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code>contains a reference to the provider, the requested provider is supplied.<p><li> If no <code>SyncProvider</code> object is specified, the referenceimplementation provider <code>RIOptimisticProvider</code> is supplied.</ul><p>These policies are explored in more detail in the <a href="SyncFactory.html"><code>SyncFactory</code></a> class.</ul> <li><a name="impl"><h3>3.0 SyncProvider Implementer's Guide</h3><ul><b>3.1 Requirements</b><p>A compliant <code>SyncProvider</code> implementation that is fully pluggableinto the <code>SyncFactory</code> <b>must</b> extend and implement allabstract methods in the <a href="SyncProvider.html"><code>SyncProvider</code></a>class. In addition, an implementation <b>must</b> determine the grade, locking and updatable view capabilities defined in the<code>SyncProvider</code> class definition. One or more of the<code>SyncProvider</code> description criteria <b>must</b> be supported. Itis expected that vendor implementations will offer a range of grade, locking, andupdatable view capabilities.<p>Furthermore, the <code>SyncProvider</code> naming convention <b>must</b> be followed asdetailed in the <a href="SyncProvider.html"><code>SyncProvider</code></a> classdescription.<p><b>3.2 Grades</b><p>JSR 114 defines a set of grades to describe the quality of synchronizationa <code>SyncProvider</code> object can offer a disconnected <code>RowSet</code>object. These grades are listed from the lowest quality of service to the highest.<ul><li><b>GRADE_NONE</b> - No synchronization with the originating data source isprovided. A <code>SyncProvider</code> implementation returning this grade will simplyattempt to write any data that has changed in the <code>RowSet</code> object to theunderlying data source, overwriting whatever is there. No attempt is made to compare original values with current values to see if there is a conflict. The <code>RIXMLProvider</code> is implemented with this grade.<p><li><b>GRADE_CHECK_MODIFIED_AT_COMMIT</b> - A low grade of optimistic synchronization.A <code>SyncProvider</code> implementation returning this gradewill check for conflicts in rows that have changed between the last synchronization and the current synchronization under way. Any changes in the originating data sourcethat have been modified will not be reflected in the disconnected <code>RowSet</code>object. If there are no conflicts, changes in the <code>RowSet</code> object will bewritten to the data source. If there are conflicts, no changes are written.The <code>RIOptimisticProvider</code> implementation uses this grade.<p><li><b>GRADE_CHECK_ALL_AT_COMMIT</b> - A high grade of optimistic synchronization.A <code>SyncProvider</code> implementation returning this gradewill check all rows, including rows that have not changed in the disconnected<code>RowSet</code> object. In this way, any changes to rows in the underlyingdata source will be reflected in the disconnected <code>RowSet</code> objectwhen the synchronization finishes successfully.<p><li><b>GRADE_LOCK_WHEN_MODIFIED</b> - A pessimistic grade of synchronization.<code>SyncProvider</code> implementations returning this grade will lockthe row in the originating data source that corresponds to the row being changedin the <code>RowSet</code> object to reduce the possibility of otherprocesses modifying the same data in the data source.<p><li><b>GRADE_LOCK_WHEN_LOADED</b> - A higher pessimistic synchronization grade.A <code>SyncProvider</code> implementation returning this grade will lockthe entire view and/or table affected by the original query used topopulate a <code>RowSet</code> object.</ul><p><b>3.3 Locks</b><p>JSR 114 defines a set of constants that specify whether any locks have beenplaced on a <code>RowSet</code> object's underlying data source and, if so,on which constructs the locks are placed. These locks will remain on the datasource while the <code>RowSet</code> object is disconnected from the data source.<P>These constants <b>should</b> be considered complementary to the grade constants. The default setting for the majority of grade settings requiresthat no data source locks remain when a <code>RowSet</code> object is disconnected from its data source.The grades <code>GRADE_LOCK_WHEN_MODIFIED</code> and<code>GRADE_LOCK_WHEN_LOADED</code> allow a disconnected <code>RowSet</code> objectto have a fine-grained control over the degree of locking.<ul><li><b>DATASOURCE_NO_LOCK</b> - No locks remain on the originating data source. This is the default lock setting for all <code>SyncProvider</code> implementations unless otherwise directed by a <code>RowSet</code> object.<p><li><b>DATASOURCE_ROW_LOCK</b> - A lock is placed on the rows that are touched bythe original SQL query used to populate the <code>RowSet</code> object.<p> <li><b>DATASOURCE_TABLE_LOCK</b> - A lock is placed on all tables that are touchedby the query that was used to populate the <code>RowSet</code> object.<p><li><b>DATASOURCE_DB_LOCK</b>A lock is placed on the entire data source that is used by the <code>RowSet</code>object.</ul><p><b>3.4 Updatable Views</b><p>A <code>RowSet</code> object may be populated with data from an SQL <code>VIEW</code>.The following constants indicate whether a <code>SyncProvider</code> object canupdate data in the table or tables from which the <code>VIEW</code> was derived.<ul><li><b>UPDATABLE_VIEW_SYNC</b>Indicates that a <code>SyncProvider</code> implementation supports synchronizationto the table or tables from which the SQL <code>VIEW</code> used to populate aa <code>RowSet</code> object is derived.<p><li><b>NONUPDATABLE_VIEW_SYNC</b>Indicates that a <code>SyncProvider</code> implementation does <b>not</b> supportsynchronization to the table or tables from which the SQL <code>VIEW</code> used to populate a <code>RowSet</code> object is derived.</ul><p><b>3.5 Usage of <code>SyncProvider</code> Grading and Locking</b><p>In the example below, the reference <tt>CachedRowSetImpl</tt> implementationreconfigures its current <tt>SyncProvider</tt> object by calling the <tt>setSyncProvider</tt> method.<br> <PRE> CachedRowSetImpl crs = new CachedRowSetImpl(); crs.setSyncProvider("com.foo.bar.HASyncProvider");</PRE> An application can retrieve the <tt>SyncProvider</tt> object currently in useby a disconnected <code>RowSet</code> object. It can also retrieve thegrade of synchronization with which the provider was implemented and the degree oflocking currently in use. In addition, an application has the flexibility to setthe degree of locking to be used, which can increase the possibilities for successfulsynchronization. These operation are shown in the following code fragment.<PRE> SyncProvider sync = crs.getSyncProvider(); switch (sync.getProviderGrade()) { case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT //A high grade of optimistic synchronization break; case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT //A low grade of optimistic synchronization break; case: SyncProvider.GRADE_LOCK_WHEN_LOADED // A pessimistic synchronization grade break; case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED // A pessimistic synchronization grade break; case: SyncProvider.GRADE_NONE // No synchronization with the originating data source provided break; } switch (sync.getDataSourcLock() { case: SyncProvider.DATASOURCE_DB_LOCK // A lock is placed on the entire datasource that is used by the // <code>RowSet</code> object break; case: SyncProvider.DATASOURCE_NO_LOCK // No locks remain on the originating data source. break; case: SyncProvider.DATASOURCE_ROW_LOCK // A lock is placed on the rows that are touched by the original // SQL statement used to populate // the RowSet object that is using the SyncProvider break; case: DATASOURCE_TABLE_LOCK // A lock is placed on all tables that are touched by the original // SQL statement used to populated // the RowSet object that is using the SyncProvider break; </PRE> It is also possible using the static utility method in the<code>SyncFactory</code> class to determine the list of <code>SyncProvider</code>implementations currently registered with the <code>SyncFactory</code>. <pre> Enumeration e = SyncFactory.getRegisteredProviders();</pre> </ul> <h3><a name="resolving">4.0 Resolving Synchronization Conflicts</h3> The interface <code>SyncResolver</code> provides a way for an application todecide manually what to do when a conflict occurs. When the <code>CachedRowSet</code>method <code>acceptChanges</code> finishes and has detected one or more conflicts,it throws a <code>SyncProviderException</code> object. An application cancatch the exception andhave it retrieve a <code>SyncResolver</code> object by calling the method<code>SyncProviderException.getSyncResolver()</code>. <P>A <code>SyncResolver</code> object, which is a special kind of <code>CachedRowSet</code> object ora <code>JdbcRowSet</code> object that has implemented the <code>SyncResolver</code> interface, examines the conflicts row by row. It is a duplicate of the <code>RowSet</code> object being synchronized except that it contains only the datafrom the data source this is causing a conflict. All of the other column values areset to <code>null</code>. To navigate from one conflict value to another, a<code>SyncResolver</code> object provides the methods <code>nextConflict</code> and<code>previousConflict</code>.<P>The <code>SyncResolver</code> interface alsoprovides methods for doing the following:<UL> <LI>finding out whether the conflict involved an update, a delete, or an insert <LI>getting the value in the data source that caused the conflict <LI>setting the value that should be in the data source if it needs to be changed or setting the value that should be in the <code>RowSet</code> object if it needs to be changed</UL><P>When the <code>CachedRowSet</code> method <code>acceptChanges</code> is called, it delegates to the <code>RowSet</code> object's <code>SyncProvider</code> object.How the writer provided by that <code>SyncProvider</code> object is implementeddetermines what level (grade) of checking for conflicts will be done. After all checking for conflicts is completed and one or more conflicts has been found, the method<code>acceptChanges</code> throws a <code>SyncProviderException</code> object. Theapplication can catch the exception and use it to obtain a <code>SyncResolver</code> object. <P>The application can then use <code>SyncResolver</code> methods to get informationabout each conflict and decide what to do. If the application logic or the userdecides that a value in the <code>RowSet</code> object should be the one topersist, the application or user can overwrite the data source value with it. <P>The comment for the <code>SyncResolver</code> interface has more detail. <a name="relspec"><h3>5.0 Related Specifications</h3><ul><li><a href="http://java.sun.com/products/jndi">JNDI 1.3</a><li><a href="{@docRoot}/../technotes/guides/logging/index.html">Java LoggingAPIs</a></ul><a name="reldocs"><h3>6.0 Related Documentation</h3>Lines 1–500 of 510. Load more
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]"> <!-- Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. This code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 only, as published by the Free Software Foundation. Oracle designates this particular file as subject to the "Classpath" exception as provided by Oracle in the LICENSE file that accompanied this code. This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License version 2 for more details (a copy is included in the LICENSE file that accompanied this code). You should have received a copy of the GNU General Public License version 2 along with this work; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA or visit www.oracle.com if you need additional information or have any questions. --> <title>javax.sql.rowset.spi</title> </head> <body bgcolor="#ffffff"> The standard classes and interfaces that a third party vendor has to use in its implementation of a synchronization provider. These classes and interfaces are referred to as the Service Provider Interface (SPI). A vendor may have its implementation included on the JDBC web page that lists available <code>SyncProvider</code> implementations by sending email to <code>jdbc@sun.com</code>. Doing this helps make developers aware of the implementation. To make it possible for a <code>RowSet</code> object to use an implementation, the vendor must register it with the <code>SyncFactory</code> singleton. (See the class comment for <code>SyncProvider</code> for a full explanation of the registration process and the naming convention to be used.) <P> <h2>Table of Contents</h2> <ul> <li><a href="#pkgspec">1.0 Package Specification</a> <li><a href="#arch">2.0 Service Provider Architecture</a> <li><a href="#impl">3.0 Implementer's Guide</a> <li><a href="#resolving">4.0 Resolving Synchronization Conflicts</a> <li><a href="#relspec">5.0 Related Specifications</a> <li><a href="#reldocs">6.0 Related Documentation</a> </ul> <h3><a name="pkgspec">1.0 Package Specification</h3> <P> The following classes and interfaces make up the <code>javax.sql.rowset.spi</code> package: <UL> <LI><code>SyncFactory</code> <LI><code>SyncProvider</code> <LI><code>SyncFactoryException</code> <LI><code>SyncProviderException</code> <LI><code>SyncResolver</code> <LI><code>XmlReader</code> <LI><code>XmlWriter</code> <LI><code>TransactionalWriter</code> </UL> The following interfaces, in the <code>javax.sql</code> package, are also part of the SPI: <UL> <LI><code>RowSetReader</code> <LI><code>RowSetWriter</code> </UL> <P> A <code>SyncProvider</code> implementation provides a disconnected <code>RowSet</code> object with the mechanisms for reading data into it and for writing data that has been modified in it back to the underlying data source. A <i>reader</i>, a <code>RowSetReader</code> or <code>XMLReader</code> object, reads data into a <code>RowSet</code> object when the <code>CachedRowSet</code> methods <code>execute</code> or <code>populate</code> are called. A <i>writer</i>, a <code>RowSetWriter</code> or <code>XMLWriter</code> object, writes changes back to the underlying data source when the <code>CachedRowSet</code> method <code>acceptChanges</code> is called. <P> The process of writing changes in a <code>RowSet</code> object to its data source is known as <i>synchronization</i>. The <code>SyncProvider</code> implementation that a <code>RowSet</code> object is using determines the level of synchronization that the <code>RowSet</code> object's writer uses. The various levels of synchronization are referred to as <i>grades</i>. <P> The lower grades of synchronization are known as <i>optimistic</i> concurrency levels because they optimistically assume that there will be no conflicts or very few conflicts. A conflict exists when the same data modified in the <code>RowSet</code> object has also been modified in the data source. Using the optimistic concurrency model means that if there is a conflict, modifications to either the data source or the <code>RowSet</code> object will be lost. <P> Higher grades of synchronization are called <i>pessimistic</i> because they assume that others will be accessing the data source and making modifications. These grades set varying levels of locks to increase the chances that no conflicts occur. <P> The lowest level of synchronization is simply writing any changes made to the <code>RowSet</code> object to its underlying data source. The writer does nothing to check for conflicts. If there is a conflict and the data source values are overwritten, the changes other parties have made by to the data source are lost. <P> The <code>RIXMLProvider</code> implementation uses the lowest level of synchronization and just writes <code>RowSet</code> changes to the data source. This is true because typically XML data sources do not enable transaction techniques for maintaining the integrity of data. However, specific standards groups have considered offering XML-based synchronization. For details, see <PRE> <a href="http://www.syncml.org">http://www.syncml.org</a> </PRE> <P> For the the next level up, the writer checks to see if there are any conflicts, and if there are, it does not write anything to the data source. The problem with this concurrency level is that if another party has modified the corresponding data in the data source since the <code>RowSet</code> object got its data, the changes made to the <code>RowSet</code> object are lost. The <code>RIOptimisticProvider</code> implementation uses this level of synchronization. <P> At higher levels of synchronization, referred to as pessimistic concurrency, the writer take steps to avoid conflicts by setting locks. Setting locks can vary from setting a lock on a single row to setting a lock on a table or the entire data source. The level of synchronization is therefore a tradeoff between the ability of users to access the data source concurrently and the ability of the writer to keep the data in the <code>RowSet</code> object and its data source synchronized. <P> It is a requirement that all disconnected <code>RowSet</code> objects (<code>CachedRowSet</code>, <code>FilteredRowSet</code>, <code>JoinRowSet</code>, and <code>WebRowSet</code> objects) obtain their <code>SyncProvider</code> objects from the <code>SyncFactory</code> mechanism. <P> The reference implementation (RI) provides two synchronization providers. <UL> <LI><b><tt>RIOptimisticProvider</tt></b> <br> The default provider that the <code>SyncFactory</code> instance will supply to a disconnected <code>RowSet</code> object when no provider implementation is specified.<BR> This synchronization provider uses an optimistic concurrency model, assuming that there will be few conflicts among users who are accessing the same data in a database. It avoids using locks; rather, it checks to see if there is a conflict before trying to synchronize the <code>RowSet</code> object and the data source. If there is a conflict, it does nothing, meaning that changes to the <code>RowSet</code> object are not persisted to the data source. <LI><B><tt>RIXMLProvider</tt></B> <BR> A synchronization provider that can be used with a <code>WebRowSet</code> object, which is a rowset that can be written in XML format or read from XML format. The <code>RIXMLProvider</code> implementation does no checking at all for conflicts and simply writes any updated data in the <code>WebRowSet</code> object to the underlying data source. <code>WebRowSet</code> objects use this provider when they are dealing with XML data. </UL> These <code>SyncProvider</code> implementations are bundled with the reference implementation, which makes them always available to <code>RowSet</code> implementations. <code>SyncProvider</code> implementations make themselves available by being registered with the <code>SyncFactory</code> singleton. When a <code>RowSet</code> object requests a provider, by specifying it in the constructor or as an argument to the <code>CachedRowSet</code> method <code>setSyncProvider</code>, the <code>SyncFactory</code> singleton checks to see if the requested provider has been registered with it. If it has, the <code>SyncFactory</code> creates an instance of it and passes it to the requesting <code>RowSet</code> object. If the <code>SyncProvider</code> implementation that is specified has not been registered, the <code>SyncFactory</code> singleton causes a <code>SyncFactoryException</code> object to be thrown. If no provider is specified, the <code>SyncFactory</code> singleton will create an instance of the default provider implementation, <code>RIOptimisticProvider</code>, and pass it to the requesting <code>RowSet</code> object. <P> If a <code>WebRowSet</code> object does not specify a provider in its constructor, the <code>SyncFactory</code> will give it an instance of <code>RIOptimisticProvider</code>. However, the constructor for <code>WebRowSet</code> is implemented to set the provider to the <code>RIXMLProvider</code>, which reads and writes a <code>RowSet</code> object in XML format. <P> See the <a href="SyncProvider.html">SyncProvider</a> class specification for further details. <p> Vendors may develop a <tt>SyncProvider</tt> implementation with any one of the possible levels of synchronization, thus giving <code>RowSet</code> objects a choice of synchronization mechanisms. A vendor can make its implementation available by registering the fully qualified class name with Oracle Corporation at <code>jdbc@sun.com</code>. This process is discussed in further detail below. <P> <a name="arch"><h3>2.0 Service Provider Interface Architecture</h3> <ul> <b>2.1 Overview</b> <p> The Service Provider Interface provides a pluggable mechanism by which <code>SyncProvider</code> implementations can be registered and then generated when required. The lazy reference mechanism employed by the <code>SyncFactory</code> limits unnecessary resource consumption by not creating an instance until it is required by a disconnected <code>RowSet</code> object. The <code>SyncFactory</code> class also provides a standard API to configure logging options and streams that <b>may</b> be provided by a particular <code>SyncProvider</code> implementation. <p> <b>2.2 Registering with the <code>SyncFactory</code></b> <p> A third party <code>SyncProvider</code> implementation must be registered with the <code>SyncFactory</code> in order for a disconnected <code>RowSet</code> object to obtain it and thereby use its <code>javax.sql.RowSetReader</code> and <code>javax.sql.RowSetWriter</code> implementations. The following registration mechanisms are available to all <code>SyncProvider</code> implementations: <ul> <li><b>System properties</b> - Properties set at the command line. These properties are set at run time and apply system-wide per invocation of the Java application. See the section <a href="#reldocs">"Related Documentation"</a> further related information. <p> <li><b>Property Files</b> - Properties specified in a standard property file. This can be specified using a System Property or by modifying a standard property file located in the platform run-time. The reference implementation of this technology includes a standard property file than can be edited to add additional <code>SyncProvider</code> objects. <p> <li><b>JNDI Context</b> - Available providers can be registered on a JNDI context. The <tt>SyncFactory</tt> will attempt to load <tt>SyncProvider</tt> objects bound to the context and register them with the factory. This context must be supplied to the <code>SyncFactory</code> for the mechanism to function correctly. </ul> <p> Details on how to specify the system properties or properties in a property file and how to configure the JNDI Context are explained in detail in the <a href="SyncFactory.html"><code>SyncFactory</code></a> class description. <p> <b>2.3 SyncFactory Provider Instance Generation Policies</b> <p> The <code>SyncFactory</code> generates a requested <code>SyncProvider</code> object if the provider has been correctly registered. The following policies are adhered to when either a disconnected <code>RowSet</code> object is instantiated with a specified <code>SyncProvider</code> implementation or is reconfigured at runtime with an alternative <code>SyncProvider</code> object. <ul> <li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code> contains <i>no</i> reference to the provider, a <code>SyncFactoryException</code> is thrown. <p> <li> If a <code>SyncProvider</code> object is specified and the <code>SyncFactory</code> contains a reference to the provider, the requested provider is supplied. <p> <li> If no <code>SyncProvider</code> object is specified, the reference implementation provider <code>RIOptimisticProvider</code> is supplied. </ul> <p> These policies are explored in more detail in the <a href="SyncFactory.html"> <code>SyncFactory</code></a> class. </ul> <li><a name="impl"><h3>3.0 SyncProvider Implementer's Guide</h3> <ul> <b>3.1 Requirements</b> <p> A compliant <code>SyncProvider</code> implementation that is fully pluggable into the <code>SyncFactory</code> <b>must</b> extend and implement all abstract methods in the <a href="SyncProvider.html"><code>SyncProvider</code></a> class. In addition, an implementation <b>must</b> determine the grade, locking and updatable view capabilities defined in the <code>SyncProvider</code> class definition. One or more of the <code>SyncProvider</code> description criteria <b>must</b> be supported. It is expected that vendor implementations will offer a range of grade, locking, and updatable view capabilities. <p> Furthermore, the <code>SyncProvider</code> naming convention <b>must</b> be followed as detailed in the <a href="SyncProvider.html"><code>SyncProvider</code></a> class description. <p> <b>3.2 Grades</b> <p> JSR 114 defines a set of grades to describe the quality of synchronization a <code>SyncProvider</code> object can offer a disconnected <code>RowSet</code> object. These grades are listed from the lowest quality of service to the highest. <ul> <li><b>GRADE_NONE</b> - No synchronization with the originating data source is provided. A <code>SyncProvider</code> implementation returning this grade will simply attempt to write any data that has changed in the <code>RowSet</code> object to the underlying data source, overwriting whatever is there. No attempt is made to compare original values with current values to see if there is a conflict. The <code>RIXMLProvider</code> is implemented with this grade. <p> <li><b>GRADE_CHECK_MODIFIED_AT_COMMIT</b> - A low grade of optimistic synchronization. A <code>SyncProvider</code> implementation returning this grade will check for conflicts in rows that have changed between the last synchronization and the current synchronization under way. Any changes in the originating data source that have been modified will not be reflected in the disconnected <code>RowSet</code> object. If there are no conflicts, changes in the <code>RowSet</code> object will be written to the data source. If there are conflicts, no changes are written. The <code>RIOptimisticProvider</code> implementation uses this grade. <p> <li><b>GRADE_CHECK_ALL_AT_COMMIT</b> - A high grade of optimistic synchronization. A <code>SyncProvider</code> implementation returning this grade will check all rows, including rows that have not changed in the disconnected <code>RowSet</code> object. In this way, any changes to rows in the underlying data source will be reflected in the disconnected <code>RowSet</code> object when the synchronization finishes successfully. <p> <li><b>GRADE_LOCK_WHEN_MODIFIED</b> - A pessimistic grade of synchronization. <code>SyncProvider</code> implementations returning this grade will lock the row in the originating data source that corresponds to the row being changed in the <code>RowSet</code> object to reduce the possibility of other processes modifying the same data in the data source. <p> <li><b>GRADE_LOCK_WHEN_LOADED</b> - A higher pessimistic synchronization grade. A <code>SyncProvider</code> implementation returning this grade will lock the entire view and/or table affected by the original query used to populate a <code>RowSet</code> object. </ul> <p> <b>3.3 Locks</b> <p> JSR 114 defines a set of constants that specify whether any locks have been placed on a <code>RowSet</code> object's underlying data source and, if so, on which constructs the locks are placed. These locks will remain on the data source while the <code>RowSet</code> object is disconnected from the data source. <P> These constants <b>should</b> be considered complementary to the grade constants. The default setting for the majority of grade settings requires that no data source locks remain when a <code>RowSet</code> object is disconnected from its data source. The grades <code>GRADE_LOCK_WHEN_MODIFIED</code> and <code>GRADE_LOCK_WHEN_LOADED</code> allow a disconnected <code>RowSet</code> object to have a fine-grained control over the degree of locking. <ul> <li><b>DATASOURCE_NO_LOCK</b> - No locks remain on the originating data source. This is the default lock setting for all <code>SyncProvider</code> implementations unless otherwise directed by a <code>RowSet</code> object. <p> <li><b>DATASOURCE_ROW_LOCK</b> - A lock is placed on the rows that are touched by the original SQL query used to populate the <code>RowSet</code> object. <p> <li><b>DATASOURCE_TABLE_LOCK</b> - A lock is placed on all tables that are touched by the query that was used to populate the <code>RowSet</code> object. <p> <li><b>DATASOURCE_DB_LOCK</b> A lock is placed on the entire data source that is used by the <code>RowSet</code> object. </ul> <p> <b>3.4 Updatable Views</b> <p> A <code>RowSet</code> object may be populated with data from an SQL <code>VIEW</code>. The following constants indicate whether a <code>SyncProvider</code> object can update data in the table or tables from which the <code>VIEW</code> was derived. <ul> <li><b>UPDATABLE_VIEW_SYNC</b> Indicates that a <code>SyncProvider</code> implementation supports synchronization to the table or tables from which the SQL <code>VIEW</code> used to populate a a <code>RowSet</code> object is derived. <p> <li><b>NONUPDATABLE_VIEW_SYNC</b> Indicates that a <code>SyncProvider</code> implementation does <b>not</b> support synchronization to the table or tables from which the SQL <code>VIEW</code> used to populate a <code>RowSet</code> object is derived. </ul> <p> <b>3.5 Usage of <code>SyncProvider</code> Grading and Locking</b> <p> In the example below, the reference <tt>CachedRowSetImpl</tt> implementation reconfigures its current <tt>SyncProvider</tt> object by calling the <tt>setSyncProvider</tt> method.<br> <PRE> CachedRowSetImpl crs = new CachedRowSetImpl(); crs.setSyncProvider("com.foo.bar.HASyncProvider"); </PRE> An application can retrieve the <tt>SyncProvider</tt> object currently in use by a disconnected <code>RowSet</code> object. It can also retrieve the grade of synchronization with which the provider was implemented and the degree of locking currently in use. In addition, an application has the flexibility to set the degree of locking to be used, which can increase the possibilities for successful synchronization. These operation are shown in the following code fragment. <PRE> SyncProvider sync = crs.getSyncProvider(); switch (sync.getProviderGrade()) { case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT //A high grade of optimistic synchronization break; case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT //A low grade of optimistic synchronization break; case: SyncProvider.GRADE_LOCK_WHEN_LOADED // A pessimistic synchronization grade break; case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED // A pessimistic synchronization grade break; case: SyncProvider.GRADE_NONE // No synchronization with the originating data source provided break; } switch (sync.getDataSourcLock() { case: SyncProvider.DATASOURCE_DB_LOCK // A lock is placed on the entire datasource that is used by the // <code>RowSet</code> object break; case: SyncProvider.DATASOURCE_NO_LOCK // No locks remain on the originating data source. break; case: SyncProvider.DATASOURCE_ROW_LOCK // A lock is placed on the rows that are touched by the original // SQL statement used to populate // the RowSet object that is using the SyncProvider break; case: DATASOURCE_TABLE_LOCK // A lock is placed on all tables that are touched by the original // SQL statement used to populated // the RowSet object that is using the SyncProvider break; </PRE> It is also possible using the static utility method in the <code>SyncFactory</code> class to determine the list of <code>SyncProvider</code> implementations currently registered with the <code>SyncFactory</code>. <pre> Enumeration e = SyncFactory.getRegisteredProviders(); </pre> </ul> <h3><a name="resolving">4.0 Resolving Synchronization Conflicts</h3> The interface <code>SyncResolver</code> provides a way for an application to decide manually what to do when a conflict occurs. When the <code>CachedRowSet</code> method <code>acceptChanges</code> finishes and has detected one or more conflicts, it throws a <code>SyncProviderException</code> object. An application can catch the exception and have it retrieve a <code>SyncResolver</code> object by calling the method <code>SyncProviderException.getSyncResolver()</code>. <P> A <code>SyncResolver</code> object, which is a special kind of <code>CachedRowSet</code> object or a <code>JdbcRowSet</code> object that has implemented the <code>SyncResolver</code> interface, examines the conflicts row by row. It is a duplicate of the <code>RowSet</code> object being synchronized except that it contains only the data from the data source this is causing a conflict. All of the other column values are set to <code>null</code>. To navigate from one conflict value to another, a <code>SyncResolver</code> object provides the methods <code>nextConflict</code> and <code>previousConflict</code>. <P> The <code>SyncResolver</code> interface also provides methods for doing the following: <UL> <LI>finding out whether the conflict involved an update, a delete, or an insert <LI>getting the value in the data source that caused the conflict <LI>setting the value that should be in the data source if it needs to be changed or setting the value that should be in the <code>RowSet</code> object if it needs to be changed </UL> <P> When the <code>CachedRowSet</code> method <code>acceptChanges</code> is called, it delegates to the <code>RowSet</code> object's <code>SyncProvider</code> object. How the writer provided by that <code>SyncProvider</code> object is implemented determines what level (grade) of checking for conflicts will be done. After all checking for conflicts is completed and one or more conflicts has been found, the method <code>acceptChanges</code> throws a <code>SyncProviderException</code> object. The application can catch the exception and use it to obtain a <code>SyncResolver</code> object. <P> The application can then use <code>SyncResolver</code> methods to get information about each conflict and decide what to do. If the application logic or the user decides that a value in the <code>RowSet</code> object should be the one to persist, the application or user can overwrite the data source value with it. <P> The comment for the <code>SyncResolver</code> interface has more detail. <a name="relspec"><h3>5.0 Related Specifications</h3> <ul> <li><a href="http://java.sun.com/products/jndi">JNDI 1.3</a> <li><a href="{@docRoot}/../technotes/guides/logging/index.html">Java Logging APIs</a> </ul> <a name="reldocs"><h3>6.0 Related Documentation</h3>