Path: blob/master/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package-info.java
40948 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/**26* The standard classes and interfaces that a third party vendor has to27* use in its implementation of a synchronization provider. These classes and28* interfaces are referred to as the Service Provider Interface (SPI). To make it possible29* for a {@code RowSet} object to use an implementation, the vendor must register30* it with the {@code SyncFactory} singleton. (See the class comment for31* {@code SyncProvider} for a full explanation of the registration process and32* the naming convention to be used.)33*34* <h2>Table of Contents</h2>35* <ul>36* <li><a href="#pkgspec">1.0 Package Specification</a>37* <li><a href="#arch">2.0 Service Provider Architecture</a>38* <li><a href="#impl">3.0 Implementer's Guide</a>39* <li><a href="#resolving">4.0 Resolving Synchronization Conflicts</a>40* <li><a href="#relspec">5.0 Related Specifications</a>41* <li><a href="#reldocs">6.0 Related Documentation</a>42* </ul>43*44* <h3><a id="pkgspec">1.0 Package Specification</a></h3>45* <P>46* The following classes and interfaces make up the {@code javax.sql.rowset.spi}47* package:48* <UL>49* <LI>{@code SyncFactory}50* <LI>{@code SyncProvider}51* <LI>{@code SyncFactoryException}52* <LI>{@code SyncProviderException}53* <LI>{@code SyncResolver}54* <LI>{@code XmlReader}55* <LI>{@code XmlWriter}56* <LI>{@code TransactionalWriter}57* </UL>58* The following interfaces, in the {@code javax.sql} package, are also part of the SPI:59* <UL>60* <LI>{@code RowSetReader}61* <LI>{@code RowSetWriter}62* </UL>63* <P>64* A {@code SyncProvider} implementation provides a disconnected {@code RowSet}65* object with the mechanisms for reading data into it and for writing data that has been66* modified in it67* back to the underlying data source. A <i>reader</i>, a {@code RowSetReader} or68* {@code XMLReader} object, reads data into a {@code RowSet} object when the69* {@code CachedRowSet} methods {@code execute} or {@code populate}70* are called. A <i>writer</i>, a {@code RowSetWriter} or {@code XMLWriter}71* object, writes changes back to the underlying data source when the72* {@code CachedRowSet} method {@code acceptChanges} is called.73* <P>74* The process of writing changes in a {@code RowSet} object to its data source75* is known as <i>synchronization</i>. The {@code SyncProvider} implementation that a76* {@code RowSet} object is using determines the level of synchronization that the77* {@code RowSet} object's writer uses. The various levels of synchronization are78* referred to as <i>grades</i>.79* <P>80* The lower grades of synchronization are81* known as <i>optimistic</i> concurrency levels because they optimistically82* assume that there will be no conflicts or very few conflicts. A conflict exists when83* the same data modified in the {@code RowSet} object has also been modified84* in the data source. Using the optimistic concurrency model means that if there85* is a conflict, modifications to either the data source or the {@code RowSet}86* object will be lost.87* <P>88* Higher grades of synchronization are called <i>pessimistic</i> because they assume89* that others will be accessing the data source and making modifications. These90* grades set varying levels of locks to increase the chances that no conflicts91* occur.92* <P>93* The lowest level of synchronization is simply writing any changes made to the94* {@code RowSet} object to its underlying data source. The writer does95* nothing to check for conflicts.96* If there is a conflict and the data97* source values are overwritten, the changes other parties have made by to the data98* source are lost.99* <P>100* The {@code RIXMLProvider} implementation uses the lowest level101* of synchronization and just writes {@code RowSet} changes to the data source.102*103* <P>104* For the next level up, the105* writer checks to see if there are any conflicts, and if there are,106* it does not write anything to the data source. The problem with this concurrency107* level is that if another party has modified the corresponding data in the data source108* since the {@code RowSet} object got its data,109* the changes made to the {@code RowSet} object are lost. The110* {@code RIOptimisticProvider} implementation uses this level of synchronization.111* <P>112* At higher levels of synchronization, referred to as pessimistic concurrency,113* the writer take steps to avoid conflicts by setting locks. Setting locks114* can vary from setting a lock on a single row to setting a lock on a table115* or the entire data source. The level of synchronization is therefore a tradeoff116* between the ability of users to access the data source concurrently and the ability117* of the writer to keep the data in the {@code RowSet} object and its data source118* synchronized.119* <P>120* It is a requirement that all disconnected {@code RowSet} objects121* ({@code CachedRowSet}, {@code FilteredRowSet}, {@code JoinRowSet},122* and {@code WebRowSet} objects) obtain their {@code SyncProvider} objects123* from the {@code SyncFactory} mechanism.124* <P>125* The reference implementation (RI) provides two synchronization providers.126* <UL>127* <LI><b>{@code RIOptimisticProvider}</b> <br>128* The default provider that the {@code SyncFactory} instance will129* supply to a disconnected {@code RowSet} object when no provider130* implementation is specified.<BR>131* This synchronization provider uses an optimistic concurrency model,132* assuming that there will be few conflicts among users133* who are accessing the same data in a database. It avoids134* using locks; rather, it checks to see if there is a conflict135* before trying to synchronize the {@code RowSet} object and the136* data source. If there is a conflict, it does nothing, meaning that137* changes to the {@code RowSet} object are not persisted to the data138* source.139* <LI><B>{@code RIXMLProvider}</B> <BR>140* A synchronization provider that can be used with a141* {@code WebRowSet} object, which is a rowset that can be written142* in XML format or read from XML format. The143* {@code RIXMLProvider} implementation does no checking at all for144* conflicts and simply writes any updated data in the145* {@code WebRowSet} object to the underlying data source.146* {@code WebRowSet} objects use this provider when they are147* dealing with XML data.148* </UL>149*150* These {@code SyncProvider} implementations151* are bundled with the reference implementation, which makes them always available to152* {@code RowSet} implementations.153* {@code SyncProvider} implementations make themselves available by being154* registered with the {@code SyncFactory} singleton. When a {@code RowSet}155* object requests a provider, by specifying it in the constructor or as an argument to the156* {@code CachedRowSet} method {@code setSyncProvider},157* the {@code SyncFactory} singleton158* checks to see if the requested provider has been registered with it.159* If it has, the {@code SyncFactory} creates an instance of it and passes it to the160* requesting {@code RowSet} object.161* If the {@code SyncProvider} implementation that is specified has not been registered,162* the {@code SyncFactory} singleton causes a {@code SyncFactoryException} object163* to be thrown. If no provider is specified,164* the {@code SyncFactory} singleton will create an instance of the default165* provider implementation, {@code RIOptimisticProvider},166* and pass it to the requesting {@code RowSet} object.167*168* <P>169* If a {@code WebRowSet} object does not specify a provider in its constructor, the170* {@code SyncFactory} will give it an instance of {@code RIOptimisticProvider}.171* However, the constructor for {@code WebRowSet} is implemented to set the provider172* to the {@code RIXMLProvider}, which reads and writes a {@code RowSet} object173* in XML format.174* <P>175* See the <a href="SyncProvider.html">SyncProvider</a> class176* specification for further details.177* <p>178* Vendors may develop a {@code SyncProvider} implementation with any one of the possible179* levels of synchronization, thus giving {@code RowSet} objects a choice of180* synchronization mechanisms.181*182* <h3><a id="arch">2.0 Service Provider Interface Architecture</a></h3>183* <b>2.1 Overview</b>184* <p>185* The Service Provider Interface provides a pluggable mechanism by which186* {@code SyncProvider} implementations can be registered and then generated when187* required. The lazy reference mechanism employed by the {@code SyncFactory} limits188* unnecessary resource consumption by not creating an instance until it is189* required by a disconnected190* {@code RowSet} object. The {@code SyncFactory} class also provides191* a standard API to configure logging options and streams that <b>may</b> be provided192* by a particular {@code SyncProvider} implementation.193* <p>194* <b>2.2 Registering with the {@code SyncFactory}</b>195* <p>196* A third party {@code SyncProvider} implementation must be registered with the197* {@code SyncFactory} in order for a disconnected {@code RowSet} object198* to obtain it and thereby use its {@code javax.sql.RowSetReader} and199* {@code javax.sql.RowSetWriter}200* implementations. The following registration mechanisms are available to all201* {@code SyncProvider} implementations:202* <ul>203* <li><b>System properties</b> - Properties set at the command line. These204* properties are set at run time and apply system-wide per invocation of the Java205* application. See the section <a href="#reldocs">"Related Documentation"</a>206* further related information.207*208* <li><b>Property Files</b> - Properties specified in a standard property file.209* This can be specified using a System Property or by modifying a standard210* property file located in the platform run-time. The211* reference implementation of this technology includes a standard property212* file than can be edited to add additional {@code SyncProvider} objects.213*214* <li><b>JNDI Context</b> - Available providers can be registered on a JNDI215* context. The {@code SyncFactory} will attempt to load {@code SyncProvider}216* objects bound to the context and register them with the factory. This217* context must be supplied to the {@code SyncFactory} for the mechanism to218* function correctly.219* </ul>220* <p>221* Details on how to specify the system properties or properties in a property file222* and how to configure the JNDI Context are explained in detail in the223* <a href="SyncFactory.html">{@code SyncFactory}</a> class description.224* <p>225* <b>2.3 SyncFactory Provider Instance Generation Policies</b>226* <p>227* The {@code SyncFactory} generates a requested {@code SyncProvider}228* object if the provider has been correctly registered. The229* following policies are adhered to when either a disconnected {@code RowSet} object230* is instantiated with a specified {@code SyncProvider} implementation or is231* reconfigured at runtime with an alternative {@code SyncProvider} object.232* <ul>233* <li> If a {@code SyncProvider} object is specified and the {@code SyncFactory}234* contains <i>no</i> reference to the provider, a {@code SyncFactoryException} is235* thrown.236*237* <li> If a {@code SyncProvider} object is specified and the {@code SyncFactory}238* contains a reference to the provider, the requested provider is supplied.239*240* <li> If no {@code SyncProvider} object is specified, the reference241* implementation provider {@code RIOptimisticProvider} is supplied.242* </ul>243* <p>244* These policies are explored in more detail in the <a href="SyncFactory.html">245* {@code SyncFactory}</a> class.246*247* <h3><a id="impl">3.0 SyncProvider Implementer's Guide</a></h3>248*249* <b>3.1 Requirements</b>250* <p>251* A compliant {@code SyncProvider} implementation that is fully pluggable252* into the {@code SyncFactory} <b>must</b> extend and implement all253* abstract methods in the <a href="SyncProvider.html">{@code SyncProvider}</a>254* class. In addition, an implementation <b>must</b> determine the255* grade, locking and updatable view capabilities defined in the256* {@code SyncProvider} class definition. One or more of the257* {@code SyncProvider} description criteria <b>must</b> be supported. It258* is expected that vendor implementations will offer a range of grade, locking, and259* updatable view capabilities.260* <p>261* Furthermore, the {@code SyncProvider} naming convention <b>must</b> be followed as262* detailed in the <a href="SyncProvider.html">{@code SyncProvider}</a> class263* description.264* <p>265* <b>3.2 Grades</b>266* <p>267* JSR 114 defines a set of grades to describe the quality of synchronization268* a {@code SyncProvider} object can offer a disconnected {@code RowSet}269* object. These grades are listed from the lowest quality of service to the highest.270* <ul>271* <li><b>GRADE_NONE</b> - No synchronization with the originating data source is272* provided. A {@code SyncProvider} implementation returning this grade will simply273* attempt to write any data that has changed in the {@code RowSet} object to the274*underlying data source, overwriting whatever is there. No attempt is made to compare275* original values with current values to see if there is a conflict. The276* {@code RIXMLProvider} is implemented with this grade.277*278* <li><b>GRADE_CHECK_MODIFIED_AT_COMMIT</b> - A low grade of optimistic synchronization.279* A {@code SyncProvider} implementation returning this grade280* will check for conflicts in rows that have changed between the last synchronization281* and the current synchronization under way. Any changes in the originating data source282* that have been modified will not be reflected in the disconnected {@code RowSet}283* object. If there are no conflicts, changes in the {@code RowSet} object will be284* written to the data source. If there are conflicts, no changes are written.285* The {@code RIOptimisticProvider} implementation uses this grade.286*287* <li><b>GRADE_CHECK_ALL_AT_COMMIT</b> - A high grade of optimistic synchronization.288* A {@code SyncProvider} implementation returning this grade289* will check all rows, including rows that have not changed in the disconnected290* {@code RowSet} object. In this way, any changes to rows in the underlying291* data source will be reflected in the disconnected {@code RowSet} object292* when the synchronization finishes successfully.293*294* <li><b>GRADE_LOCK_WHEN_MODIFIED</b> - A pessimistic grade of synchronization.295* {@code SyncProvider} implementations returning this grade will lock296* the row in the originating data source that corresponds to the row being changed297* in the {@code RowSet} object to reduce the possibility of other298* processes modifying the same data in the data source.299*300* <li><b>GRADE_LOCK_WHEN_LOADED</b> - A higher pessimistic synchronization grade.301* A {@code SyncProvider} implementation returning this grade will lock302* the entire view and/or table affected by the original query used to303* populate a {@code RowSet} object.304* </ul>305* <p>306* <b>3.3 Locks</b>307* <p>308* JSR 114 defines a set of constants that specify whether any locks have been309* placed on a {@code RowSet} object's underlying data source and, if so,310* on which constructs the locks are placed. These locks will remain on the data311* source while the {@code RowSet} object is disconnected from the data source.312* <P>313* These constants <b>should</b> be considered complementary to the314* grade constants. The default setting for the majority of grade settings requires315* that no data source locks remain when a {@code RowSet} object is disconnected316* from its data source.317* The grades {@code GRADE_LOCK_WHEN_MODIFIED} and318* {@code GRADE_LOCK_WHEN_LOADED} allow a disconnected {@code RowSet} object319* to have a fine-grained control over the degree of locking.320* <ul>321* <li><b>DATASOURCE_NO_LOCK</b> - No locks remain on the originating data source.322* This is the default lock setting for all {@code SyncProvider} implementations323* unless otherwise directed by a {@code RowSet} object.324*325* <li><b>DATASOURCE_ROW_LOCK</b> - A lock is placed on the rows that are touched by326* the original SQL query used to populate the {@code RowSet} object.327*328* <li><b>DATASOURCE_TABLE_LOCK</b> - A lock is placed on all tables that are touched329* by the query that was used to populate the {@code RowSet} object.330*331* <li><b>DATASOURCE_DB_LOCK</b>332* A lock is placed on the entire data source that is used by the {@code RowSet}333* object.334* </ul>335* <p>336* <b>3.4 Updatable Views</b>337* <p>338* A {@code RowSet} object may be populated with data from an SQL {@code VIEW}.339* The following constants indicate whether a {@code SyncProvider} object can340* update data in the table or tables from which the {@code VIEW} was derived.341* <ul>342* <li><b>UPDATABLE_VIEW_SYNC</b>343* Indicates that a {@code SyncProvider} implementation supports synchronization344* to the table or tables from which the SQL {@code VIEW} used to populate345* a {@code RowSet} object is derived.346*347* <li><b>NONUPDATABLE_VIEW_SYNC</b>348* Indicates that a {@code SyncProvider} implementation does <b>not</b> support349* synchronization to the table or tables from which the SQL {@code VIEW}350* used to populate a {@code RowSet} object is derived.351* </ul>352* <p>353* <b>3.5 Usage of {@code SyncProvider} Grading and Locking</b>354* <p>355* In the example below, the reference {@code CachedRowSetImpl} implementation356* reconfigures its current {@code SyncProvider} object by calling the357* {@code setSyncProvider} method.<br>358*359* <PRE>360* CachedRowSetImpl crs = new CachedRowSetImpl();361* crs.setSyncProvider("com.foo.bar.HASyncProvider");362* </PRE>363* An application can retrieve the {@code SyncProvider} object currently in use364* by a disconnected {@code RowSet} object. It can also retrieve the365* grade of synchronization with which the provider was implemented and the degree of366* locking currently in use. In addition, an application has the flexibility to set367* the degree of locking to be used, which can increase the possibilities for successful368* synchronization. These operation are shown in the following code fragment.369* <PRE>370* SyncProvider sync = crs.getSyncProvider();371*372* switch (sync.getProviderGrade()) {373* case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT374* //A high grade of optimistic synchronization375* break;376* case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT377* //A low grade of optimistic synchronization378* break;379* case: SyncProvider.GRADE_LOCK_WHEN_LOADED380* // A pessimistic synchronization grade381* break;382* case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED383* // A pessimistic synchronization grade384* break;385* case: SyncProvider.GRADE_NONE386* // No synchronization with the originating data source provided387* break;388* }389*390* switch (sync.getDataSourceLock() {391* case: SyncProvider.DATASOURCE_DB_LOCK392* // A lock is placed on the entire datasource that is used by the393* // {@code RowSet} object394* break;395*396* case: SyncProvider.DATASOURCE_NO_LOCK397* // No locks remain on the originating data source.398* break;399*400* case: SyncProvider.DATASOURCE_ROW_LOCK401* // A lock is placed on the rows that are touched by the original402* // SQL statement used to populate403* // the RowSet object that is using the SyncProvider404* break;405*406* case: DATASOURCE_TABLE_LOCK407* // A lock is placed on all tables that are touched by the original408* // SQL statement used to populated409* // the RowSet object that is using the SyncProvider410* break;411*412* </PRE>413* It is also possible using the static utility method in the414* {@code SyncFactory} class to determine the list of {@code SyncProvider}415* implementations currently registered with the {@code SyncFactory}.416*417* <pre>418* Enumeration e = SyncFactory.getRegisteredProviders();419* </pre>420*421*422* <h3><a id="resolving">4.0 Resolving Synchronization Conflicts</a></h3>423*424* The interface {@code SyncResolver} provides a way for an application to425* decide manually what to do when a conflict occurs. When the {@code CachedRowSet}426* method {@code acceptChanges} finishes and has detected one or more conflicts,427* it throws a {@code SyncProviderException} object. An application can428* catch the exception and429* have it retrieve a {@code SyncResolver} object by calling the method430* {@code SyncProviderException.getSyncResolver()}.431* <P>432* A {@code SyncResolver} object, which is a special kind of433* {@code CachedRowSet} object or434* a {@code JdbcRowSet} object that has implemented the {@code SyncResolver}435* interface, examines the conflicts row by row. It is a duplicate of the436* {@code RowSet} object being synchronized except that it contains only the data437* from the data source this is causing a conflict. All of the other column values are438* set to {@code null}. To navigate from one conflict value to another, a439* {@code SyncResolver} object provides the methods {@code nextConflict} and440* {@code previousConflict}.441* <P>442* The {@code SyncResolver} interface also443* provides methods for doing the following:444* <UL>445* <LI>finding out whether the conflict involved an update, a delete, or an insert446* <LI>getting the value in the data source that caused the conflict447* <LI>setting the value that should be in the data source if it needs to be changed448* or setting the value that should be in the {@code RowSet} object if it needs449* to be changed450* </UL>451* <P>452* When the {@code CachedRowSet} method {@code acceptChanges} is called, it453* delegates to the {@code RowSet} object's {@code SyncProvider} object.454* How the writer provided by that {@code SyncProvider} object is implemented455* determines what level (grade) of checking for conflicts will be done. After all456* checking for conflicts is completed and one or more conflicts has been found, the method457* {@code acceptChanges} throws a {@code SyncProviderException} object. The458* application can catch the exception and use it to obtain a {@code SyncResolver} object.459* <P>460* The application can then use {@code SyncResolver} methods to get information461* about each conflict and decide what to do. If the application logic or the user462* decides that a value in the {@code RowSet} object should be the one to463* persist, the application or user can overwrite the data source value with it.464* <P>465* The comment for the {@code SyncResolver} interface has more detail.466*467* <h3><a id="relspec">5.0 Related Specifications</a></h3>468* <ul>469* <li><a href="http://docs.oracle.com/javase/jndi/tutorial/index.html">JNDI</a>470* <li><a href="{@docRoot}/java.logging/java/util/logging/package-summary.html">Java Logging471* APIs</a>472* </ul>473* <h3><a id="reldocs">6.0 Related Documentation</a></h3>474* <ul>475* <li><a href="http://docs.oracle.com/javase/tutorial/jdbc/">DataSource for JDBC476* Connections</a>477* </ul>478*/479package javax.sql.rowset.spi;480481482