RowSetMigration

Migrating from visualweb rowsets to standard rowsets

Review Page - use this page to add your comments for this spec.

DavidVanCouvering

This is the page describing the functional changes and underlying design of migrating the visualweb project's use of a private implementation of rowsets to using the reference implementation that comes with the Java Runtime Environment.

This task is tracked by Issue 94906 in Issuezilla

Contents

Problem description

Today the Visual Web project (VWP) uses a private extension of the standard Java rowset functionality. This is a problem because

  • It locks users in to the VWP implementation of row sets. This
 is against NetBean's overall principle of giving users flexibility
 and freedom through the use of standard and open technologies.
  • It means that NetBeans has to maintain its own implementation of
 rowsets, rather than take advantage of the existing Reference
 Implemenation provided by OpenJDK
  • The existing VWP implementation of rowsets can not be placed into
 open source without further legal review.
  • The existing VWP implementation of rowsets can not be compiled with
 JDK 6 because of changes to the underlying JDBC interfaces that
 occurred in JDBC 4, which ships with JDK 6.

Goal

Our goal is to migrate VWP to using the standard RowSet interfaces and the RowSet RI. This involves not only fixing VWP to use the standard; it also means somehow migrating or otherwise supporting existing VWP and Java Studio Creator customers who have built their applications using the proprietary VWP rowset implementation.

Use Cases

Deploying to a J2EE 1.4 container

  1. User creates a new Visual Web Project to be deployed to J2EE 1.4 container that uses J2SE 1.4.x (source level for container is 1.4)
  2. A dialog opens to alert the user to download the RowSet RI from the Plugin Center
  3. Project should open with badged node and red display name indicating missing references (the rowset jar)
  4. Once the user downloads and installs the RowSet RI plug-in then the project node badge will disappear and the

display name reverts to black text

  1. User can go ahead and deploy to J2EE 1.4 server

Deploying to other container that uses J2SE 1.5 or greater (source level of container is J2SE 1.5 or greater)

  1. no impact RowSet RI from J2SE 1.5 is used - user can go ahead and create visual web projects and deploy

Functional Changes

This section provides a description of the changes in VWP that are visible to the NetBeans user.

For each use case I will describe the existing behavior and what will change when we move to standard rowsets.

I will also address support of existing customers if that is relevant to the use case.

Binding a Table to a Visual Component

Current functionality

Today when a user drags a database table onto a visual component, a CachedRowSetDataProvider is created in the Page Bean for the page and an instance of com.sun.sql.rowset.CachedRowSetXImpl is added to the session bean as a private member variable.

This rowset is constructed where it is declared:

private CachedRowSetXImpl personRowSet = new CachedRowSetXImpl();

CachedRowSetXImpl is imported in the Session Bean as follows:

import com.sun.sql.rowset.CachedRowSetXImpl;

In the _init() method of the bean the rowset is initialized as follows:

personRowSet.setDataSourceName("java:comp/env/jdbc/TravelPack");
personRowSet.setCommand("SELECT * FROM TRAVEL.PERSON");
personRowSet.setTableName("PERSON");

This rowset is also exposed as a property by defining a setter and getter for the rowset:

public CachedRowSetXImpl getPersonRowSet() {
    return personRowSet;
}

public void setPersonRowSet(CachedRowSetXImpl crsxi) {
    this.personRowSet = crsxi;
}

New functionality

The new functionality will be very similar, with some small but important changes

The import statement in the session bean will change to:

import com.sun.rowset.CachedRowSetImpl;

The declaration of the rowset in the Session Bean will change as follows:

