December 13, 2004
I almost never go to Google home page these days: I use a bookmarklet to directly go to Google results page instead. However with their suggest feature, Google has convinced me that it's worth it to go again to their homepage.
Now a RFE for Googlers: I'd like is to have this suggest feature in GMail when I do a mail search. I type from:
in the search field and GMail should suggest me a list of senders. That'd be cool and useful...
Google is not the first web site to make extensive use of XmlHttpRequest but they show how it can be done to enhance the web experience. As more developpers become aware of such functionalities, it will create a new breed of web applications which extend the web experience by embracing its principles rather than just mocking desktop applications within the browser.
December 7, 2004
Following my latest blog on the usefulness of a CRC Card whiteboard based on Mozilla and XBL, I made a simple prototype of such a whiteboard (works with Mozilla-based browsers only).
I only prototyped the client side of the whiteboard. But if that whiteboard was coupled with Wiki software on the server (for version control mainly but also to annotate the cards if the need arises), it could be a simple tool to communicate simple designs between development teams which are geographically separated.
When I had some time, I'll try to integrate it with a Wiki.
December 7, 2004
Could it be a good idea to develop a CRC Card-based whiteboard with Mozilla and XBL (similar to the sticky note example)?
It may be interesting to use it similarly to a Wiki to share design information simply. I made a quick search for such a Firefox extension but I found nothing.
Is it worth it?
December 1, 2004
Yesterday, I discovered that Firefox 1.0 on Mac OS X emulates a right click if I make a long click on the left (and only!) button. I didn't observe that behavior on Windows XP or Fedora Core 2. That's quite handy because I mostly use the trackpad on my PowerBook.
That's great to see that Firefox on Mac OS X tries to provide the same user experience than Aqua. I'm looking forward to Firefox 1.x releases which should increase compliance to the Human Interface Guidelines according to the new roadmap.
(Note to myself: I need to try Camino)
November 26, 2004
I had two interesting comments on my blog concerning logging.
BlogicBlogger added some advices to my list. He especially emphasizes the need to uniquely identify the logs (with session Id, transaction Id,...). If you log a multithreaded application, you need more contextual information than in a single user application because same parts of the code can be executed by different threads on behalf of different users and the logs are of no use if you can't follow the flow of execution for a given user ("user" may not be the appropriate term, e.g. it could also be a transaction).
Scott Deboy proposed me to use Chainsaw to watch the log files. I was aware of the product but I need to check that it can be used with an inconsistent log format (those dreaded System.err.print()
are mixed in the log4j files).
I saw a lot of documentation on logs but I find surprising that there is not so much good documentation on the specificity of logging multithreaded applications.
November 25, 2004
I had recently the opportunity to study log files of a heavily used Java-based Web application (several million hits a day). It was interesting to read these log files because I wrote a lot of logs when I developped but it was the first time that I had to read logs from code I was not familiar with.
It's definitely not rocket science but here is what I learn.
1. Log at the appropriate level
Logging framework defines several level of logging. For example, Log4J defines the following levels in its Level
interface:
DEBUG Fine-grained informational events that are most useful to debug an application
INFO Informational messages that highlight the progress of the application at coarse-grained level
WARNING Potentially harmful situations
ERROR Error events that might still allow the application to continue running
FATAL Very severe error events that will presumably lead the application to abort
However, it happens that some developpers understand slightly differently these definitions. What is important is to agree within the development team on the meaning and use of these levels to use them consistently.
2. Write your log at a given level for a given population
Depending of the level, your logs will be read by different people (either technical or non technical one). The logged information may need to be more or less descriptive.
3. Do not use several log calls to log related information
I often put in my code the following statements:
public void aMethod(String id, int value, boolean activated) {
if (logger.isEnabledFor(DEBUG)) {
logger.debug("id=" + id);
logger.debug("value=" + value);
logger.debug("activated=" + activate);
}
...
}
That's fine as long you are in a single-thread application. In that case, you get the logs one after the other in the log files. However, once you're in a heavily multithreaded application, you can have several other logs between two of your own logs. That makes it harder to understand the flow and the state of execution due to the noise provided by the other logs.
4. Do not rely on previous logs at different level to retrieve information
I saw the following code:
private void doStuff(String name) {
if (logger.isEnabledFor(Level.DEBUG)) {
logger.debug("name=" + name);
}
String value = giveMeTheValueFor(name);
if (value == null) {
if (logger.isEnabledFor(Level.WARN)) {
logger.warn("value not found, using default.");
}
value = ...
}
...
}
If the logging configuration displays up to DEBUG
level, that's great. But if the logging configuration displays only WARN
and ERROR
levels, the warning is useless. There is not enough information at these levels to give to the developper to help him or her reproduce and understand the problem.
5. No fancy System.err
or System.out
I still saw some System.err.print(...)
or System.out.println(...)
. It was obviously put while debugging the code but wasn't removed...
6. Use MDC/NDC to correlate logs
In a heavily multithreaded application, you can have lots of intermingled logs. It makes hard to correlate the logs to trace the execution for a specific user. One solution to this problem is to use Log4J Mapped Diagnostic Context or Nested Diagnostic Context. You can then store in the diagnostic context the session ID of the user to be able to uniquely identify all logs associated with a given user.
(It was Gavin King of Hibernate fame who introduced me to contextual logging)
7. No fancy System.err
or System.out
...
...especially in JSP!
Unfortunately there were a lot of System.err
in the JSP files. I suppose it's because it's less tedious to write a System.err.println()
in a JSP than a correct log statement.
8. Use Arrays.asList(Object[])
to log object arrays
I already blogged about this one but it's worth repeating it.
9. No fancy System.err
or System.out
...
Did I already mention this one?
To sum up
The bottom line is to have correct logs so that we are able to process them and automatically extract useful information. If they are consistent, it is then possible to retrieve much more information than if tehy are not (e.g. recurring exceptions at a given level).
November 24, 2004
I finally decided to setup a personal Wiki on my web site.
I have taken the habit to use plain text files to keep track of my daily work. I can then simply use grep
when I need to retrieve any information. I have files for every week that I fill as I work. It went quite well for some time but it has reached some shortcomings and I'm looking for an alternative.
The main disadvantage of plain text files is that is not internet friendly. Most of my work deals with URL (bugzilla URL, corporate wiki URL, client site URL generating errors,...). It's not a big deal to copy/paste from the files to the browser but when you have to do very often everyday, it becomes boring. Secondly, it's quite inconvenient to backup these files. I let them in the home directory on the workstation of my client company but I've to think to back them up weekly or monthly on my USB drive. I also need from time to time to refer from a file to another one (e.g. I encounter a problem I've worked on weeks ago and I'd like to refer to the first encounter without repeating myself). plain text is not good for such resource links...
My requirement for these files were pretty simple:
- they should be be viewable directly in a web browser to take advantage of the URLs
- they should be stored on my web server so that I can access them from anywhere...
- ... but I should be the only one allowed to view them
- it should be simple and straightforward to edit and modify them without uploads every time
- the file format should be as close as possible from plain text to keep editing simple
- Files should be searchable efficiently
A wiki meets all these requirements but the authorization one (more on that later). So I decided to give it a try and install a personal Wiki on my hosted web site.
I had to take into account my web site requirements to choose the right Wiki implemenation (among all the available ones):
- only Perl, Python or PHP implementation
- if a database is needed, only MySQL is an option
- I don't have a SSH access, so the installation and configuration setup has to be done only through the web or FTP
With these requirements in mind, I made a (completely subjective) short list:
I did not find enough information on MoinMoin to install it without shell access. I had the opportunity to use Twiki and I don't like it (it works great but I find it too bloated). I did not find any clear installation documentation on PhpWiki web site (it didn't pass my 5-minute test).
So the only remaining ones were UseMod and MediaWiki. And both had good documentation and were a breeze to install.
UseMod is a no-nonsense Wiki, very similar to the original Wiki. One Perl script, one data directory to store the files and that's it. You just have to change a few settings in the script, upload it on the web site and create the wiki directory.
MediaWiki has more features than UseMod. It is based on PHP and MySQL but is also very simple to install. You just have to upload a directory on your web site and use the web based wizard to configure everything (including MySQL tables). There is some chmod
to do but nothing more complicate (It's quite similar to the installation of Movable Type).
So in less than twenty minutes, I had downloaded and configured these two Wiki engines on my web site.
Next time, a comparison between the two and which one I finally decided to use.
November 22, 2004
I'm a little disappointed by Firefox 1.0 behavior on Fedora Core 2. It often crashes when I'm loading a batch of tabs in the background or if I'm Alt+Tabbing my windows (I already lost two blogs because of that...). It also freezes when I'm changing tabs.
It's quite surprising that the stability and responsiveness of Firefox is so poor on my Fedora box because I also uses it extensively on Windows XP SP2 and Mac OS X and it really rocks (I even removed Safari from Mac OS X dock).
Firefox is a milestone for Open Source softwares. It is the first Open Source project that I installed on my parent's desktop and they happily use it. It has the potential to be the Open Source's poster child on the desktop the same way Apache web server is on the servers. The Mozilla Foundation deserves huge congratulations for their work. They have done a lots of mistakes in the past (mainly due to AOL) and more than once it seemed it was losing its focus. But with the release of Firefox 1.0 and the upcoming Thunderbird 1.0, they are back on tracks and they really enhance the internet experience.
Never web browsing has been so fun! Well... as long as it's not on my fedora box!
November 18, 2004
Congratulation to the C-JDBC team!
It is a new example of how the Apache Software Foundation and the ObjectWeb Consortium collaborates to create great Open Source products.
Another great example which has not been talked a lot (because it lacks the cool factor) is the inclusion of Howl in Apache Geronimo and ActiveMQ so that these products can support transaction persistence and recovery.
Another milestone I'm waiting for is the integration of JOTM in Geronimo. Jean-Pierre Laisne and I were at the origin of the change of license of JOTM from LGPL to BSD to make it possible to use JOTM in Geronimo (ASF does not accept integration of LGPL code in their codebase). I believed that the change of license was a good opportunity for both JOTM and the J2EE Open Source community in general because ObjectWeb and Apache communities would then be able to contribute to it instead of wasting resource and time to duplicate a transaction manager.
To be honest, JOTM has not attracted a lot of contributors yet but I expect it to change once it's integrated in Geronimo and can reach a wider audience among J2EE developpers.
Brian Behlendorf used the term coopetition (cooperation + competition) to describe the Apache and ObjectWeb relationship and that's a quite accurate description (no needs of lawyers between the two, only software layers). At the end, what counts is that both communities gain from collaborating and sharing code.
November 8, 2004
When you call the toString()
method on an array in Java, you don't get an useful representation:
Object[] foo = {"bar", "baz"};
System.out.println(foo);
>>> [Ljava.lang.Object;@e0b6f5
I used to create my own representation of the array:
StringBuffer buff = new StringBuffer("[");
for (int i = 0; i < foo.length; i++) {
if (i > 0) {
buff.append(", ");
}
buff.append(foo[i]);
}
buff.append("]");
System.out.println(buff.toString());
>>> ["bar", "baz"]
But I recently discovered that the Collections Framework already offers this function:
System.out.println(Arrays.asList(foo));
>>> ["bar", "baz"]</code>
The trick is that you rely on the stringified representation of a List
to get the stringified representation of the array.