Creating a distributed database application using DataSetData

Database application development is a feature of JBuilder Professional and Enterprise. Distributed application development is a feature of JBuilder Enterprise.

The DataSetData.jpr sample project in the /samples/DataExpress/StreamableDataSets directory of your JBuilder installation contains a completed distributed database application using Java Remote Method Invocation (RMI) and DataSetData. It includes a server application that will take data from the sample JDataStore employee table and send the data via RMI in the form of DataSetData. A DataSetData is used to pass data as an argument to an RMI method or as an input stream to a Java servlet.

A client application will communicate with the server through a custom Provider and a custom Resolver. The client application displays the data in a table. Editing performed on the client can be saved using a JdbNavToolBar's Save button.

For more information on developing distributed applications, see the Distributed Application Developer's Guide.

For more information on writing custom providers, see "Writing a custom data provider". For information on writing or customizing a resolver, see "Customizing the default resolver logic".

See the file DataSetData.html in the /samples/DataExpress/StreamableDataSets/ directory for updated information on this sample application.


Understanding the sample distributed database application (using Java RMI and DataSetData)

The sample project, found in /samples/DataExpress/StreamableDataSets/DataSetData.jpr, demonstrates the use of the DataExpress DataSetData class to build a distributed database application. In addition to using DataSetData objects to pass database data between an RMI server and client, this sample illustrates the use of a custom DataSet Provider and Resolver. The sample application contains the following files:

Setting up the sample application

To run the sample application, you need to

  1. Open this application in JBuilder by selecting File|Open and browsing to /samples/DataExpress/StreamableDataSets/DataSetData.jpr.
  2. Select Project|Project Properties to view the properties of this project. Set the following options;

  3. Start the RMI registry by selecting Tools|RMI Registry from JBuilder. The registry is toggled on and off from the Tools menu.
  4. Select the file DataServerApp in the project pane. Right-click the file, and select Run to start the RMI server.
  5. Select the file ClientApp in the project pane. Right-click the file, and select Run to start the RMI client.
  6. Edit the data in the ClientApp's table, and press either the Save Changes button on the toolbar (to save the changes back to the server) or the Refresh button on the toolbar (to reload the data from the server). Each time data is saved or refreshed, the middle-tier request counter increases.

What is going on?

These steps enable the DataServerApp to register itself as an RMI server. DataServerApp will respond to two RMI client requests: provideEmployeeData and resolveEmployeeChanges, as defined in the RMI remote interface EmployeeApi.java.

The ClientApp file is a frame with a JdbTable and a JdbNavToolBar for displaying data in a DataExpress DataSet. Data is provided to the DataSet via a custom Provider, ClientProvider.java, and data is saved to the source via a custom Resolver, ClientResolver.java. ClientProvider.java fills its table data by invoking the DataServerApp provideEmployeeData() remote method via RMI. DataServerApp subsequently queries data from a table on a JDBC database server into a DataSet. It then extracts the data from the DataSet into a DataSetData object and sends it back to ClientProvider via RMI. ClientProvider then loads the data in the DataSetData object into the ClientApp DataSet, and the data appears in the table.

When it is time to resolve changes made in the table back to the database, the ClientApp DataSet "custom Resolver", ClientResolver.java, extracts (only) the changes that need to be sent to the database server into a DataSetData object. ClientResolver then invokes the DataServerApp resolveEmployeeChanges() remote method via RMI, passing it the DataSetData object containing the necessary updates as the parameter.

DataServerApp then uses DataExpress to resolves the changes back to the database server. If an error occurs (due to a business rule or data constraint violation, for example) DataServerApp packages rows which could not be saved back to the database into a DataSetData object and returns it back to ClientResolver. ClientResolver then extracts the unresolvable rows in the DataSetData object into the ClientApp table, allowing the problematic rows to be corrected and resolved back to the server again.

Note that DataServerApp is the "middle-tier" of the application. It can enforce its own business rules and constraints between the database server and the client. And of course, it could provide any number of additional remotely accessibly methods for implementing business logic or application-specific tasks.

Passing metadata by DataSetData

The metadata passed in a DataSetData object is very limited. Only the following Column properties are passed:

Other column properties that a server needs to pass to a client application, should be passed as an array of Columns via RMI. The Column object itself is serializable, so a client application could be designed to get these column properties before it needed the data. The columns should be added as persistent columns before the DataSetData is loaded.

Deploying the application on 3-tiers

To deploy the application on 3-tiers,
  1. Select DataServerApp.java in the project pane. Modify the database connection URL in the constructor to point to a remote database connection to which you have access. The database is the back end, or third tier.
  2. Select Project|Make Project to recompile and update DataServerApp.class.
  3. Deploy DataServerApp.class to a remote machine to which you are connected. DataServerApp runs on the middle, or second, tier.

  4. Start the RMI Registry on the middle tier computer.

  5. Start DataServerApp on the middle tier.

    NOTE: Beginning with JDK 1.2, it is necessary to grant an RMI server special security rights in order for it to listen for and accept client RMI requests over a network. Typically, these rights are specified in a java security policy file defined by a special property, java.security.policy, passed by way of a command-line argument to the VM of the server. This is similar to the java.rmi.server.codebase property which must also be passed to the server's VM.A sample RMI security policy file which will allow an RMI client to connect to the server is included with this project in the file SampleRMI.policy.

    When starting DataServerApp on the middle-tier, make sure both the java.security.policy and java.rmi.server.codebase properties are set to the proper locations on the middle-tier machine.

  6. Double-click ClientFrame.java in the project pane of JBuilder to bring it into the content pane. Select the Design tab to invoke the designer. Select clientProvider1 in the component tree and modify the hostName property to the hostname of the middle-tier machine.

  7. Select clientResolver1 and modify the hostName property to the hostname of the middle-tier machine.

  8. Select Project|Make Project to rebuild ClientApp.

    Start ClientApp on the client, or first tier, by right-clicking on the ClientApp.java file in the project pane and selecting Run.

For more information