private CachedRowSet personRowSet = CachedRowSetDataProvider.createCachedRowSet();
The
createCachedRowSet</tt> method of <tt>{CachedRowSetDataProvider
is a new public static method that would look like this:
public static CachedRowSet createCachedRowSet() {
  try {
    return new CachedRowSetImpl();
  } catch (SQLException e) {
    throw new RuntimeException(e);
  }
}
The reason this method exists is to catch and re-throw the SQLException as a RuntimeException. If we were to call the
CachedRowSetImpl
method directly where the variable is declared we would get a compilation error because the exception is not being handled.

We will need to import CachedRowSetDataProvider into the bean where the rowset is generated:

import com.sun.data.provider.impl.CachedRowSetDataProvider;

Finally, the property getter/setter pair for the rowset will also change:

public CachedRowSet getPersonRowSet() {
    return personRowSet;
}

public void setPersonRowSet(CachedRowSet crs) {
    this.personRowSet = crs;
}

NOTE that the type of the variable is not the implementation class but the interface. This is very important, as it by default requires any code that uses the rowset to stick with the standard interface methods. This is an important principle: we want our user code to be standards-compliant, and not make use of proprietary extensions, even if those extensions are part of the RI.

Support for existing users/migration of existing projects.

When an existing project is opened in NetBeans 6, we will detect this and mark the project as using the old rowsets. Depending on how our issues are resolved (see Issues below), the user may need to obtain the old rowset jar from the update center.

Any new rowsets created in this project will continue to use the old rowset classes.

Only new projects will use the RI rowset.

Non-visual rowsets

It is possible to create rowsets in the designer that are not bound (at least initially) to any visual component.

An example of this is the MaxTripRowSet that is defined as part of the InsertUpdateDelete tutorial.

To do this, you drag a table from a connected database to any of the Pages, Application Beans, Request Beans or Session Beans that are displayed in the project navigator while you are in design view.

When you do this, a new CachedRowSetDataProvider and an associated rowset are created in that element (with the exception that if you drag a table onto a Page, the rowset is created in the session bean, while the data provider is created on the page).

In all these cases the same basic code is generated as described above: an instance of the rowset is declared, a setter/getter pair is generated for it, and it is initialized in the _init() method for the given bean.

The same changes will be made as for when the rowset is created as part of a data binding: the type for the variable and the setter/getter pair will be CachedRowSet rather than CachedRowSetXImpl.


Impact

This section describes the impact of this change to other parts of organization.

QE

QE tests will need to be adjusted to use the standard rowset rather than our private implementation.

QE will need to test import of existing projects from NetBeans 5.5 and Creator 2 to make sure these existing projects can work with the RI of rowsets.

Documentation

We will need to update the documentation to reflect the use of the standard rowset interfaces.

We may need to update the migration guide to provide guidance for moving code that depends on CachedRowSetX extensions to work with the reference implementation. It's possible that we will choose to wait on this until we understand better how many people are using these extensions and the level of impact -- this documentation may not be necessary.

Tutorials and Samples

Tutorials and samples will need to be updated to reflect the use of the standard rowset interfaces and implementation.

Tasks

These are described in the main VisualWeb6TaskList

Issues

Support for updatable rowsets that are based on a join

There is one key piece of functionality in the Creator rowset which is not available in the RI: the ability to update and insert rows on a rowset whose command is a join of one or more tables. In the Creator rowset code, you can update the columns of the table returned by
rowset.getTableName()
. This is not possible in the rowset RI. There is general consensus that this is crucial functionality and we need to provide support for it. The question is, how?

Here are the various plans that have been proposed, in order of preference.

Plan A - get this to work with the RI

Rowsets based on a join in the RI appear to be not supported not by any particular code that disallows it but primarily by the fact that the underlying JDBC result set marks all columns as read-only when the query is a join.

Rowsets return their metadata as
RowSetMetaData
. For reasons that escape me, this class allows you to not only read but also modify the metadata. There is also a method {RowSet.setMetaData()} that allows you to set the metadata for a rowset.

With this in hand, it is potentially possible to "trick" the rowset to allow updates on the primary table by modifying the metadata to indicate the columns are updatable.

It is likely this will not work, but it's worth a shot, and will take a day to test out. I'll be reporting back at this space.

Plan B - have our code be an extension of the RI and add support for updatable rowsets there

Right now our rowset code is a copy then change of the RI. We could attempt to instead extend the RI with just the functionality we need to support updatable rowsets.

It is not clear that this will work -- it is possible that large chunks of code will need to be rewritten and will be more effort than is wortwhile.

The value of this is that it is much more clear that we can open source this solution, and also most of our code will rely on the reference implementation rather than be our own copy that we have to support. Bugfixes will be done in one place rather than two places, etc.

Plan C - open source the Creator rowset code and ship it with NetBeans

This is attractive because it will Just Work and no extra coding will be required. It is unattractive because we'd really like users to make use of the RI if we can.

Plan D - put the Creator rowset code on the update center

If for some reason we can't open source the Creator rowset code, we can put the binary on the update center and instruct users to get it there. This has a big usability impact and should be avoided if at all possible

Options that are explicitly off the table:

  • Do not support updatable rowsets based on joins
  • Get the RI to take back the changes needed for updatable rowsets based on joins (this wouldn't work anyway because we need to work with the older versions of the RI that are part of the JRE for Java 5 and Java 6).
Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo