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.
5 Responses
rodolfo
December 1st, 2006 at 3:49 pm
1This looks all very interesting, but I cannot get it to work.
E.g. Netbeans (and Spring-Version: 2.0.1 )
does not like multiple Id, it says:
“There are multiple IDs in this entity class, but no
IDclass is defined”
So if I remove the second ID annotation here:
@Id
private String key;
@Id
private String locale;
the error message goes away.
I am new to persistence and annotations etc.
I just want to have a database-backend-multilingual
nonresource-bundl setup (like I have seen it in the PHP world).
Could you elaborate or post some sample .war file or something like that?
Thanx,
Rodolfo
suresk
December 1st, 2006 at 4:15 pm
2Hi Rodolfo,
My apologies: When I adapted my code for this tutorial, I didn’t setup the IdClass properly.
The tutorial is updated now, but basically you need to define the ContentKey class and then annotate the Content entity with @IdClass(ContentKey.class).
- Spencer
Rodolfo
December 6th, 2006 at 3:43 pm
3Hi Spencer,
I still do not get it to compile.
I tried to change your line
public Set> entrySet() {
to
public Set> entrySet(){
but probably this is not correct (though the IDE claims that this is a valid implementation of entrySet )
–
Could you maybe post a Netbeans (or Eclipse)-importable project ?
Maybe I do something wrong with the package-file-layout.
Sorry, I am just not so experienced.
Rodolfo
Rodolfo
December 6th, 2006 at 3:47 pm
4AHA! Looking at my last comment I see that
your blog-comment-software destroyed my proposed change (so probably yours too).
I use < and > now:
public Set<Map.Entry<String, String%gt;%gt entrySet(){
Maybe this works.
Rodolfo
Rodolfo
December 6th, 2006 at 3:49 pm
5soryy, being tired.
change in the last post %gt;%gt to >>
RSS feed for comments on this post · TrackBack URI
Leave a reply
Categories
Archives
Links
Meta
Recent Entries
Recent Comments
Most Commented
JSF Resources is proudly powered by WordPress - BloggingPro theme by: DesignDisease