Where JSTL comes to short (Part 1 : I speak to you in klingon)


JSTL (JavaServer Pages Standard Tag Library / JSR-52) has been around for quite some time now. It was certainly a breath of fresh air when it was introduced as an alternative to inline java in JSP files. Unfortunately I still find it lacking. I will try to describe these problems as best I can in a number of posts here on my blog. Please comment if you think I have misunderstood some of the concepts along the way.

I speak to you in klingon

Encoding URL’s in JSTL will give you problems. It turns out that the specification has a weird idea of automatic URL encoding. How they came up with this idea beats me. Or what really beats me is that they haven’t made it possible to manually override the encoding scheme to be used.

When encoding a URL you must know what charset a character within the URL should be encoded to. And that has to be a charset that the server which the URL leads to understands. So if you for example have encoded an URL with Klingon and the receiver decodes it as Esperanto, it will fail. JSTL will automatically encode any URL with the encoding scheme that your site is using (Actually the encoding scheme is taken from the Response object). But this is really useless if you are creating an URL to an external server that requires another encoding scheme than the one your site is using.

Example 1

Let’s say that my site is using ISO-8859-1. That includes source files and all content returned to the end user. Now I want to add a link to Twitter on all my articles. This link should automatically post a new tweed. And since I’m living in Norway I would like the text to be something like “Nå leser jeg : http://www.jakobnielsen.net/?p=1”

So I add this to my JSP file:

<c:url var="shareUrlTwitter" value="http://twitter.com/home">
    <c:param name="status" value="Nå leser jeg: ${siteUrl}" />
</c:url>

<a href="${shareUrlTwitter}">Tweed me!</a>

Where ${siteUrl} is a variable containing the URL to page we are at.

So I deploy the changes to my server and expects everything to work as planned. But clicking on the link immediately gives me a problem. The norwegian letter å is replaced with a strange character. Why is that? Well, as we could have expected, Twitter is not fond of ISO-8859-1 encoded URLs. It really prefers UTF-8.

Something is wrong

Something is wrong

So we’ve ended up with a URL looking like this:

http://twitter.com/home?status=N%E5+leser+jeg%3A+http%3A%2F%2Fwww.jakobnielsen.net%2F%3Fp%3D1

which is encoded with ISO-8859-1. What we really needed was a UTF-8 encoded URL like this:

http://twitter.com/home?status=N%C3%A5+leser+jeg%3A+http%3A%2F%2Fwww.jakobnielsen.net%2F%3Fp%3D

Ok, then we just need to tell the c:param tag or the c:url tag what encoding scheme to use when encoding the parameters right? Sorry dude! You cannot specify encoding for URLs in JSTL!

Conclusion

The JSTL specification states that all names and values in a <c :param> tag should automatically be encoded.

…It is indeed redundant, but is consistent with<jsp :include>, which supports nested <jsp :param>sub-elements. Moreover, it has been designed such that the attributes
name and value are automatically URLencoded.

It doesn’t say anything about what encoding to be used. The Jakarta taglibs project has solved this by picking the encoding from the Response object. For internal linking this works. But when creating external URLs this strategy must fail when creating a link to a server using another charset.

So, in these cases you have to come up with your own tags to solve the encoding problem.

How this problem could be solved

What is missing is an encoding attribute in the c:url tag, where you could specify what encoding scheme to be used.

<c :url var="shareUrlTwitter" value="http://twitter.com/home" encoding="utf-8">
    <c :param name="status" value="Nå leser jeg: ${siteUrl}" />
</c>

Leave a Reply

Your email address will not be published. Required fields are marked *