Usage of Data Base Classes

This page explains how interfaces and implementations can be used efficiently to model your own data. I’ll show you how to write a data model that is stored at the filesystem. If you need to implement your model based on a database model, it is recommended to check out this tutorial because DB models require more specific handling. The RS Library module data-hibernate delivers most of the logic implementation but you still have to add code specific for your model.

If you are directly looking for application code examples that leverage the model in production life, there is a special article available.

We will begin with the definition of terms that we use throughout the documentation and which will be reflected by class names.

Terms

Business Objects are Java Beans that represent real-world objects. A customer is such a Business Object, or products that can be bought in an online shop are Business Objects. Their main task is to store properties such as the name and address of the customer, or description and price of the product to be sold.

Data Access Objects implement the access mechanism required to work with the data source. The data source could be a persistent store like an RDBMS, an external service like a B2B exchange, a repository like an LDAP database, or a business service accessed via CORBA Internet Inter-ORB Protocol (IIOP) or low-level sockets. The business component that relies on the DAO uses the simpler interface exposed by the DAO for its clients. The DAO completely hides the data source implementation details from its clients. Because the interface exposed by the DAO to clients does not change when the underlying data source implementation changes, this pattern allows the DAO to adapt to different storage schemes without affecting its clients or business components. Essentially, the DAO acts as an adapter between the component and the data source.

Data Transfer Objects are data carriers. The Business Object may use a Data Transfer Object to return data to the client. The Data Access Object may also receive the data from the client in a Transfer Object to update the data in the data source.

A DAO Factory allows highly flexible DAO patterns. The DAO Factory creates and maintains the Data Access Objects an application requires. The DAO Factory itself exposes its functionality via an interface.

A DAO Master shares data between multiple Data Access Objects. This can be metadata about the data store, authentication information or other useful settings that Data Access Objects require to work properly.

The following picture illustrates the relationships between the various components:

DataModelHierarchy

Writing a Data Model: Interfaces

The following section will demonstrate how a Data Model can be designed and implemented using the Data Base Library. The complete source code of this example is available here. Our example will use the filesystem to store information about customers. Here is an example of such a file:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<object class="rs.data.file.impl.CustomerFileImpl">
   <id class="java.lang.Long">1</id>
   <name class="java.lang.String">John Doe</name>
   <invoiceAddress class="rs.baselib.type.Address">
      <street1 class="java.lang.String">42, 2nd Street</street1>
      <street2/>
      <zipCode class="java.lang.String">60549</zipCode>
      <state/>
      <city class="java.lang.String">Frankfurt/Main</city>
      <country class="rs.baselib.type.Country">GERMANY</country>
   </invoiceAddress>
</object>

As you see, this is a simple XML file. It will be stored in a special directory /customers on our local disk.

The Primary Key

Each Business Object requires a Primary Key that uniquely identifies this customers. Of course, the name already fulfills that requirement. However, Primary Keys must not change over time. That’s why names are bad candidates for Primary Keys. Our example will use an artificial serial number that is generated from a sequence each time we create a new customer. Therefore it is a Long object. We will call it Customer ID, or just ID.

The filename

The filename will be the customer ID appended by .xml suffix. 555.xml is a valid filename, 0555.xml or customer555.xml are not.

Business Object

We now have all necessary information to create our Business Object interface. It derives from ILongBO which is a IGeneralBO using a Long as its Primary Key.

1
2
3
4
5
6
7
8
9
public interface Customer extends ILongBO {
   public static final String NAME    = "name";
   public static final String INVOICE_ADDRESS = "invoiceAddress";
 
   String  getName();
   void    setName(String name);
   Address getInvoiceAddress();
   void    setInvoiceAddress(Address address);
}

The interface declares Getters and Setters for each of the properties so a client can retrieve and modify them. Additionally, the interface defines constants for each of the properties that will be later used in PropertyChangeEvents (Remember! Business Objects are Java Beans).

Data Access Object

We will need a Data Access object which deals with customers. We keep it simple and declare no additional methods than those that are already defined by the ILongDAO interface (deriving this from IGeneralDAO).

public interface CustomerDAO extends ILongDAO<Customer> {
}

Using this inheritance, we already have methods available that create and retrieve customers, modify or delete them. It is recommended that you inspect the Java API of IGeneralDAO to see what functionality a DAO brings along.

DAO Factory

The last interface to be defined is the DAO Factory that we want to use. It is very simple as we are currently just using customers. We derive our interface from IDaoFactory.

1
2
3
4
5
public interface ExampleDaoFactory extends IDaoFactory {
 
   CustomerDAO getCustomerDao();
 
}

That’s it. We just defined the client-side interfaces for our Data Model. The following picture illustrates again the relationships between the various interfaces:

CustomerInterfaces

Writing a Data Model: Implementations

We will now bring life into our model. We’ll start with the Data Transfer Object as a pre-requisite to Business Objects. However, you can decide to implement the Data Model without such DTOs.

