Semaphores for children

October 28, 2007

In the never ending search for better metaphors, I stumbled upon a nice example from my childhood. When I was a child and went to kindergarten, next to the door in the classroom, there were 2 necklaces. If you wanted to go to the toilet, you had to take a necklace, and when you returned, you had to put the necklace back. If you were unlucky, both necklaces were lent, and you had wait or try again a few minutes later. This is a perfect example of a Semaphore with 2 licences.

The solution isn’t quite optimal however. The building has room for 2 classrooms (with each 2 necklaces) and 4 toilets. So it could happen that a child needs to wait in one classroom, even though the necklaces in the other classroom still are available. But heck, what more can you expect from a child that is able to comprehend the basic concepts of concurrency control 🙂

Advertisements

Design patterns and design problems

October 24, 2007

At the moment I’m playing with Ruby (building a Norton Commander thingy based on GTK) and one of the things I’m realizing (again) is that a lot of ‘design’ complexity disappears because Ruby, in a lot of cases, is cleaner and less verbose. For example: in Java you would have to create a Strategy (aka Policy) or Template Method if you need to inject a function, in Ruby you can use a closure. The consequence is that small grained design in Java is difficult, and this is caused by all the syntactic overhead (interface definitions, anonymous innerclasses, template-methods etc).

I don’t say design patterns are bad, but some design patterns (I would rather call them concepts) are harder to implement in some languages, and this inhibits good design: you are damned if you do, and damned if you don’t (if you don’t, your code gets ugly, and if you do, your code gets ugly).

Design pattern = Concept + Implementation
Concepts often are good, implementations often are limited by the host-language.


Versioned id’s

October 22, 2007

If you are using multiple system transactions that span a single business transaction, there is chance of isolation problems: a business transaction could see changes made by other transactions and this could lead to erroneous behavior.

Example:
there is a web page that can be accessed by management, that contains a list of all employees. Each row contains the id, the name, the date of the last bonus and a button to give the bonus. When the button is pressed, the id of the employee (eventually) is send to the following service method:

@Transactional
void giveBonus(long id){
	//load throws a special exception if the employee is not found
	//Spring: ObjectRetrievalFailureException if employee isn't found
	Employee e = employeeDao.load(id);
	e.giveBonus();
}

The problem with this approach is that 2 managers could access the page at roughly the same moment and both see that some employee didn’t get a bonus for some time and decide to give the bonus. The consequence is that the employee has received the bonus twice. Although this example is a little bit hypothetical, in some cases this behavior could lead to serious problems.

Optimistic locking is one of the best known techniques to deal with these issues: it doesn’t lock (unlike pessimistic locking) but hopes (is optimistic) about the fact that no other transaction is going to conflict. If a different transaction does make a change, the version of the data is changed, and this is something that can be checked. As soon as a difference between versions is found, an optimistic locking failure exception can be thrown.

Just carrying around the version and id, doesn’t feel that good. It makes method signatures less pretty and you have to carry it around. Especially when you need to deal with multiple entities, the solution gets more ugly. The solution is simple: integrate id and version into a single structure: VersionedId. VersionedId’s contain the id of an entity and also contain the version of that entity; so a VersionedId can uniquely identify an entity in time and could look like this:

class VersionedId{
	long version, id;
}

the previous example could be rewritten by using a VersionedId:

@Transactional
void giveBonus(VersionedId id){
	//load throws a special exception if the employee is not found or version doesn't match
	//Spring: ObjectRetrievalFailureException if employee not found
	//Spring: OptimisticLockingFailureException if version doesn't match
	Employee e = employeeDao.load(id);
	e.giveBonus();
}

As you can see there is not much difference. But you have to make sure that the load method of the EmployeeDao is able to handle versioned id’s and starts throwing some kind of optimistic locking failure if the Employee with the given id and version can’t be found. And instead of just placing the id of the employee on the html-page, the version needs to be placed as well.

Using detached objects (and reattaching them) is also a solution. But there are some issues:

  1. The detached objects need to be stored and the most likely place is the HttpSession. This could lead to replication issues if you are in a clustered environment
  2. Vague transactional behavior
  3. I have seen some weird issues with detaching and reattaching entities with Hibernate (especially not detaching completely)

Damn checked Interrupted Exception

October 9, 2007

A lot has been written about checked and unchecked exceptions and in most cases I prefer using unchecked ones. Because you don’t want deal with the exception, but want it to be propagated instead, so it can be handled higher up the call stack. In case of pooled threads, like in a servlet container or Executor, the exception is caught and usually logged and the thread is made available for the next task.

InterruptedExceptions are no difference: in most cases the thread container interrupts blocking threads (because it wants to shut down for example) and only this container is able to deal with the InterruptedException. This means that you are forced to catch it, but normally this is not something you want because an interrupted thread should ‘stop’ as fast as possible to return to the top of the callstack so the threadcontainer can decide what to do.

A better solution is to propagate the exception, but because the InterruptedException is checked, it also need to be added to the throws clause. The problem with this solution is that you keep adding it to the throws clauses higher up the callstack and this isn’t always the cleanest solution or even possible. So in both cases, you are screwed.