JEP draft: Deprecate the RowSet API for Removal
Summary
Deprecate the RowSet API for future removal.
Motivation
The Java Platform provides JDBC for accessing and processing data stored in databases.
The core interfaces in JDBC include java.sql.Connection, java.sql.Statement, and java.sql.ResultSet. These interfaces are widely used by applications and frameworks.
JDBC also defines the javax.sql.RowSet interface, which provides a higher-level, JavaBeans-style abstraction over ResultSet. A RowSet is essentially a scrollable, serializable, and optionally disconnected tabular data container intended for use in GUI applications, distributed systems, and component frameworks.
The RowSet interface is supplemented by several related interfaces in the javax.sql package, along with interfaces and base classes in the javax.sql.rowset package for RowSet implementations. Collectively, these types are referred to in this JEP as the RowSet API.
The RowSet API was designed for web-tier and component-oriented programming models common in the late 1990s and early 2000s. It was never widely implemented or adopted.
RowSets are not widely used
RowSets were designed for application architectures that commonly exchanged tabular data directly between tiers and components. Java desktop clients, Java Server Pages (JSP) applications, Enterprise Java Beans (EJB)-based applications, and JavaBeans-style tools commonly manipulated tabular data directly.
RowSet types provided ResultSet-like containers that could be disconnected from the database and serialized. They also supported features such as listeners, filtering, joins, and synchronization back to the data source. A disconnected container such as CachedRowSet was intended to allow applications to:
- fetch data while a JDBC connection was available,
- release the connection quickly,
- pass the data to another layer or component,
- manipulate data without holding database resources, and
- optionally write changes back later.
That design aligned with the web-tier and component-oriented programming models common in the late 1990s and early 2000s. It also reflected expectations that JSP tag libraries and visual builder tools would make extensive use of JavaBeans-style tabular components.
In practice, this programming model was not widely used by Java applications.
Modern applications typically use alternative approaches
The architectural assumptions behind RowSets are no longer common. Modern Java applications typically use:
- object-relational mapping frameworks, including Jakarta Persistence and Hibernate,
- type-safe SQL libraries such as jOOQ,
- data-access frameworks including Spring JDBC and MyBatis,
- service-oriented architectures that exchange JSON, Protocol Buffers (protobuf), or domain-specific
Data Transfer Objects (DTOs) rather than
RowSetinstances, or - non-relational data APIs, such as the MongoDB Java Driver, where JDBC is not the relevant abstraction.
Applications that require disconnected data, pagination, data binding, or optimistic updates typically use these approaches instead of the RowSet API.
Ecosystem support and usage have declined
There appears to be little evidence that new applications are being developed using the RowSet API, and relatively little evidence of substantial ongoing use in existing applications.
Informal surveys of open-source code bases reveal relatively few active usages beyond very old examples, compatibility code, and legacy documentation. Public discussion and ecosystem activity related to the API appear limited. For example, Stack Overflow contains relatively few questions about RowSets given the age of the feature, and there appears to be limited ongoing community discussion of the API.
The RowSet interface was added in Java 1.4, and the javax.sql.rowset package was added in Java 5.0. The JDK has received very few bug reports or enhancement requests related to the RowSet API since then. There appears to be little interest in further evolution of the API.
Beyond the implementation included in the JDK, relatively few third-party implementations and integrations were created for the RowSet specification, and most have since been deprecated or removed:
-
Oracle RowSets was deprecated in Oracle Database 12c Release 2 (12.2) in 2017
-
The WebLogic RowSets implementation was deprecated in WebLogic Server 12.1.2 in 2013
-
NetBeans Visual Web Pack, which included RowSet-related tooling, was removed in NetBeans 6.8 in 2009
This decline in vendor support is consistent with the limited adoption and ecosystem activity surrounding the RowSet API.
Retaining RowSets imposes ongoing costs
Even an infrequently used module imposes ongoing costs. The costs to the Java Platform include specification, implementation, testing, compatibility surface, and documentation, all of which require ongoing maintenance. The JDK also includes a RowSet test suite, even though only part of the API can be exercised without integration with an external database.
In addition, there are costs imposed on vendors who provide implementations of the JDBC API. Even when they do not provide a RowSet implementation, RowSets remain part of the JDBC specifications and must still be considered during ongoing design, implementation, and compatibility work.
Removing RowSets would likely have little impact on most Java developers while reducing long-term maintenance obligations within the Java ecosystem. Deprecating the RowSet API for future removal should therefore have low impact.
In summary, there appears to be little interest in using the RowSet API in new Java applications. The API reflects programming models and architectural assumptions that are no longer common in modern Java application development.
Description
In JDK xx, we will:
-
Deprecate, for removal, the following interfaces in the
javax.sqlpackage:javax.sql.RowSetjavax.sql.RowSetEventjavax.sql.RowSetInternaljavax.sql.RowSetMetaDatajavax.sql.RowSetReaderjavax.sql.RowSetWriter
-
Deprecate, for removal, all interfaces and classes in the
javax.sql.rowset,javax.sql.rowset.serial, andjavax.sql.rowset.spipackages. -
Add deprecation notices to the package declarations and to the module declaration of the enclosing module,
java.sql.rowset.
Alternatives
Leave the RowSet API in Place
One alternative is to leave the RowSet API in place, as has been the case for many years. That would continue to impose an ongoing quality risk and maintenance burden. Those continuing costs are not justified by the minimal value that this essentially unused mechanism now brings to the platform.
Move the RowSet API to its own project
Another possibility is to move the RowSet API to its own project. This would most likely involve contributing the RowSet API specifications, source code, and tests to a foundation such as Eclipse or Apache, which has been done previously for JDO and Java EE (Jakarta EE). This would be followed by removal of the API from the Java Platform. To date, we are unaware of anyone interested in undertaking such a project.
Risks and Assumptions
It is possible that some products use the RowSet classes in the javax.sql.rowset package and would therefore be impacted if those classes were removed. However, given the limited ecosystem activity, bug reports, and enhancement requests related to RowSets, it appears unlikely that these classes are widely used in current applications.
It is also possible that some projects use CachedRowSet in testing scenarios to mock a ResultSet. Projects that rely on this approach may need to adopt alternatives, such as developing custom mocks or embedding a CachedRowSet implementation into their test infrastructure.
Applications that depend on the RowSet API can continue to use existing supported JDK releases while migrating away from the API.