Friday, November 16, 2007

Recursive, is it good?

Want a job? Reverse a string ...
having read the blog above, remind me of an interview I had which exactly, asked me to write a code which reverse a string. The code I wrote was a simple for loop doing exactly what was asked, so simple a code that I'm so sure it won't have any bug.

The blog I read made me think, was recursive really the code that was expected by my interviewer (which then became my boss for the shortest time of my employments' life... ever :p)
Anyway, that's not what I'm talking about here, the point of interest is recursive.

Recursive, imho, is very useful, sometimes an undisputable way to solve a problem efficiently. BUT... it is not the silver bullet which will work efficiently for every problem. Yes, it will work undisputably well for layouting components (e.g. Swing, JSF), some mathematical stuffs (e.g. permutation), deleting folder and its content and many other things.

Wise programmer will try to write a simple, elegant and performing code. Less bugs, easy to maintain, faster code, less memory consumed aren't those the traits we all want for our code (there are some more...).
Only unwise programmer will try to write a recursive code for reversing a string, or maybe....
only an interviewee who knows where this question lead to, will write it that way (and hoping that he will get the job at some high salary :p).

It's really funny remembering that I've had this kind of test in my interview... If I did write a recursive code for reversing a string... was I a super programmer? or even a genius?

Wednesday, October 24, 2007

Sniffing your request-response data (how does server redirect?)

At first I was curious what are the data sent by the server to redirect the browser to the next page.

My first try is to use wireshark (it was ethereal before renamed to wireshark), unfortunately localhost traffic doesn't get sniffed. Then I try to install Microsoft loopback adapter, then again... wireshark doesn't detect the loopback adapter. I was thinking wireshark can do almost anything for me, unfortunately it didn't (or is it because of the os limitation? dunno).

Looking up for tools, then I remembered back then I used Grinder as a proxy. Going to grinder's site, downloading the latest version (3.x), setting it up, it works! However (again), the output isn't exactly what I need.
Going for the previous version of Grinder (2.x), got it, set it up, works like charm :) I analyze the data and here's what I found.

------ localhost:8080->localhost:4632 ------

HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Location: http://localhost:8001/loadtracker/form/project-select.shtml?cid=1&clr=true
Content-Length: 0
Date: Wed, 24 Oct 2007 05:09:27 GMT


Interesting! HTTP/1.1 302 is the answer.

I've heard that IE 7 doesn't redirect to the new location, my first guess maybe this was the cause :

If the 302 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.



But it said that the request is a GET/HEAD and mine is POST (after login). Probably it is the security setting in IE that blocks it, not replicated in my IE.. yet.

Anyway, I'm not talking about IE here, Grinder will be quite handy for everyone who want to investigate the request-response data. FYI, having read some comments about Grinder 3, it could be an interesting tools for load testing, replacing JMeter.

Tuesday, October 23, 2007

Date is displayed wrong-decrease 1 day(JSF)

Have you ever get confused because your Date is displayed wrong (i.e. decreased 1 day) when you use h:outputText?
This might happen because JSF spec says that date converter defaults to using standard UTC timezone and you're happen to live in some other timezone, in my case it is GMT+07.

My first idea was to build a date converter which use the default timezone in the server and use f:converter to specify my converter id. Somehow the date pattern can't be passed to my converter, that's sad, I don't want to force a certain pattern.

My second idea is simply to create a method in my utility bean called
public String getTimeZone() which will return the default timezone ID, and use it to specify the timezone attribute in f:convertDateTime facet.

so the outcome looks like this :
<h:outputText value="#{track.movedDate}">
<f:convertDateTime pattern="MM/dd/yyyy" type="date" timeZone="#{constants.timeZone}"/>
</h:outputText>

All that needs to be done is to put the convertDateTime facet in every outputText.

Monday, October 22, 2007

JSTL 1.0 and 1.1 URI

It's a bit confusing for some developers why EL doesn't work in JSTL tags where they think it should've work and it turns out the culprit is the taglib uri.

JSTL 1.0 URI is http://java.sun.com/jstl/core
JSTL 1.1 URI is http://java.sun.com/jsp/jstl/core

So instead of using 1.0, it is better to use 1.1.

Don't forget to put standard.jar and jstl.jar in your WEB-INF/lib.

Saturday, October 20, 2007

Setting up web application using seam

Last time I used seam was in a project that was setup using maven2 and running in a tomcat with embedded ejb container from JBoss. I thought that moving the application to JBoss server (4.2.1.GA) would be easy, I was wrong (probably because I never setup a JSF project before, especially one that uses seam).

My plan was to create an ear containing a jar (containing the model & service ejb3 beans), another jar (containing the action listener classes, which is stateless/stateful beans) and a war file. All the libraries will be put under lib directory inside the ear.

Problems I got (I forgot some details, I write this around 3 weeks after):
1. When deployed, the jars inside the lib directory can't be found.
2. I was desperate, so I put the jars back in each jars & war lib. Got ClassCastException somewhere, this was due to different classloader used to load the jar. So I define a classloader repository name in the configuration file (jboss specific), then I got another exception related to the listener configured for the web app... totally desperate.
3. Seam doesn't know my bean in the other jar file, should I include the jar in my war's lib? nope, don't want to.

The point is I want to use the same jars for all the three of my jars & war.

I just go to sleep, having enough headache and annoyance. The day after, going around the net, I found this interesting element I can use in the application.xml file, i.e. (available since JEE 5).

Problems solved! All my jars & war use the same libraries, Seam knows all my beans in my jars, no more ClassCastException, listener related exception and other strange things unbeknown to the world of mortals.

Here are my projects & configurations :
1 project containing the model & service beans. (1 jar)
1 project containing the jsf action listener beans (ejb3 stateless & stateful beans)
1 web application project
1 ear project

My ear looks like this :
- model.jar
- action.jar
- app.war
- lib (containing libraries, i.e. jboss-seam.jar, etc)

The key is in application.xml :
<module>
<ejb>model.jar</ejb>
</module>
<module>
<ejb>service.jar</ejb>
</module>
<module>
<web>
<web-uri>app.war</web-uri>
<context-root>app</context-root>
</web>
</module>

<library-directory>lib</library-directory>

At last, I can work happily ever after...... :)

Friday, October 19, 2007

Truncate date object

Unfortunately Date object doesn't provide a way to truncate a date effectively removing its time (resetting to 0) easily.

My first try is to use Calendar and set the hour, minute, second and millisecond fields to 0.
Calendar calendar = Calendar.getInstance();
calendar.setTime(theDate);
calendar.set(Calendar.HOUR, 0);
.... same with min, sec, mil.

Then came up DateUtils from apache common lang, interesting utility, but the javadoc doesn't explain much on how truncating the time and strangely it choose instead to pick parameter which is specified as the most significant field to preserve(when all I want to do is to remove the time).
Anyway after trial-error, here is the code I came up with :
DateUtils.truncate(theDate, Calendar.DATE);

I was expecting only date is preserved, month and anything else will be gone, but it works! Thanks to DateUtils.