Data Transfer Object Implementation

Our example will use java.util.Maps as transfer objects. Of course, the choice could be different (especially Hibernate models will require your own implementation). However, Map is the easiest choice here as it doesn’t require any additional implementation and rs.data.file.bo.AbstractFileBO (see below) already uses this by default.

Business Object Implementation

The Data Base Library already comes along with abstract implementations of interfaces that we used earlier. This will keep our implementations small and easy to read. We’ll inherit now from rs.data.file.bo.AbstractFileBO. However, you can inherit from AbstractBO and implement it on your own as it was done for AbstractFileBo (Source Code):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class CustomerFileImpl extends AbstractFileBO<Long> implements Customer {
 
   public CustomerImpl() {
      this(new MapDTO<Long>());
   }
 
   public CustomerImpl(MapDTO<Long> dto) {
      super(dto);
   }
 
   public String getName() {
      return (String)getData(NAME);
   }
 
   public void setName(String name) {
      setData(NAME, name);
   }
 
   public Address getInvoiceAddress() {
      return (Address)getData(INVOICE_ADDRESS);
   }
 
   public void setInvoiceAddress(Address address) {
      setData(INVOICE_ADDRESS, address);
   }
 
   ...
}

This implementation requires some explanation. Line 4 declares a no-argument constructor. Each Business Object implementation requires such a constructor. The library requires this to easily create instances of Business Objects for you (see newInstance() method).

Line 8: This constructor is for ease of use. It will pass the DTO to the super constructor. AbstractFileBO (resp. AbstractBO) will automatically create a DTO when you don’t pass it in.

The Getter (line 12) shows how to retrieve the name from the Transfer Object. The method is straight-forward.

The Setter method is usually somewhat more sophisticated as it would require you to store the old value temporary before setting the new name into the DTO, and then finally to send a PropertyChangeEvent. However, AbstractMapBO (anchestor of AbstractFileBO) already does all the logic for you so you just need to call setData() (line 16). Check out the source code of AbstractFileBO to see the complete implementation of setter methods.

Data Access Object Implementation

The DAO implementation is even more simple than the BO implementation. We didn’t define any additional methods, so all implementations are already delivered. Just derive from AbstractFileDAO.

1
2
3
4
5
6
7
8
9
public class CustomerDAOFileImpl extends AbstractFileDAO<Long, CustomerFileImpl, Customer> implements CustomerDAO {
 
   /**
    * Constructor.
    */
   public CustomerDAOFileImpl() {
   }
 
}

The DAO Factory Interface

As will all other classes, application code should operate on interfaces only – instead of specific implementation classes. That’s why we define an interface for our DAO Factory first.

1
2
3
4
5
6
7
8
public interface ExampleDaoFactory extends IDaoFactory {
 
   /**
    * Returns the DAO for customers.
    * @return the DAO
    */
   public CustomerDAO getCustomerDao();
}

We could define it without the getter for the CustomerDAO and simply use getDao(Class< ?> clazz) in application code, but it will ease our life later and make the code more type-safe.

Define getters for all your DAOs and you are done with the DAO Factory definition.

The DAO Factory Implementation

The implementation is as simple as the interface. We derive from AbstractDaoFactory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ExampleDaoFactoryImpl extends AbstractDaoFactory implements ExampleDaoFactory {
 
   /**
    * Constructor.
    */
   public ExampleDaoFactoryImpl() {
      registerDao(new CustomerDAOFileImpl());
   }
 
   /**
    * {@inheritDoc}
    */
   @Override
   public CustomerDAO getCustomerDao() {
      return getDao(CustomerDAO.class);
   }
}

Line 7 is not required and you shall definitely omit this initialization when you want your application to be more flexible. The implementations delivered with RS Library comes with an extensive configuration mechanism (based on XML files) that allow you to change you DAO implementation classes just by configuration. See the DAO Factory Configuration article for more details.

Line 15 is actually the example of what you would do in application code in case you didn’t define the getCustomerDao() method earlier. Again, we recommend to define them.

The following picture outlines the implementation hierarchy:

CustomerImplementations

Bring it all together

We now can bring all pieces together and write some application code to startup our model:

ExampleDaoFactory factory = new ExampleDaoFactoryImpl();

That’s it. 🙂 Your model just started up. If you are in an OSGI environment, you could also use the IOsgiModelService to register your factory and have it available wherever you want.

And what’s next?

This article showed how to use the interfaces and implementations delivered with the RS Library to implement your own persistent data model. The following list contains articles that describe other aspects of data models when you use this library:

One Response to “Usage of Data Base Classes”

  1. American Steroids Says:

    […] with Bitcoins Buy American Steroids Online with Bitcoins Buy American Steroids Online with Bitcoins Buy American Steroids Online with Bitcoins Buy American Steroids Online with Bitcoins Buy American Steroids Online with Bitcoins Buy American […]

Leave a Reply