null checking in the extreme

In Java, we’re told to check for nulls to avoid unexpected null pointer exceptions.  This can be taken too far though.  Consider the following code:

StringBuilder builder = new StringBuilder():
if ( builder != null ) {
builder.append("data");
}

When did builder have the opportunity to become null? By definition, a constructor creates an object. We just called the constructor. We know builder isn’t null. Having extra code around just invites confusion. It leaves the reader of the code wondering if they are misunderstanding something. Worse , it is a form of dead code. The if statement will never be false so it serves no purpose.

When universities teach programming, they often leave out the parts about how to make code readable and easy to maintain for others. Whether that “other” is yourself in six months or someone else, it is still professional to make the code easy to maintain.

The extra null check certainly isn’t anywhere near the worst example of unmaintainable code I’ve seen. I’ll blog more examples of this in the future.

Database Key Generation in Java Applications

All JDBC programmers at one time or another have had to deal with key generation for new records, or more precisely, how to retrieve keys for newly created records. This article discusses some of the techniques and limitations offered to Java JDBC programmers.

Key

  • Unique Keys

Most (good) database systems assign a unique key, usually a large number, to every record in the database. For example, a user “Bob Jones” might have a User Id associated with the record of 808182313713. This key is unique for Bob and is a lot easier to pass around a system then Bob’s full name, since there may be other Bob Jones’s in the system. We could spend time discussing Natural Keys, although I would argue there is no such thing as natural keys. As an example, Bob’s social security number might seem like a natural key since it is unique to Bob but it may be the case Bob is a visiting foreigner (or the application is deployed outside the country) in which a US social security number is not applicable. Also, it’s been reported the government has been known to recycle social security numbers, as well as the fact that people can be issued new social security numbers during their lifetime. Even if unique natural keys did exist – e-mail for example – what if a user wants to change their address down the road?

This leads us to our second requirement of unique keys: Unique keys should not change throughout the life of the system. Changing unique keys is often an extremely difficult, highly risk process. A third, less followed, requirement is that unique keys should be private and only used internally by the application server. This is a huge boon to security and prevents users from attacking the system. In the case the system does need to expose a key, such as an eBay item number found in the URL of the auction, the system may create two keys: an Internal Id that is used for table relations within a database, and an External Id used to perform lookups on behalf of the user. The key here is that the External Id the user sees only exists in one record, whereas the Internal Id is used throughout the system to connect different records.

For the purpose of this article, we’ll assume key generation is the common approach of assigning long integers to each record in a table. In most database systems, this corresponds to the BIGINT type.

Helpful Advice: Always use the largest integer type the database has to offer for unique keys – numeric wrap-around is something to be concerned about, especially on smaller data types.

  • Defining the Problem

Most systems generate keys sequentially starting with a low number such as 1000. Why? Well, for starters it makes it easy to find new unused key value. Just find the max value of the table, and any value above this will be an unused available key. You could randomly generate a key, but then creating a new key would be a time consuming processing of generating a random number that has not been used.

Now, let’s say a user is in the process of creating a new record in your system. For each user record, you also have a set of postal addresses. For example, Bob may be purchasing items on NewEgg and have a home address and a work address. Furthermore, Bob enters his two addresses at the time he creates his account, so the application server receives the information to create all 3 records at once. In such a situation, you would normally have 3 records: 1 user record for Bob and 2 address records. You could add the address info in the user table, although then you have to restrict the number of addresses Bob can have and/or have a user table with a lot of extra columns.

Inserting Bob into the user table is straight forward enough, but there is a problem when you go to insert users into the address table, namely that you need Bob’s newly generated User Id in order to insert any records into the address table. After all, you can’t insert addresses without being connected to a specific user, lest chaos ensue in your data management system.

Most database systems provide a technique for the database to create keys for you in the event you do not specify them. In this situation, the first insert would leave the User Id for Bob as blank, or more precisely null, and the database would fill in a new value on insertion. The problem is the database isn’t really obligated to tell you what this newly created value is. The rest of this article will be devoted to discussing how you can get this generated key in your application.

  • Technique 1: Get the max id

