SITE
  Documentation
  Download
  License
  Performance
  Mailing List

FACADE
  Documentation
  Download
  License
  Mailing List

STORE
  Overview
  Tools
  Download
  License
  Mailing List

JUNIT EXTENSIONS
  Documentation
  Download
  License

AMANDA CD-RW
TAPER

  Overview
  Installation & Usage
  Internals

STORE - Overview

What's this?

STORE's Tivano's Object-Relational Engine. It also is Not Java 2 Enterprise Edition (the original name was dropped for obvious reasons). Instead it is a simple package that implements some of the nice parts of J2EE while trying to avoid the overhead that comes with a full J2EE implementation.

In the past we have completed a couple of projects where J2EE was used quite heavily, e. g. with Bea's Weblogic Commerce Server. We have made the experience that in those projects the cost of employing J2EE often outweighed the benefits. Cost, in particular, means

Tutoring time for the developers
Due to the fast pace at which J2EE has been evolving during the last few years, our developers have spent a lot of time on keeping their knowledge up to date. Therefore in this case tutoring time is not a one-time investment but a continuous cost factor.
Development time
If you try to do things in the right way (in terms of J2EE), things are more complicated. E. g. you have to get a JNDI context which you use to look up the home interface for a bean, which you use to get a bean instance, which you can finally use to invoke the method you were looking for. So in some cases a simple method call can explode into four, not counting any required try/catch clauses.
Administrative overhead
This may not be a big factor. A J2EE compliant application server usually has an administration interface that makes some tasks easier (like defining data sources etc.). Sometimes things have to be done by hand, though, like setting up message queues for message driven beans. Sometimes you want to be able to preserve configuration information in a simple form but the only way to access it is some GUI.
Resource usage
CPU utilization can be significantly higher when using J2EE, especially when beans are accessed via RMI. Also, database lookups can be significantly slower (which may be an implementation detail, of course - but sometimes you can't do anything about it). That means you have to put more money into faster hardware to achieve the same application speed compared to an implementation without J2EE. (One might speculate about SUN's motivation for introducing J2EE here... ;-)

Of course, there are benefits, too:

  • Entity beans provide a very convenient way to abstract the functionality of a database. This is especially true for entity beans with container managed persistence.
  • J2EE-based applications scale - in theory. I haven't seen an application that actually uses beans deployed on multiple machines. In theory you can load-balance a J2EE application quite nicely by distributing it among several machines. In practice, for the vast majority of web applications at least, this is simply not necessary.

So, the goal of this project is to create a simple infrastructure that provides some of the benefits mentioned above.

Step 1

At the time of writing the most important benefit is that of abstraction from the database layer. In other words, we want a simple replacement for entity beans. We will call these "entity peas" (because obviously they aren't beans).

Peas are designed with the following constraints in mind:

  1. An instance of a pea class represents a part of a datastore's contents, e. g. a row in a database table. Let P mean a part of that datastore's contents.
  2. For any P at any given point in time there must not exist more than one instance of any pea class within an application representing exactly P.
  3. Only if P is constant, i. e. it cannot be modified by any part of the application (including any peas), P may be part of the data represented by more than one pea.
  4. Usually nothing outside the application is allowed to modify any part of the data represented by a given pea. This is application dependent, of course - if the data will be modified the pea's implementation must handle it gracefully.
  5. Inside an application the only methods allowed to modify the P represented by a given pea instance are the member methods of that pea.
  6. If a pea's implementation allows modification of the data represented by it, the implementation must make sure that the modifications are propagated into the datastore in a convenient way.
  7. Any pea instance may be in use by more than one thread at any given time. If you don't like this, use synchronized methods.
  8. Any pea instance may be garbage collected at any given time, unless one of its methods is currently being executed by a thread.
  9. Every pea instance is uniquely identified by its class and a primary key. The primary key must never be modified.
  10. For every pea class B there must be a primary key class K. B must define an instance method getPrimaryKey() that returns an instance of K representing the primary key of the instance. Instances of K must not contain references to instances of B. For any two instances k1, k2 of K returned by calls to getPrimaryKey() on the same instance b of B the following equalities must hold:
    • k1.equals(b)
    • b.equals(k1)
    • k1.equals(k2)
    • k1.hashCode() == k2.hashCode()
    • k1.hashCode() == b.hashCode()
    • k1.getCache() == k2.getCache()
    It is encouraged that k1 == k2, i. e. b may contain a reference to its primary key. However, it is not allowed that k1 == b.

Peas will automatically be cached using weak references. A simple utility will emulate container-managed persistence by automatically creating a pea class with simple getter, setter, finder and creation methods.

How to employ generated peas

This section suggests an approach how to generate and handle pea classes that represent database contents (usually individual rows in a single table) via JDBC. This may not be the perfect method in all cases.

Employing a database-related pea encloses three things:

  1. managing database connectivity
  2. pea classes managing database content
  3. your application managing and using pea classes

These points are reflected in the approach described below. The goal of this approach is to handle step 2 automatically, i. e. to use a tool for automatic generation of java classes that handle most of the database interaction. In this way you can simply re-run the tool whenever the database layout changes.

Database connectivity is something that is usually the same for many different pea classes. This is a good reason to keep that part separate from the actual pea implementations. Also, since you usually want to use connection caching, or e. g. easily configurable connections, this is something that can hardly be generated automatically.

On the other side you have the view of the application itself on the peas. You usually want to have a stable interface for that application, that changes as little as possible when the database layout changes. This is the third part of the approach. In simple cases this part is not important and need not be reflected in your class structure.

The suggestion is to create a tree of classes looking like this:

  1. At the top you have de.tivano.store.peas.Pea, of course. Below that you create a Connector class (or several classes) that define a static method getConnection(String) - these will provide your Pea classes with the required JDBC connections.
  2. Then, use the de.tivano.store.util.DBPeaGenerator or de.tivano.store.util.ParseDia tools to generate pea classes for your database tables. Use the -x option to make these classes extend your Connectors.
  3. Finally (and optionally) create classes that extend the generated classes. Add your own methods for finding peas in the database or for creating new ones here. (You should use the -impl switch of DBPeaGenerator or ParseDia to make sure the generated Pea classes create instances of your classes!) You can also override some of the getter or setter methods, e. g. to put additional constraints on the values.

If at some later time the database layout changes, you can execute step 2 again and receive an updated representation of the database, while your own additions and modifications (in the form of your manually created subclasses) are preserved.

An example where this approach has been used can be found among the unit tests for the project. Check test/de/tivano/store/util/DBPeaGeneratorTest.java .



[ t]ivano software gmbh
www.tivano.de

Sun, Java, JDBC, JNDI and J2EE are registered trademarks of SUN Microsystems, Inc. BEA and BEA Weblogic are registered trademarks of BEA Systems, Inc. All other products and services are trademarks of their respective owners.