0N/A<!
DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
0N/A <
meta http-
equiv="Content-Type" 0N/A <
meta name="GENERATOR" 2802N/ACopyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 0N/ADO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/AThis code is free software; you can redistribute it and/or modify it 0N/Aunder the terms of the GNU General Public License version 2 only, as 2362N/Apublished by the Free Software Foundation. Oracle designates this 0N/Aparticular file as subject to the "Classpath" exception as provided 2362N/Aby Oracle in the LICENSE file that accompanied this code. 0N/AThis code is distributed in the hope that it will be useful, but WITHOUT 0N/AANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/AFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/Aversion 2 for more details (a copy is included in the LICENSE file that 0N/Aaccompanied this code). 0N/AYou should have received a copy of the GNU General Public License version 0N/A2 along with this work; if not, write to the Free Software Foundation, 0N/AInc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2365N/APlease contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A <
body bgcolor="#ffffff">
0N/AThe standard classes and interfaces that a third party vendor has to
0N/Ause in its implementation of a synchronization provider. These classes and
0N/Ainterfaces are referred to as the Service Provider Interface (SPI). A vendor may
0N/Ahave its implementation included on the JDBC web page that lists available
0N/A<
code>SyncProvider</
code> implementations by sending email to <
code>jdbc@sun.com</
code>.
0N/ADoing this helps make developers aware of the implementation. To make it possible
0N/Afor a <
code>RowSet</
code> object to use an implementation, the vendor must register
0N/Ait with the <
code>SyncFactory</
code> singleton. (See the class comment for
0N/A<
code>SyncProvider</
code> for a full explanation of the registration process and
0N/Athe naming convention to be used.)
0N/A<
h2>Table of Contents</
h2>
0N/A<
li><
a href="#pkgspec">1.0 Package Specification</
a>
0N/A<
li><
a href="#arch">2.0 Service Provider Architecture</
a>
0N/A<
li><
a href="#impl">3.0 Implementer's Guide</
a>
0N/A<
li><
a href="#resolving">4.0 Resolving Synchronization Conflicts</
a>
0N/A<
li><
a href="#relspec">5.0 Related Specifications</
a>
0N/A<
li><
a href="#reldocs">6.0 Related Documentation</
a>
0N/A<
h3><
a name="pkgspec">1.0 Package Specification</
h3>
0N/A <
LI><
code>SyncFactory</
code>
0N/A <
LI><
code>SyncProvider</
code>
0N/A <
LI><
code>SyncFactoryException</
code>
0N/A <
LI><
code>SyncProviderException</
code>
0N/A <
LI><
code>SyncResolver</
code>
0N/A <
LI><
code>XmlReader</
code>
0N/A <
LI><
code>XmlWriter</
code>
0N/A <
LI><
code>TransactionalWriter</
code>
0N/AThe following interfaces, in the <
code>
javax.sql</
code> package, are also part of the SPI:
0N/A <
LI><
code>RowSetReader</
code>
0N/A <
LI><
code>RowSetWriter</
code>
0N/AA <
code>SyncProvider</
code> implementation provides a disconnected <
code>RowSet</
code>
0N/Aobject with the mechanisms for reading data into it and for writing data that has been
0N/Aback to the underlying data source. A <
i>reader</
i>, a <
code>RowSetReader</
code> or
0N/A<
code>XMLReader</
code> object, reads data into a <
code>RowSet</
code> object when the
0N/A<
code>CachedRowSet</
code> methods <
code>execute</
code> or <
code>populate</
code>
0N/Aare called. A <
i>writer</
i>, a <
code>RowSetWriter</
code> or <
code>XMLWriter</
code>
0N/Aobject, writes changes back to the underlying data source when the
0N/A<
code>CachedRowSet</
code> method <
code>acceptChanges</
code> is called.
0N/AThe process of writing changes in a <
code>RowSet</
code> object to its data source
0N/Ais known as <
i>synchronization</
i>. The <
code>SyncProvider</
code> implementation that a
0N/A<
code>RowSet</
code> object is using determines the level of synchronization that the
0N/A<
code>RowSet</
code> object's writer uses. The various levels of synchronization are
0N/Areferred to as <
i>grades</
i>.
0N/AThe lower grades of synchronization are
0N/Aknown as <
i>optimistic</
i> concurrency levels because they optimistically
0N/Aassume that there will be no conflicts or very few conflicts. A conflict exists when
0N/Athe same data modified in the <
code>RowSet</
code> object has also been modified
0N/Ain the data source. Using the optimistic concurrency model means that if there
0N/Ais a conflict, modifications to either the data source or the <
code>RowSet</
code>
0N/AHigher grades of synchronization are called <
i>pessimistic</
i> because they assume
0N/Athat others will be accessing the data source and making modifications. These
0N/Agrades set varying levels of locks to increase the chances that no conflicts
0N/AThe lowest level of synchronization is simply writing any changes made to the
0N/A<
code>RowSet</
code> object to its underlying data source. The writer does
0N/Anothing to check for conflicts.
0N/AIf there is a conflict and the data
0N/Asource values are overwritten, the changes other parties have made by to the data
0N/AThe <
code>RIXMLProvider</
code> implementation uses the lowest level
0N/Aof synchronization and just writes <
code>RowSet</
code> changes to the data source.
0N/AThis is true because typically XML data sources do not enable transaction
0N/Atechniques for maintaining the integrity of data. However, specific standards
0N/Agroups have considered offering XML-based synchronization. For details, see
0N/AFor the the next level up, the
0N/Awriter checks to see if there are any conflicts, and if there are,
0N/Ait does not write anything to the data source. The problem with this concurrency
0N/Alevel is that if another party has modified the corresponding data in the data source
0N/Asince the <
code>RowSet</
code> object got its data,
0N/Athe changes made to the <
code>RowSet</
code> object are lost. The
0N/A<
code>RIOptimisticProvider</
code> implementation uses this level of synchronization.
0N/AAt higher levels of synchronization, referred to as pessimistic concurrency,
0N/Athe writer take steps to avoid conflicts by setting locks. Setting locks
0N/Acan vary from setting a lock on a single row to setting a lock on a table
0N/Aor the entire data source. The level of synchronization is therefore a tradeoff
0N/Abetween the ability of users to access the data source concurrently and the ability
0N/Aof the writer to keep the data in the <
code>RowSet</
code> object and its data source
0N/AIt is a requirement that all disconnected <
code>RowSet</
code> objects
0N/A(<
code>CachedRowSet</
code>, <
code>FilteredRowSet</
code>, <
code>JoinRowSet</
code>,
0N/Aand <
code>WebRowSet</
code> objects) obtain their <
code>SyncProvider</
code> objects
0N/Afrom the <
code>SyncFactory</
code> mechanism.
0N/AThe reference implementation (RI) provides two synchronization providers.
0N/A <
LI><
b><
tt>RIOptimisticProvider</
tt></
b> <
br>
0N/A The default provider that the <
code>SyncFactory</
code> instance will
0N/A supply to a disconnected <
code>RowSet</
code> object when no provider
0N/A implementation is specified.<
BR>
0N/A This synchronization provider uses an optimistic concurrency model,
0N/A assuming that there will be few conflicts among users
0N/A who are accessing the same data in a database. It avoids
0N/A using locks; rather, it checks to see if there is a conflict
0N/A before trying to synchronize the <
code>RowSet</
code> object and the
0N/A data source. If there is a conflict, it does nothing, meaning that
0N/A changes to the <
code>RowSet</
code> object are not persisted to the data
0N/A <
LI><
B><
tt>RIXMLProvider</
tt></
B> <
BR>
0N/A A synchronization provider that can be used with a
0N/A <
code>WebRowSet</
code> object, which is a rowset that can be written
0N/A in XML format or read from XML format. The
0N/A <
code>RIXMLProvider</
code> implementation does no checking at all for
0N/A conflicts and simply writes any updated data in the
0N/A <
code>WebRowSet</
code> object to the underlying data source.
0N/A <
code>WebRowSet</
code> objects use this provider when they are
0N/A dealing with XML data.
0N/AThese <
code>SyncProvider</
code> implementations
0N/Aare bundled with the reference implementation, which makes them always available to
0N/A<
code>RowSet</
code> implementations.
0N/A<
code>SyncProvider</
code> implementations make themselves available by being
0N/Aregistered with the <
code>SyncFactory</
code> singleton. When a <
code>RowSet</
code>
0N/Aobject requests a provider, by specifying it in the constructor or as an argument to the
0N/A<
code>CachedRowSet</
code> method <
code>setSyncProvider</
code>,
0N/Athe <
code>SyncFactory</
code> singleton
0N/Achecks to see if the requested provider has been registered with it.
0N/AIf it has, the <
code>SyncFactory</
code> creates an instance of it and passes it to the
0N/Arequesting <
code>RowSet</
code> object.
0N/AIf the <
code>SyncProvider</
code> implementation that is specified has not been registered,
0N/Athe <
code>SyncFactory</
code> singleton causes a <
code>SyncFactoryException</
code> object
0N/Ato be thrown. If no provider is specified,
0N/Athe <
code>SyncFactory</
code> singleton will create an instance of the default
0N/Aprovider implementation, <
code>RIOptimisticProvider</
code>,
0N/Aand pass it to the requesting <
code>RowSet</
code> object.
0N/AIf a <
code>WebRowSet</
code> object does not specify a provider in its constructor, the
0N/A<
code>SyncFactory</
code> will give it an instance of <
code>RIOptimisticProvider</
code>.
0N/AHowever, the constructor for <
code>WebRowSet</
code> is implemented to set the provider
0N/Ato the <
code>RIXMLProvider</
code>, which reads and writes a <
code>RowSet</
code> object
0N/Aspecification for further details.
0N/AVendors may develop a <
tt>SyncProvider</
tt> implementation with any one of the possible
0N/Alevels of synchronization, thus giving <
code>RowSet</
code> objects a choice of
0N/Asynchronization mechanisms. A vendor can make its implementation available by
2802N/Aregistering the fully qualified class name with Oracle Corporation at
0N/A<
code>jdbc@sun.com</
code>. This process is discussed in further detail below.
0N/A<
a name="arch"><
h3>2.0 Service Provider Interface Architecture</
h3>
0N/AThe Service Provider Interface provides a pluggable mechanism by which
0N/A<
code>SyncProvider</
code> implementations can be registered and then generated when
0N/Arequired. The lazy reference mechanism employed by the <
code>SyncFactory</
code> limits
0N/Aunnecessary resource consumption by not creating an instance until it is
0N/Arequired by a disconnected
0N/A<
code>RowSet</
code> object. The <
code>SyncFactory</
code> class also provides
0N/Aa standard API to configure logging options and streams that <
b>may</
b> be provided
0N/Aby a particular <
code>SyncProvider</
code> implementation.
0N/A<
b>2.2 Registering with the <
code>SyncFactory</
code></
b>
0N/AA third party <
code>SyncProvider</
code> implementation must be registered with the
0N/A<
code>SyncFactory</
code> in order for a disconnected <
code>RowSet</
code> object
0N/Aimplementations. The following registration mechanisms are available to all
0N/A<
code>SyncProvider</
code> implementations:
0N/A<
li><
b>System properties</
b> - Properties set at the command line. These
0N/Aproperties are set at run time and apply system-wide per invocation of the Java
0N/Aapplication. See the section <
a href="#reldocs">"Related Documentation"</
a>
0N/Afurther related information.
0N/A<
li><
b>Property Files</
b> - Properties specified in a standard property file.
0N/AThis can be specified using a System Property or by modifying a standard
0N/Aproperty file located in the platform run-time. The
0N/Areference implementation of this technology includes a standard property
0N/Afile than can be edited to add additional <
code>SyncProvider</
code> objects.
0N/A<
li><
b>JNDI Context</
b> - Available providers can be registered on a JNDI
0N/Acontext. The <
tt>SyncFactory</
tt> will attempt to load <
tt>SyncProvider</
tt>
0N/Aobjects bound to the context and register them with the factory. This
0N/Acontext must be supplied to the <
code>SyncFactory</
code> for the mechanism to
0N/ADetails on how to specify the system properties or properties in a property file
0N/Aand how to configure the JNDI Context are explained in detail in the
0N/A<
b>2.3 SyncFactory Provider Instance Generation Policies</
b>
0N/AThe <
code>SyncFactory</
code> generates a requested <
code>SyncProvider</
code>
0N/Aobject if the provider has been correctly registered. The
0N/Afollowing policies are adhered to when either a disconnected <
code>RowSet</
code> object
0N/Ais instantiated with a specified <
code>SyncProvider</
code> implementation or is
0N/Areconfigured at runtime with an alternative <
code>SyncProvider</
code> object.
0N/A<
li> If a <
code>SyncProvider</
code> object is specified and the <
code>SyncFactory</
code>
0N/Acontains <
i>no</
i> reference to the provider, a <
code>SyncFactoryException</
code> is
0N/A<
li> If a <
code>SyncProvider</
code> object is specified and the <
code>SyncFactory</
code>
0N/Acontains a reference to the provider, the requested provider is supplied.
0N/A<
li> If no <
code>SyncProvider</
code> object is specified, the reference
0N/Aimplementation provider <
code>RIOptimisticProvider</
code> is supplied.
0N/A<
code>SyncFactory</
code></
a> class.
0N/A<
li><
a name="impl"><
h3>3.0 SyncProvider Implementer's Guide</
h3>
0N/A<
b>3.1 Requirements</
b>
0N/AA compliant <
code>SyncProvider</
code> implementation that is fully pluggable
0N/Ainto the <
code>SyncFactory</
code> <
b>must</
b> extend and implement all
0N/Aclass. In addition, an implementation <
b>must</
b> determine the
0N/Agrade, locking and updatable view capabilities defined in the
0N/A<
code>SyncProvider</
code> class definition. One or more of the
0N/A<
code>SyncProvider</
code> description criteria <
b>must</
b> be supported. It
0N/Ais expected that vendor implementations will offer a range of grade, locking, and
0N/Aupdatable view capabilities.
0N/AFurthermore, the <
code>SyncProvider</
code> naming convention <
b>must</
b> be followed as
0N/AJSR 114 defines a set of grades to describe the quality of synchronization
0N/Aa <
code>SyncProvider</
code> object can offer a disconnected <
code>RowSet</
code>
0N/Aobject. These grades are listed from the lowest quality of service to the highest.
0N/A<
li><
b>GRADE_NONE</
b> - No synchronization with the originating data source is
0N/Aprovided. A <
code>SyncProvider</
code> implementation returning this grade will simply
0N/Aattempt to write any data that has changed in the <
code>RowSet</
code> object to the
0N/Aunderlying data source, overwriting whatever is there. No attempt is made to compare
0N/Aoriginal values with current values to see if there is a conflict. The
0N/A<
code>RIXMLProvider</
code> is implemented with this grade.
0N/A<
li><
b>GRADE_CHECK_MODIFIED_AT_COMMIT</
b> - A low grade of optimistic synchronization.
0N/AA <
code>SyncProvider</
code> implementation returning this grade
0N/Awill check for conflicts in rows that have changed between the last synchronization
0N/Aand the current synchronization under way. Any changes in the originating data source
0N/Athat have been modified will not be reflected in the disconnected <
code>RowSet</
code>
0N/Aobject. If there are no conflicts, changes in the <
code>RowSet</
code> object will be
0N/Awritten to the data source. If there are conflicts, no changes are written.
0N/AThe <
code>RIOptimisticProvider</
code> implementation uses this grade.
0N/A<
li><
b>GRADE_CHECK_ALL_AT_COMMIT</
b> - A high grade of optimistic synchronization.
0N/AA <
code>SyncProvider</
code> implementation returning this grade
0N/Awill check all rows, including rows that have not changed in the disconnected
0N/A<
code>RowSet</
code> object. In this way, any changes to rows in the underlying
0N/Adata source will be reflected in the disconnected <
code>RowSet</
code> object
0N/Awhen the synchronization finishes successfully.
0N/A<
li><
b>GRADE_LOCK_WHEN_MODIFIED</
b> - A pessimistic grade of synchronization.
0N/A<
code>SyncProvider</
code> implementations returning this grade will lock
0N/Athe row in the originating data source that corresponds to the row being changed
0N/Ain the <
code>RowSet</
code> object to reduce the possibility of other
0N/Aprocesses modifying the same data in the data source.
0N/A<
li><
b>GRADE_LOCK_WHEN_LOADED</
b> - A higher pessimistic synchronization grade.
0N/AA <
code>SyncProvider</
code> implementation returning this grade will lock
0N/Athe entire view
and/
or table affected by the original query used to
0N/Apopulate a <
code>RowSet</
code> object.
0N/AJSR 114 defines a set of constants that specify whether any locks have been
0N/Aplaced on a <
code>RowSet</
code> object's underlying data source and, if so,
0N/Aon which constructs the locks are placed. These locks will remain on the data
0N/Asource while the <
code>RowSet</
code> object is disconnected from the data source.
0N/AThese constants <
b>should</
b> be considered complementary to the
0N/Agrade constants. The default setting for the majority of grade settings requires
0N/Athat no data source locks remain when a <
code>RowSet</
code> object is disconnected
0N/Afrom its data source.
0N/AThe grades <
code>GRADE_LOCK_WHEN_MODIFIED</
code> and
0N/A<
code>GRADE_LOCK_WHEN_LOADED</
code> allow a disconnected <
code>RowSet</
code> object
0N/Ato have a fine-grained control over the degree of locking.
0N/A<
li><
b>DATASOURCE_NO_LOCK</
b> - No locks remain on the originating data source.
0N/AThis is the default lock setting for all <
code>SyncProvider</
code> implementations
0N/Aunless otherwise directed by a <
code>RowSet</
code> object.
0N/A<
li><
b>DATASOURCE_ROW_LOCK</
b> - A lock is placed on the rows that are touched by
0N/Athe original SQL query used to populate the <
code>RowSet</
code> object.
0N/A<
li><
b>DATASOURCE_TABLE_LOCK</
b> - A lock is placed on all tables that are touched
0N/Aby the query that was used to populate the <
code>RowSet</
code> object.
0N/A<
li><
b>DATASOURCE_DB_LOCK</
b>
0N/AA lock is placed on the entire data source that is used by the <
code>RowSet</
code>
0N/A<
b>3.4 Updatable Views</
b>
0N/AA <
code>RowSet</
code> object may be populated with data from an SQL <
code>VIEW</
code>.
0N/AThe following constants indicate whether a <
code>SyncProvider</
code> object can
0N/Aupdate data in the table or tables from which the <
code>VIEW</
code> was derived.
0N/A<
li><
b>UPDATABLE_VIEW_SYNC</
b>
0N/AIndicates that a <
code>SyncProvider</
code> implementation supports synchronization
0N/Ato the table or tables from which the SQL <
code>VIEW</
code> used to populate a
0N/Aa <
code>RowSet</
code> object is derived.
0N/A<
li><
b>NONUPDATABLE_VIEW_SYNC</
b>
0N/AIndicates that a <
code>SyncProvider</
code> implementation does <
b>not</
b> support
0N/Asynchronization to the table or tables from which the SQL <
code>VIEW</
code>
0N/Aused to populate a <
code>RowSet</
code> object is derived.
0N/A<
b>3.5 Usage of <
code>SyncProvider</
code> Grading and Locking</
b>
0N/AIn the example below, the reference <
tt>CachedRowSetImpl</
tt> implementation
0N/Areconfigures its current <
tt>SyncProvider</
tt> object by calling the
0N/A<
tt>setSyncProvider</
tt> method.<
br>
0N/A CachedRowSetImpl crs = new CachedRowSetImpl();
0N/A An application can retrieve the <
tt>SyncProvider</
tt> object currently in use
0N/Aby a disconnected <
code>RowSet</
code> object. It can also retrieve the
0N/Agrade of synchronization with which the provider was implemented and the degree of
0N/Alocking currently in use. In addition, an application has the flexibility to set
0N/Athe degree of locking to be used, which can increase the possibilities for successful
0N/Asynchronization. These operation are shown in the following code fragment.
0N/A //A high grade of optimistic synchronization
0N/A //A low grade of optimistic synchronization
0N/A // A pessimistic synchronization grade
0N/A // A pessimistic synchronization grade
0N/A // No synchronization with the originating data source provided
0N/A // A lock is placed on the entire datasource that is used by the
0N/A // <
code>RowSet</
code> object
0N/A // No locks remain on the originating data source.
0N/A // A lock is placed on the rows that are touched by the original
0N/A // SQL statement used to populate
0N/A // the RowSet object that is using the SyncProvider
0N/A case: DATASOURCE_TABLE_LOCK
0N/A // A lock is placed on all tables that are touched by the original
0N/A // SQL statement used to populated
0N/A // the RowSet object that is using the SyncProvider
0N/A It is also possible using the static utility method in the
0N/A<
code>SyncFactory</
code> class to determine the list of <
code>SyncProvider</
code>
0N/Aimplementations currently registered with the <
code>SyncFactory</
code>.
0N/A<
h3><
a name="resolving">4.0 Resolving Synchronization Conflicts</
h3>
0N/AThe interface <
code>SyncResolver</
code> provides a way for an application to
0N/Adecide manually what to do when a conflict occurs. When the <
code>CachedRowSet</
code>
0N/Amethod <
code>acceptChanges</
code> finishes and has detected one or more conflicts,
0N/Ait throws a <
code>SyncProviderException</
code> object. An application can
0N/Acatch the exception and
0N/Ahave it retrieve a <
code>SyncResolver</
code> object by calling the method
0N/AA <
code>SyncResolver</
code> object, which is a special kind of
0N/A<
code>CachedRowSet</
code> object or
0N/Aa <
code>JdbcRowSet</
code> object that has implemented the <
code>SyncResolver</
code>
0N/Ainterface, examines the conflicts row by row. It is a duplicate of the
0N/A<
code>RowSet</
code> object being synchronized except that it contains only the data
0N/Afrom the data source this is causing a conflict. All of the other column values are
0N/Aset to <
code>null</
code>. To navigate from one conflict value to another, a
0N/A<
code>SyncResolver</
code> object provides the methods <
code>nextConflict</
code> and
0N/A<
code>previousConflict</
code>.
0N/AThe <
code>SyncResolver</
code> interface also
0N/Aprovides methods for doing the following:
0N/A <
LI>finding out whether the conflict involved an update, a delete, or an insert
0N/A <
LI>getting the value in the data source that caused the conflict
0N/A <
LI>setting the value that should be in the data source if it needs to be changed
0N/A or setting the value that should be in the <
code>RowSet</
code> object if it needs
0N/AWhen the <
code>CachedRowSet</
code> method <
code>acceptChanges</
code> is called, it
0N/Adelegates to the <
code>RowSet</
code> object's <
code>SyncProvider</
code> object.
0N/AHow the writer provided by that <
code>SyncProvider</
code> object is implemented
0N/Adetermines what level (grade) of checking for conflicts will be done. After all
0N/Achecking for conflicts is completed and one or more conflicts has been found, the method
0N/A<
code>acceptChanges</
code> throws a <
code>SyncProviderException</
code> object. The
0N/Aapplication can catch the exception and use it to obtain a <
code>SyncResolver</
code> object.
0N/AThe application can then use <
code>SyncResolver</
code> methods to get information
0N/Aabout each conflict and decide what to do. If the application logic or the user
0N/Adecides that a value in the <
code>RowSet</
code> object should be the one to
0N/Apersist, the application or user can overwrite the data source value with it.
0N/AThe comment for the <
code>SyncResolver</
code> interface has more detail.
0N/A<
a name="relspec"><
h3>5.0 Related Specifications</
h3>
0N/A<
a name="reldocs"><
h3>6.0 Related Documentation</
h3>