Probably the most common approach is the quick and dirty one; perform a select query immediately after your insert and retrieve the max value:

SELECT max(id) FROM users

The good: In a lot of systems this actually works pretty well. It’s easy to implement and is extremely database independent.
The bad: It’s extremely risky in high concurrency environments. For example, if two users perform inserts at nearly the same time, they will both get the same max value from this query, leading to a huge breach in security (both users may have access to one of the users records if the application server returns the same id). There are ways to set your transaction isolation level to avoid problems like this, but that can be tricky and often requires more skill and experience than someone implementing this solution regularly is likely to have.

Also, you have to be *very* sure the system always creates keys strictly in ascending order. A database system that reused old or skipped key values would be incompatible with this approach.

  • Technique 2: JDBC to the Rescue!

Many JDBC programmers are unaware that there is built-in JDBC method for retrieving the newly generated keys immediately after an insert. It is appropriately named getGeneratedKeys() and can be used as follows:

Connection con = // connect to database
final PreparedStatement ps = con.prepareStatement("INSERT INTO users (...) VALUES (...)");
ps.setInt(1,...)
...
final int insertStatus = ps.executeUpdate();
int newKey = -1;
if(insertStatus == 1) {
     final ResultSet rs = ps.getGeneratedKeys();
     if(rs.next()) {
          newKey = rs.getInt(1);
          if(rs.next()) {
               // Probably should throw some exception if rs returns a second, unexpected record
          }
     } else {
          // Probably should throw some exception if no generated keys created
     }
} else {
     // Definitely should throw an error if insert failed
}
System.out.println("The key value for the newly created record is: "+newKey);

A reminder: JDBC starts with 1 (instead of 0) for accessing columns based on an index number.

The good: Don’t need to write any special or tricky logic to get the key. Works in systems that use ascending and non-ascending key value generation. No risk of getting the wrong key value even if you fail to set transaction or isolation levels properly.
The bad: Not supported by all JDBC drivers. Need to test it out in your real system to verify it works before relying on it.

  • Technique 3: Application Server Controlled Keys

One approach used in most large J2EE systems is to build a key generation service within the application tier. In this manner, all generated keys are created ahead of time by the application server without the use of any database-specific features. In the example above, the system would generate all the keys for the user and addresses before the first insert even occurs. Then it would insert the 3 records, one after another, using the keys it had at the start of the service. Keep in mind, the order of insert still matters, i.e. you can’t insert an address for a user that does not yet exist; but in this case, you don’t need to stop after the first insert to figure out information for the next insert.

Such a key generation module would have to be application-wide (static) and thread safe to prevent two requests from getting the same key at the same time. Also, such a system would have to be fault tolerant; if the system crashes it should not reassign any of the same keys after the next restart.

Often this is implemented with a database table that keeps track of the most recently assigned key for each record. To make the service perform well, keys are often released in blocks. For example, the system might say “The last key used was 4100, and I’m going to request 4101-4200”. In this manner the system would update the database record for that table to 4200 and only change this value when it used up all 100 keys in memory. It’s fault tolerant because even if not all keys from 4101-4200 are used, if the system crashes, it knows it can just request 4201-4300 next time.

The good: Performs better than any of the other solutions since it takes the load off of the database entirely. All inserts can be performed immediately without requesting information from the database in between inserts. Safer than any of the solutions because its is 100% database independent. Supports composite keys and distributed database systems.
The bad: Requires the most overhead of any of the solutions since you need to implement a server wide key generation tool. Requires the application server to know the name of each table (or some reference to each table) to track the key generation values for each table. Also, you could skip a lot of keys (sparse key range) if your system restarts frequently, although servers shouldn’t be restarting frequently! Lastly, it tends to require an experienced developer to implement properly (prevent errors) and perform well (using blocking properly).

  • Technique 4: Database-specific techniques

Lastly, you may want to rely on database-specific techniques. For example, Oracle allows you to write queries such as:

INSERT INTO Users (...) VALUES (...) RETURNING (id) INTO newUserId

In this case you would perform an executeQuery() instead of an executeUpdate(), so that the results of the insert could be read in a Result Set.

