Thứ Hai, 17 tháng 5, 2010

Spring & Freemarker, when the *advertised* stuff doesn't work

FreeMarker is a cool Java template engine, for almost every purpose, especially for the web.
I have adapted FreeMarker for quite some months, and been very happy with it since. However, there's one thing in FreeMarker that make me feel *damn* uncomfortable. It's the number format. FreeMarker will *smartly* add "comma" to make my number more readable. So, 1000 should be rendered as "1,000".

Back to the past, I adapt FreeMarker as an supplement into my existing code based on Spring MVC. So, I search around for solution. Some guys on the internet suggest I added a class name FreeMarkerConfigurer to my Spring beans definition and add a property named "number_format" with value of "0.####" and the problem should go away.

However, I tried without any success. I guess I make some typos so I tried again and again. A lot of article, and my problem remained unsolved. Finally, after hours of frustration, I switched to the the hard way: Add "?c" after every number I'm about to print into the screen (it's an instruction that tell FreeMarker engine to not add the comma into the number).

Well, thing went well at first. But I'm not a man of good memory. So, after few months of development, I have introduced few dozens of "?c" but forget to add this instruction for hundreds of numbers, most of them lied in the link.

So, what is the problem? Glad you asked.

Given I want to give user an access to a database record. So I give him the link:
Link

The link work well, if record.id<1000. If the record is a number that exceeds 1000, for example, 1002, then I get this link:
/database/rec/1,002

You can notice a *comma* was added to the number, and thus make the link incorrect.

I have hundreds of these kind of links in my templates. So, I'm hanging my self on a sting of the sword, waiting for my app to gradually fail....

Well, I shouldn't let it happen, right?

So, this time, I did an exploration through these FreeMarker configuration. Thanks to maven dependency management and eclipse awesome exploration tool, I finally notice a protected method name createConfiguration which FreemarkerServlet used to instantiate configuration itself. The method was declared as protected for some reason, and that reason allow me to subclass it and feed the FreemarkerServlet my desired configuration.

You guess, here is the code:

import freemarker.ext.servlet.FreemarkerServlet;
import freemarker.template.Configuration;

public class CustomizedFreemarkerServlet extends FreemarkerServlet {

/**
*
*/
private static final long serialVersionUID = 3079263156037673099L;

@Override
protected Configuration createConfiguration() {
Configuration conf = super.createConfiguration();
conf.setNumberFormat("0.#####");
return conf;
}
}

Just a few lines, and now things are in order. I'm back into a safe living condition.

Thứ Hai, 26 tháng 4, 2010

Stupid m2eclipse

Maven is cool stuff. And m2eclipse is cool, too. However, m2eclipse seems to be stupid with my connection. When ever I make a change in my pom.xml, m2eclipse will *very smartly* hang my eclipse while it's trying to download a dependency from the internet. It would not be a problem if the file is relative small. But with the Google App Engine SDK (which is about 50 MB in totals for every new release), m2eclipse start to suck. I got no idea of how fast it is downloading all the giant jars. And guess what, when I try to stop it, it will be so stubborn and take, I don't know, probably an hour just to give up. I know m2eclipse is given for free, but it just makes me mad. I'm blogging this post while waiting for maven (which I kick start from command line) to fix some consequences of m2eclipse (and what I've done when I was getting mad at m2eclipse). May be I should file a bug on m2eclipse issue tracker to notice soya developers about this stupid behavior. Cannot stand it any longer. (Probably find myself mad again with the stupid Jira in the next few minutes. Why can't Atlassian people just make thing simple and elegant like Google Code?)

Thứ Hai, 29 tháng 3, 2010

Do it the GWT way

Back to the time when I was developing website with Asp.NET & jQuery, one of my favorite way is to generate as much HTML as possible on serverside. On client, I will use jQuery CSS Selector to bind these HTML back to some kind of encapsulated object (For example: I will generate a HTML for a Product on server and then use jQuery CSS Selector to build a Javascript Product object from these HTML).
Things worked pretty well back to that time. User will quickly see the page without waiting for javascript to be loaded. And when javascript is loaded, I can take control over existing HTML Element. And well, I save one round trip to query products from server and render them using javascript. Quite some benefit, though.

When I adopt GWT, this way is still strong wired to me. Since GWT does not provide a CSS Selector, I turn to GWTQuery for a help. Things goes pretty well until...

Assume that I have 2 products. For each product, I would have a div to display them. In each div, I would have some anchor, some label, span. In order to manipulate these element easily, I assign each element with some id. Problems is, the page will now have many element with the same id. However, they are in separated panels, so it shouldn't matter, should it? Well, indeed, it does matter, as GWTQuery no longer be able to serve that purpose: If I use the same selector (like input#email) over two distinct base HTML Element (2 different divs) then it will result in the same element (at least on the most popular browser Firefox).

After two days of frustrating trial and errors over debugger, I found GWTQuery unusable for this purpose and well, I were stuck...

However, things shine quickly. Few hours after that, I try to figure out the GWT way to do that, and I found UIBinder. Although UIBinder cannot server my purpose (not a replacement to GWTQuery, and I'm not going to save any round trip since my client code will now query for products itself), it does open my eyes to a new way of web UI development: the GWT way.

Using UIBinder, my HTML Template will be easily wired to an existing class (using @UiField annotation), so I don't need any CSS Selector any more and still be able to manipulate the DOM like a charm.

Hmm, there're some problems left with GWT though. Gotta solve it.

Thứ Hai, 22 tháng 3, 2010

HtmlUnit & Button Element

Recently, when I adopt the HtmlUnit into testing, I encountered a weird problem.
In the page, there is a BUTTON element. Whenever the button is clicked, a value will be submitted to server, result in a change in content.
However, HtmlUnit won't let me see the new content.
The code look like this:
WebClient wc = new WebClient();
HtmlPage page = (HtmlPage) wc.getPage("http://localhost/doSomething");
HtmlButton button = (HtmlButton) page.getByXPath(...);
HtmlPage page2 = button.click();

As that step, if I make an evaluation in my debugger, then page==page2 will result in true (normally, it would be false). So, I come to a conclusion that HtmlUnit didn't submit the form when I clicked on the button.

So, I replaced [BUTTON] element with [INPUT type="submit"] and the page==page2 will now result in false, the page is properly submitted.

Oh, sh*t, I whispered, a bug in the HtmlUnit code base....

But well, thing isn't that bad. After looking around for more information about BUTTON element, I found out that BUTTON have an attribute named type, which can be set to either "submit|button|reset". So, I gave it a try, add [type="button"] to the [BUTTON] element and BOOM, my code worked.

Hmm, a little difference with the expectation but thing is fine. After all, I learned a lesson: When in doubt, make all properties explicit.

HtmlUnit is great, though.