So far, you've seen how JDBC and ADO.NET can be used to perform simple database access from Java and .NET, respectively. From here, it should be clear how both drivers could point to the same instance of a database and be used to insert, update, and delete records, thus enabling data to be shared between the two platforms, as shown in Figure 7.3.
To show a particular implementation of this, we'll work with a design pattern known as the Data Access Object (DAO). This is also known as the Data Access Component (DAC) or Data Access Layer Component (DALC).
|More Info|| |
The DAO pattern was first introduced by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, affectionately referred to as the Gang of Four. You can learn more about this and other design patterns in Design Patterns (Addison-Wesley, 1995).
In its simplest form, the DAO is used to separate database access code (such as the samples you just saw) from business logic. The DAO is very similar to the agent-service pattern discussed in Chapter 6, "Connectivity with XML Web Services, Part 2," except that instead of abstracting a Web service proxy, you abstract code that makes direct calls to the database.
If you look at this pictorially, in Figure 7.4, you can see how the DAO layer resides directly between the database layer and the business logic layer.
In general, a DAO is used to provide CRUD-type functionality for abstracting a database from business logic. CRUD is an acronym commonly used in the database world that stands for:
Creating new records in the database
Reading records from the database (and returning them as data types used by the business logic)
Updating records in the database (by using updated data types that are used by the business logic)
Deleting records in the database
In the chapter's samples, you'll see examples of creating and reading these records by using both the Java and .NET platforms. By examining the code, it will be possible to see how update and delete methods can be introduced.
The sample code for the DAO can be found in the C:\Interoperability\Samples\Resource\Database\DAO directory. Two versions, one for ADO.NET and one for JDBC, can be found there. Both of the samples define a data type named StockRecord , which contains elements that match the fields of the order table, and a class for the DAO itself, named StockRecordDAO . The StockRecordDAO class is responsible for maintaining the connection to the database and for exposing the database connection through a series of methods to perform the creates and updates. These methods include the following:
GetStockRecords(String type, long accountID)
GetStockRecords(String type, String ticker)
GetStockRecords(long accountID, String ticker)
GetStockRecords(String type, long accountID, String ticker)
When a method is invoked, the DAO constructs the correct SELECT statement, executing the query against the database and returning the result either as a StockRecord (for single records returned) or an ArrayList that contains one or more StockRecords .
Compile both the ADO.NET and JDBC samples, using either NAnt or Ant depending on the programming language selected. The DAO is invoked by a Client class that simulates some simple business logic to read and add a record from the database:
Reading a single record with ID=1000: CONT There are 2 records with ID = 38293 Adding a record...
Each time you run the sample, it displays the ticker of an individual record and adds a new record to the table. By running both samples multiple times, you can observe how new records are created by both the ADO.NET and JDBC sample.
Notice that the client code is very similar for both .NET and Java, whereas the platform-specific code (the database access) is abstracted in the DAO layer. For developers using both platforms, this abstraction is one of the benefits for using a consistent DAO.
What benefit does a shared DAO pattern yield when you're developing solutions that require interoperability between .NET and J2EE? In terms of direct database access, the calls to the database will be the same regardless of whether a pattern is used. Therefore, the main advantages are twofold.
First, developing data access based on a shared DAO gives you a common frame of reference for accessing data on either platform. If you were to follow a similar pattern to the one shown in the previous sample, writing business logic for either .NET or J2EE would allow for a consistent feel regardless of the platform used to access the data.
Second, as with the agent-service pattern you saw in Chapter 6, the DAO pattern has the ability to provide additional logic and functionality for accessing databases. For example, a DAO could include code that provides the following:
A level of caching between the business logic and the database. Records that were recently accessed could be returned from a cache to increase performance.
Management for security (authentication and authorization) for connecting to the database.
Handling for transactional and locking issues.
Data paging to allow pages (or blocks) of data to be returned for large data sets.
Based on this list, a DAO pattern that's used by both the .NET and J2EE platforms also allows for some other interesting notification options in a shared database. Imagine a configuration in which business components from both .NET and J2EE access a shared database by using the DAO pattern, as Figure 7.4 depicted.
Using this setup, it might be desirable to find out when either of the platforms has updated a particular record in a database. For example, if a component on one of the platforms has made an update, a component on the other platform might want to reload that data to either perform some function or keep the cache current.
Using this DAO pattern, you have the potential to extend the DAO layer on both .NET and Java in order to provide some notification from each platform to the other. For example, you could use either .NET Remoting or Web services to pass an update message between the two DAO layers , as shown in Figure 7.5.
Doing this can eliminate the need for each of the platforms to constantly "poll" records in the database for changes ”which can be common in situations where a shared database setup is required.
The final sample in this chapter will demonstrate how the DAO can be extended to include such an update operation. This sample can be found in the C:\Interoperability\Samples\Resource\Database\UpdateDAO directory and is based upon a particular customer requirement that I encountered recently.
The sample shows a small .NET application based on Windows Forms that's used to monitor the order table in the database. The forms-based application allows the user to view the current records populated in this table and uses methods exposed from the same DAO pattern shown in the previous discussion. The second half of the sample shows a Java client that also accesses the database by using the DAO pattern and adds a new record when run.
The update operation is performed by using .NET Remoting between the Java client and the Windows Forms application. The Windows Forms application exposes a server-side component that can be called by using .NET Remoting. After the Java DAO successfully adds a new record to the database, it uses a .NET Remoting call to inform the Windows Forms application that it should refresh its view of the database. Figure 7.6 illustrates this.
The server-side component of the Windows Forms application that's exposed is attached to an event in code. When an incoming call is made by the Java DAO, the event triggers a refresh of the screen.
To see this in action, compile both the ADO.NET and JDBC portions of the UpdateDAO sample code. Because the JDBC code uses Intrinsyc Ja.NET to perform .NET Remoting, you might want to refer to Chapter 4, "Connectivity with .NET Remoting," for further details. All the required proxies have been generated as part of the sample, but the licensing will need configuring by using the janetor tool.
Within the ADO.NET sample directory, compile and run the Windows Forms code by using nant run . The form that's displayed shows a simple summary of each record within the order table, as depicted in Figure 7.7. To scroll through the records, use the navigation control to view a particular record number.
Now switch to the JDBC sample in the UpdateDAO directory. Run the Client application. This will use the DAO layer to add a new record to the database, indicated by the following output:
Adding a record...
Once this operation is complete, switch back to the Windows Forms application. You should notice that the number of records has been incremented automatically, as shown in Figure 7.8. Navigating to the last record will show the details of the record that was added by the Java DAO layer.
In addition, the following line can be uncommented in the SummaryForm.cs class:
MessageBox.Show("The Java client has added a record to the order" +" table. Click on OK to refresh.");
This will display a message each time the database is updated by the Java DAO layer.
To allow the Java DAO layer to inform of a database update, the Windows Forms application exposes a NotificationRemoting object. When called, this object calls a NotificationFactory in order to obtain a singleton reference to a notification object. In .NET Remoting terms, a singleton is a static instance of an object that can be shared across processes. Because the same reference of a notification object is required for both the Java and ADO.NET DAO layer, a singleton provides a single point where update events can be shared.
When the notification object is called, it creates a new event that's handled by the ADO.NET DAO layer. The DAO layer in turn reexposes a new event that can be consumed by the business logic of the application. This setup is shown in Figure 7.9.
Because all the notification and access logic is abstracted by the DAO layer, the business logic code simply has to take action on the update event. The Windows Forms application includes a line to register the event handler from the DAO layer:
dao.Updated += new UpdateEventHandler(dao_Updated);
The dao_Updated method contains the code that updates the screen.
This sample shows a simple notification process between the DAO layers on the Java and .NET platforms. To extend this concept, imagine how the DAO layer could pass additional information with the update to further optimize the sample. For example, the DAO layer could pass information on which record was affected by the update.