There are numerous other database-specific techniques for retrieving newly generated keys, but since I advocate against database-specific code in Java applications, I’ll leave a more detailed discussion for someone else.

The good: It’s safer than technique 1 since it works in systems with non-sequential keys.
The bad: It’s database-specific. Not only that but as shown above, all of your insert statements would be database specific. Would make moving the code to another database system very difficult (often impossible).

  • Final Thoughts

Generally, for smaller systems Technique #2 using getGeneratedKeys() is the best solution. Larger systems with composite key generation or distributed databases often require Technique #3 for an application controlled key generator.

As for the other two approaches, I would strongly advise against ever using Technique #4, lest you want to give future developers of your source code a huge headache in management and portability. Lastly, Technique #1 is sometimes safe to use, especially in single threaded systems, although is often evidence of a beginner JDBC developer.

J2EE: Why EJB2 CMP was Doomed to Failure

EJB2 Failure

For those in the J2EE world, one of the hottest, most contentious topics that has arisen is what went wrong with EJB, version 2. For those not familiar with the subject, I’ll try to provide a brief description. In 2001, Sun released a specification for connecting a Java object, called an Enterprise Java Bean, hereafter referred to as an EJB, to a database table through an construction called an Entity Bean. They referred to the technique as Container Manager Persistence, or CMP for short. Through the clever use of XML files, one could define Entity Bean relationships between Java code and a database, that could change on the fly without having to recompile the code or rewrite the application.

Initially, Entity Beans were well received as ‘the wave of the future’, but the problem lies in the fact that this specification was mostly worked out only in theory. The specification was written with such detailed requirements for the developer, that anyone who tried to implement Entity Beans in EJB2, had immediate code maintenance problems. There were just too many rules and maintaining large code bases was extremely difficult. In 2006, Sun released the Java Persistence API, JPA for short, in version 3 of EJB specification that, for all intents and purposes was a complete rewrite of EJB2 Entity Beans. They streamlined a lot of the interactions that were required to set up EJBs and borrowed a lot from more grass roots technologies like Hibernate and JDO. In essence, they threw out EJB2, copied Hibernate, then renamed the whole thing as ‘the next version of EJB’. Ironically, they might have been a little too late as many organizations had all ready switched to Hibernate by the time the implementations of the new specification were released.

These days most developers prefer Hibernate to EJB, although given the pervasive nature of Sun’s EJB/J2EE terminology I wouldn’t be surprised if JPA/EJB3 (the name at least) makes a comeback. As I look back on these recent events it makes me wonder, if EJB2 was such a good idea in theory, why did it fail so miserably in practice? What was it about Entity Beans people failed to consider? I hope to use this post to address some of this issues, albeit in hindsight, that the original planners of EJB2 did not consider.

  • Issue #1: Not all Servers are Created Equal

One of the most prominent features of Entity Beans in the EJB2 specification was their ability to work with any database system. A developer could, again in theory, write an application could seamlessly deploy on a variety of database systems (MySQL, Oracle, SQL Server, etc.) and applications servers (JBoss, WebLogic, WebSphere, etc.). The mechanism behind this fluid deploy was that all relationships between the database and application were stored in a single XML file. One just needed to open this XML file in a text editor, rename a few fields, and the application would work on that system. Need to deploy on a variety of systems? Just create a new XML file to map the application to that system.

Sounds wonderful in theory, but the practically speaking? This never worked, the servers were just too different. For example, while all databases have standardized on common language called SQL for 90% of the database communication, it would be a near miracle for you to find a code base that did not use any database-specific features. Most large enough systems rely on stored procedures, indexes, foreign key relationships, and key generation that while may be similar from database to database, doesn’t mean you can just drag and drop code from one system to another. Porting code from one database system to another often requires editing thousands of files line-by-line looking for changes and is a quite a difficult, often impossible task.

And that’s just database servers, application servers require their own server-tailored XML to perform the data mappings for each and every field in the relationship. Most databases have an average of a hundred or so tables with a couple dozen fields per table, so you’d have maintain a server-specific XML file for thousands of fields for each application server you wanted to deploy to. When a developer says porting an EJB2 CMP application to a new application server is hard, this is a large part of what he’s referring to.

