Separating database access logic and business rules from the user interface

Data modules simplify data access development in your applications. Data modules offer you a centralized design-time container for all your data access components. This enables you to modularize your code and separate the database access logic and business rules in your applications from the user interface logic in the application. You can also maintain control over the use of the data module by delivering only the .class files to application developers.

A data module is a specialized container for data access components. Once you define your DataSet components and their corresponding Column components in a data module, all frames that use the module have consistent access to the data sets and columns without requiring you to recreate them on every frame each time you need them. Data modules do not need to reside in the same directory or package as your project. They can be stored in a location for shared use among developers and applications.

The DataModule is an interface which declares the basic behavior of a data module. To work with this interface programmatically, implement it in your data module class and extend it by adding your data components.

When you create a data module and add any component that would automatically appear under the Data Access section of the Component tree (Database, DataSet, DataStore), a getter is created. This means that any of these components will be available in a choice list for the project that references the data module. This means, for example, that you can

Creating a data module

To create a data module,

  1. Select File|Close All to close any existing project (unless you want to add the data module to an existing project. In that case, skip this step).
  2. Create a new project by selecting File|New Project. The Project Wizard displays.
  3. Select the Browse button. You can create a data module in a separate project and once defined, refer to the data module class in your application. You can also create a data module in the same project as your application.
  4. Choose a location and a name for the project. Choose Save.
  5. Select File|New and double-click the Data Module icon.
  6. Specify the package and class name for your data module class. JBuilder automatically fills in the Java file name and path based on your input.
  7. Click the OK button to close the dialog. The data module class is created and added to the project.

You'll notice that the code generated by the wizard for the data module class is slightly different than the code generated by other wizards. The getDataModule() method is defined as public static. The purpose of this method is to allow a single instance of this data module to be shared by multiple frames. The code generated for this method is:


public static DataModule1 getDataModule() {
    if (myDM == null)
      myDM = new DataModule1();
    return myDM;
  }
The code for this method

The data module class now contains all the necessary methods for your custom data module class, and a method stub for the jbInit() to which you add your data components and custom business logic.

Adding data components to the data module

To customize your data module using the UI Designer, The data components are added to a data module just as they are added to a Frame file. For more information on adding data components, see Accessing data.

Note: JBuilder automatically creates the code for a public method that "gets" each DataSet component you place in the data module. This allows the DataSet components to appear as (read-only) properties of the DataModule. This also allows DataSet components to be visible to the dataSet property of data-aware components in the Inspector when data-aware component and data modules are used in the same container.

After you have completed this section and the next, your data module file will look like this:


package untitled7;

import java.awt.*;
import java.awt.event.*;
import borland.jbcl.layout.*;
import borland.jbcl.control.*;
import borland.jbcl.dataset.*;
import borland.sql.dataset.*;
import java.lang.*;

public class DataModule1 implements DataModule{
  private static DataModule1 myDM;
  Database database1 = new Database();
  QueryDataSet queryDataSet1 = new QueryDataSet();
  public DataModule1() {
    try {
      jbInit();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  private void jbInit() throws Exception{
    database1.setConnection(new               borland.sql.dataset.ConnectionDescriptor("jdbc:odbc:dataset tutorial",
       "SYSDBA", "masterkey", false, "sun.jdbc.odbc.JdbcOdbcDriver"));
    queryDataSet1.setQuery(new borland.sql.dataset.QueryDescriptor(database1,
       "select FIRST_NAME, PHONE_EXT from employee", null, true, Load.ALL));
    queryDataSet1.addEditListener(new borland.jbcl.dataset.EditAdapter() {
        
 	 public void deleting(DataSet dataSet) throws Exception{
          queryDataSet1_deleting(dataSet);
        }
    );
  }
  public static DataModule1 getDataModule() {
    if (myDM == null)
      myDM = new DataModule1();
    return myDM;
  }
  public borland.sql.dataset.QueryDataSet getQueryDataSet1() {
    return queryDataSet1;
  }
  void queryDataSet1_deleting(DataSet dataSet) throws Exception{
    //for example, business logic goes here
  }
}


Adding business logic to the data module

Once the data components are added to the data module and corresponding properties set, you can add your custom business logic to the data model. For example, you may want to give some users the rights to delete records and others do not have these rights. To enforce this logic, you add code to various events of the DataSet components in the data module.

Note: The property settings and business logic code you add to the components in the data model cannot be overridden in the application that uses the data model. If you have behavior that you do not want to enforce across all applications that use this data model, consider creating multiple data models that are appropriate for groups of applications or users.

To add code to the events of a component,

Using a data module

To use a data module in your application, it must first be saved and compiled. In your data module,

  1. Select File|Save All. Note the name of the project and the data module.
  2. Compile the data module class by selecting Run|Run. This creates the data module class files in the directory specified in File|Project Properties, Output Root Directory.
  3. Select File|Close All.

To reference the data module in your application,

  1. Select File|New Application. Accept all defaults. (Optionally, open an existing project using File|Open/Create)
  2. Select the application's Frame file.
  3. Import the package that the data module class belongs to (if it is outside your package) by selecting Wizards|Use Data Module.
  4. Click the Browse For Class button to open the Package Browser. A tree of all known packages and classes is displayed. Browse to the location of the class files generated when the data module was saved and compiled. Select the data module class. If you do not see the data module class here, check to make sure the the project compiled without errors.
  5. Click OK.

Click the Design tab to open the UI Designer; the instance of the data module appears in the Component Tree. Clicking the entry for the data module does not display its DataSet components nor its Column components. This is intentional to avoid modification of the business logic contained in the data module from outside.

When designing your application, you'll notice that the dataSet property of a UI Control includes all the DataSetView and StorageDataSet components that are included in your data module. You have access to them even though they are not listed separately in the Component Tree.

If you have a complex data model and/or business logic that you don't want another developer or user to manipulate, encapsulating it in a reusable component is an ideal way to provide access to the data but still enforce and control the business logic.

Understanding the Use Data Module dialog

When you select Wizards|Use Data Module, you will see the following dialog:

Based on the choices shown in the dialog above, the following code will be added to the jbInit() method of the Frame file. Note that Share (Static) Instance of Data Module is selected:

employeeDataModule = untitled1.DataModule1.getDataModule();

If Create New Instance Of DataModule is selected, the following code will be added to the jbInit() method of the Frame file:

employeeDataModule = untitled1.DataModule1();