From OpenNMS
Contents |
Migrating OpenNMS to use the DAO Design Pattern (a.k.a Hibernate/Spring)
This document describes the strategy we will use to create a more flexible data implementation for OpenNMS. This implementation will abstract OpenNMS's data access and modication code to make it much easier to implement many of the long desired features of OpenNMS.
An example of just a small set of features this will enable are as follows:
- Improved XML Data Management
- By using Data Access Objects to access the XML files we will provide a much cleaner interface for manipulating the XML data that enables notification of changes and cleaner writing of XML data.
- XML to DB Migration
- Encapsulating data access will allow many properties that are currently defined in XML to be readily migrated into the DB. This will improve a number of things and make updates and other migration much better
- Distribution
- Encapsulating data access will make it possible for data to reside 'remotely' and allow for flexible distribution alternatives
- Deduplication
- There is a great deal of data access code spread through out the OpenNMS source tree. This will eliminate this duplication to a large extent.
What is the DAO Pattern?
We will (eventually) migrate all of the code that is used to access/manipulate the database, configuration files, the RRD files, or other externally data like reports or graphs to use the Data Access Object (DAO) Design Pattern. This pattern encapsulates access and manipulation of external data sources such as databases, config files and others. The DAO pattern creates the flexibility to change the format or location of data without needing to go through and rewrite the entire application.
The DAO Pattern defines five 'roles' or collaborators in the working of the pattern. These roles are as follows:
- The Client
- This role represents the 'Business Objects' or objects that need to access or modify the data.
- The DAO Interace
- This role is the operations (i.e. quieres and updates) that Data Access Objects define. These operations might include findById(nodeId) or getOpenOutagesForService(Service)
- The Data Transfer Object
- This role is the object that represents the data retrieved from the data source. An example object would be a Node or an Interface for a Database DAO or a User or Group for an XML based DAO.
- The DAO Implementation
- This provides the actual implementation of the DAO Interface. It is written for the particular data source the contains the data. These might include JDBCNodeDAO or CastorUserDAO, for node data stored in a database accessed via JDBC and for user data stored in an XML file accessed via castor respectively.
- The Data Source
- This represents the external location of the data abstracted by the DAO. This is can be a relational database, XML file, proprietary file format, web service or other external data location.
The Strategy
The approach we will take migrate OpenNMS to use the DAO Pattern is as follows:
- Define Data Transfer objects representing the data in a single row of each table defined by an OpenNMS's postgresql database.
- Create empty DAO interfaces for each table that will eventually have methods used to access the data from the table.
- Create a stub implementation extends Spring's HibernateSupport class that will use Hibernate to query the data and implement the DAO operations
- Use XDoclet on the Data Transfer object to define the Hibernate object to relational mapping and generate the hibernate configuration files.
- Setup a Spring application context file that sets up all of the DAO objects as well as the Hibernate session needed to correctly retrieve the data.
- Go through the code looking for database access code. In any location where database access is made, place an appropriate call to locate the DAO (or even better inject the DAO)
- Next define a DAO operation that provides the data
- Implement the operation in the DAO Implementation using Hibernate
- Once this is done we will enhance this strategy to discuss using the DAO Pattern for XML and RRD Files and any other places where it would make sense.
Notes: Any code that exists solely to cache database data should be removed. It this is necessary for acceptable performance it should be done inside of the DAO rather than external to it. Examples of this would be places in the code where the serviceID to serviceName maps are maintained to avoid an additional DB query.
Why Hibernate
Hibernate was selected because it provides efficient object to relation mapping technology. It enables us to efficiently represent objects in a relation database that allows to put object methods where they belong and even provides for appropriate inheritance relationships. As the code improves Hibernate will make for an easier more extendible implementation.
Why Spring
Spring has a sophisticated implementation for dealing with transactions, exceptions, and database sessions/connections. It enables us to declaratively define transactions via configuration file as well as a mechanism for 'wiring' up beans that makes for code this is both testable and easy to use. Addidtionally Spring's 'proxy' features will enable us to distribute the different pieces of OpenNMS readily.