Part of the problem with the variation among application servers was Sun’s own fault. While they defined the vast majority of the spec themselves, they, for whatever reason, allowed each application server software to define its own extensions for such features as database-specific fields. This wiggle-room allowed application server developers to create schemas as different as night and day.

  • Issue #2: Maintaining large XML files in J2EE is a contradiction

Going back to a single-server application, let’s say you do implement an EJB2 CMP-based system. At the very least you have an Entity system composed of a hundred java files, a single XML file (ejb-jar.xml) that defines the entity beans, and a single application-specific server XML file (jboss-jdbc.xml, open-ejb.xml, etc) that maps the entity beans to the database. What happens if you make a change to the java code or the database? Those files must be updated, of course! That means a developer needs to have exclusive access to edit these 2, quite large, XML files. In large enough groups, developers will be fighting to make changes to these files and contention for this file will be high in the version control system.

The history of J2EE is that it was designed to be a component oriented large business platform. Have a project with only a single developer? No reason to use J2EE since it can be done a lot faster by one developer. On the other hand, have a large project that requires dozens, perhaps hundreds, of developers working together? That’s what you ‘need’ J2EE for. But now add the fact that hundreds of developers are going to be writing and rewriting 2 very large XML files and you come to the realization that the technique is fundamentally flawed. You need J2EE for large development teams but maintaining a lot of single-point large files tends to break down faster in large development groups.

  • Issue #3: Databases change far less frequently than software

We’ve previously discussed how EJB2 defined all of those XML mappings in a way to allow you to change the database and application server without ever having to recompile code. The idea (I guess) being that database changes and application server changes were far more likely than code changes. Well, in practice that idea is completely wrong. The vast majority of J2EE applications work on one specific database type and one specific application server (often a specific version of the software). Furthermore, database changes are extremely rare. Often, once the database structure is defined, it is rarely, if ever, changed. Java code on the other hand is often rebuilt on a nightly basis. You would never get into the situation in practice where a change to an existing database system was needed before the code was ready to support it. Add to that the fact that most developers go out of there way to write solutions to software problems that do not require changes to the database! Most are fully away of the problems associated with changing the database (modify all related java and XML files, notify related teams, write database patches, etc), and will only change the database as a last resort.

In short, EJB2 defined a powerful spec for an ever changing persistence database layer, and no one bothers to use it in practice because of the maintenance issues involved. I’m sure I’m not the only developer that has seen poorly named database tables and fields like ‘u_Address_Line3’ (instead of ‘City’) but refrained from changing them knowing the havoc such changes would likely bring. Since the user is never supposed to view the database directly, why should it matter what things are named?

EJB2 Post Mortem and Lessons Learned
Not all of these issues were unaddressed during the life of EJB2. For example, XDoclet is a tool that provided a way for generating the large XML files for each system after a code change was made. The problem? It was never developed to support all systems and still had developers fighting to check in use their version of generated file to the version control system. Ultimately though, after thoughts like XDoclet were too little too late; people had seen how much more useful the implementation of object relational mapping tools such as Hibernate had become, and jumped shipped early on. When JPA finally did come out in EJB3 the audience was far from excited: the most dedicated of the crowd who had adopted EJB2 early on were left with no way to upgrade their systems other than to do a near-complete rewrite of their CMP system, and those in the crowd who would have probably most enjoyed the new features of JPA had all ready switched to Hibernate, with no reason to switch back.

When JPA/EJB3 was released, it virtually did away with all of the XML files, instead choosing to put the database mapping information directly in the java code file in the form of an annotation tag. In this manner, a developer only needed to look to one place to make changes to the entity bean and database. In the end, EJB2 entity beans is yet another example of why systems designed in theory should be tested more in practice before being trumpeted as the ‘the wave of the future’. It’s not that JPA is more superior to EJB2, in fact far from it. As I’ve mentioned EJB2 had amazing data control and could was capable of many powerful features. The problem lies in the inherent contradiction of creating J2EE as a component-oriented platform while enforcing centralized interactions and overly complicated management schemes. In the end, it was hard to find one developer, let alone a team of 30, capable of managing the EJB2 code base properly.