JSF has excellent i18n support, but sometimes the resource bundle approach won’t quite work. What if you need to be able to update content without re-deploying your app? In this short tutorial, I’ll show you how to easily implement something similar that uses a database. I’m actually in the process of writing a more advanced tutorial on making your pages easily editable via Ajax4jsf and a bit of javascript - this tutorial deals with one of the conventions you’ll see in that tutorial, and will be helpful in understanding it.

The tutorial code is using JPA, Spring 2.0, and Facelets in addition to JSF 1.2. It isn’t required that you have this same setup, though. You could use Hibernate, iBatis, straight JDBC or whatever else in place of JPA - although you’ll want to make sure you are somehow caching the results in this case. Spring 2 (or Spring at all) is not required either, but it certainly makes things easier. Facelets isn’t required either, but if you are using JSF without Facelets, umm, why?
Lastly, I haven’t really included any configuration stuff - ie, JPA configs, faces-config, or the Spring config. It shouldn’t really be necessary.

So, first, let’s create our Content object. It can be really simple - let’s just give it a key (content key and locale), a content field, and a really simple history.

And the IdClass for it:

Now we’ll need to come up with a way to get them out of the database and onto the page. We could create a backing bean and add a property for each key, but there has got to be a better way, right? Indeed, we should be able to reference it the same way we would a normal property from a resource bundle, more or less. To do that, we’ll need to create a dummy implementation of java.util.Map. If we extend java.util.AbstractMap, we only have to implement two methods: entrySet(), which can return null for our purposes, and get(Object key), which is the actual method for getting our property.

Note how we use the locale and combine it with the key to get the object. The JpaTemplate from Spring is injected in. In the event that we can’t find an object for that key, we’ll try to return a helpful message to let the developer know what is going on. Also, in this case, I am returning the actual Content object instead of the content - this may prove useful down the road should we need to, say, show content history (or any other myriad of things, such as special formatting, etc). Here is the code for our bean:

So, now we can create our page like this (wordpress mangled it a bit - but you get the idea…):

It is relatively simple, but it will provide the basis for the next tutorial, which I will hopefully be finishing and posting tomorrow.