3.0 SyncProvider Implementer's Guide
3.1 Requirements
A compliant SyncProvider
implementation that is fully pluggable
into the SyncFactory
must extend and implement all
abstract methods in the SyncProvider
class. In addition, an implementation must determine the
grade, locking and updatable view capabilities defined in the
SyncProvider
class definition. One or more of the
SyncProvider
description criteria must be supported. It
is expected that vendor implementations will offer a range of grade, locking, and
updatable view capabilities.
Furthermore, the SyncProvider
naming convention must be followed as
detailed in the SyncProvider
class
description.
3.2 Grades
JSR 114 defines a set of grades to describe the quality of synchronization
a SyncProvider
object can offer a disconnected RowSet
object. These grades are listed from the lowest quality of service to the highest.
- GRADE_NONE - No synchronization with the originating data source is
provided. A
SyncProvider
implementation returning this grade will simply
attempt to write any data that has changed in the RowSet
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
RIXMLProvider
is implemented with this grade.
- GRADE_CHECK_MODIFIED_AT_COMMIT - A low grade of optimistic synchronization.
A
SyncProvider
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 RowSet
object. If there are no conflicts, changes in the RowSet
object will be
written to the data source. If there are conflicts, no changes are written.
The RIOptimisticProvider
implementation uses this grade.
- GRADE_CHECK_ALL_AT_COMMIT - A high grade of optimistic synchronization.
A
SyncProvider
implementation returning this grade
will check all rows, including rows that have not changed in the disconnected
RowSet
object. In this way, any changes to rows in the underlying
data source will be reflected in the disconnected RowSet
object
when the synchronization finishes successfully.
- GRADE_LOCK_WHEN_MODIFIED - A pessimistic grade of synchronization.
SyncProvider
implementations returning this grade will lock
the row in the originating data source that corresponds to the row being changed
in the RowSet
object to reduce the possibility of other
processes modifying the same data in the data source.
- GRADE_LOCK_WHEN_LOADED - A higher pessimistic synchronization grade.
A
SyncProvider
implementation returning this grade will lock
the entire view and/or table affected by the original query used to
populate a RowSet
object.
3.3 Locks
JSR 114 defines a set of constants that specify whether any locks have been
placed on a RowSet
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 RowSet
object is disconnected from the data source.
These constants should 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 RowSet
object is disconnected
from its data source.
The grades GRADE_LOCK_WHEN_MODIFIED
and
GRADE_LOCK_WHEN_LOADED
allow a disconnected RowSet
object
to have a fine-grained control over the degree of locking.
- DATASOURCE_NO_LOCK - No locks remain on the originating data source.
This is the default lock setting for all
SyncProvider
implementations
unless otherwise directed by a RowSet
object.
- DATASOURCE_ROW_LOCK - A lock is placed on the rows that are touched by
the original SQL query used to populate the
RowSet
object.
- DATASOURCE_TABLE_LOCK - A lock is placed on all tables that are touched
by the query that was used to populate the
RowSet
object.
- DATASOURCE_DB_LOCK
A lock is placed on the entire data source that is used by the
RowSet
object.
3.4 Updatable Views
A RowSet
object may be populated with data from an SQL VIEW
.
The following constants indicate whether a SyncProvider
object can
update data in the table or tables from which the VIEW
was derived.
- UPDATABLE_VIEW_SYNC
Indicates that a
SyncProvider
implementation supports synchronization
to the table or tables from which the SQL VIEW
used to populate a
a RowSet
object is derived.
- NONUPDATABLE_VIEW_SYNC
Indicates that a
SyncProvider
implementation does not support
synchronization to the table or tables from which the SQL VIEW
used to populate a RowSet
object is derived.
3.5 Usage of SyncProvider
Grading and Locking
In the example below, the reference CachedRowSetImpl implementation
reconfigures its current SyncProvider object by calling the
setSyncProvider method.
CachedRowSetImpl crs = new CachedRowSetImpl();
crs.setSyncProvider("com.foo.bar.HASyncProvider");
An application can retrieve the SyncProvider object currently in use
by a disconnected RowSet
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.
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
// RowSet
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;
It is also possible using the static utility method in the
SyncFactory
class to determine the list of SyncProvider
implementations currently registered with the SyncFactory
.
Enumeration e = SyncFactory.getRegisteredProviders();
The interface SyncResolver
provides a way for an application to
decide manually what to do when a conflict occurs. When the CachedRowSet
method acceptChanges
finishes and has detected one or more conflicts,
it throws a SyncProviderException
object. An application can
catch the exception and
have it retrieve a SyncResolver
object by calling the method
SyncProviderException.getSyncResolver()
.
A SyncResolver
object, which is a special kind of
CachedRowSet
object or
a JdbcRowSet
object that has implemented the SyncResolver
interface, examines the conflicts row by row. It is a duplicate of the
RowSet
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 null
. To navigate from one conflict value to another, a
SyncResolver
object provides the methods nextConflict
and
previousConflict
.
The SyncResolver
interface also
provides methods for doing the following:
- finding out whether the conflict involved an update, a delete, or an insert
- getting the value in the data source that caused the conflict
- 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
RowSet
object if it needs
to be changed
When the CachedRowSet
method acceptChanges
is called, it
delegates to the RowSet
object's SyncProvider
object.
How the writer provided by that SyncProvider
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
acceptChanges
throws a SyncProviderException
object. The
application can catch the exception and use it to obtain a SyncResolver
object.
The application can then use SyncResolver
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 RowSet
object should be the one to
persist, the application or user can overwrite the data source value with it.
The comment for the SyncResolver
interface has more detail.
5.0 Related Specifications
6.0 Related Documentation
Copyright 2003 Sun Microsystems, Inc. All rights reserved