Sunday, December 30, 2007 online editing is awful

I have just spend some VERY frustrating days fighting with Blogspot/Bloggers online editing, as I was finishing my "Guide to OpenJDK" article. Avoid using the "a name" tag at all cost, it is normally used to create internal links to chapters in a webpage. When you switch to the preview or compose page, Blogger scripts automatically duplicate this tag EVERYWHERE throughout the text for some bloody reason. Before header tags, inside header tags, after header tags, before links, before images, before every paragraph, before lists, inside every list item.... You will have to spend hours removing them... and if you miss one, like I did, it will metatasize like a cancer all over your text if you switch editing mode again! Fun!!

Also it doesn't save your original hand edited HTML. If you use the "lesser than"/"greater than" html elements to show, for instance, an email address, when you go to compose window everything looks ok, but when you switch back to editing html it will try to parse what is inside the "tag" characters, fail and delete your text.

Friday, December 28, 2007

The LG DBRH198

Our Samsung digital TV decoder broke down recently, and when looking for a replacement I found the LG DBRH198 - a combined DVD/CD/DivX/WM/jpg player, digital decoder, cd/dvd burner and 120GB media recorder. After spending a very frustrating day and a half trying to get it to work, I am now returning it.

  • Would have replaced four machines (VHS, DVD, CD, decoder) with one, if it had worked. Compact living, and saves energy!
  • Image was sharp, at least on our small LCD TV.
  • Refused to read our Boxer smartcard connected through a CAD adapter, only the free channels worked.
  • Text TV fonts were ugly, an eyestrain to read.
  • When going through menus it kept "locking up" randomly so we had to pull the plug repeatedly.
  • If we accidentally pushed the AV button on the remote we lost the decoder image. It got to AV4 and then refused to cycle back to the beginning no matter what buttons we pushed and we had to do a "reset to factory settings" to get it to read from AV1 (antenna) again. Perhaps there is a better way, but the manual didn't say. I don't know if this is a bug or just really poor user interface design
  • Poor interface design in general. We are two engineers in the household, and if we were having problems finding out how the menus work... not a good present for grandma.
  • Poorly translated menus. Unlike some machines I've owned, this time it wasn't so bad that it made understanding difficult, but it was still distracting. Manual was ok though.
  • Felt slow and sluggish - slow on startup, slow to change channels, slow to read the DVDs.
  • We could not get sound to work through the decoder. It generally worked when playing DVDs (see below), and once we stumbled into playing back a recording from the hard drive and then it worked, but we never got it to work when watching TV directly through the decoder for some reason. Perhaps there was some setting hidden somewhere, or we should have used another audio cable, but this is something I think should just work out of the box and not something you have to fiddle around with for hours trying to get to work.
  • Once when playing a DVD the sound was suddenly just roaring white noise. The same DVD had worked fine 10 minutes before on the same machine...
Previously I have been pleased with LG products. Certainly not high-end stuff, but cheap, fairly robust and lots of features. Seems this machine had too many features crammed into it and not enough quality. I think I'll try to replace it with one really good decoder with build in HD recording, and one really good DVD player. Probably not LG this time.

Wednesday, December 12, 2007

Beginners guide to OpenJDK contributing


There is now an official OpenJDK Developer guide which incidentally appeared two days after this article was noticed on the frontpage.

You should go there for up to date information instead. Thanks to Brad Whetmore for useful feedback though, and getting this article noticed by mentioning it on his blog.


This is an expanded version of a presentation I held at Javaforum Stockholm in December 2007. It is intended as a quick "getting started" guide for those who wish to participate in the OpenJDK project. All the information was already out there, but spread over many different sites and I thought it needed summing up in one place so beginners could see step by step what they need to do to get a patch accepted. A warning - as the OpenJDK project changes quickly the information here may be out of date. Comments, feedback or errata is much appreciated. The article is published under the Creative Commons.


  • What is OpenJDK
  • Why contribute?
  • Who are in charge?
  • Organization - Groups and Projects
  • Getting the code
  • Preparing for the build
  • How to build
  • Short code overview
  • Contributor agreement
  • Testing your changes
  • Unit/regression tests
  • Committing patches
  • Making a good patch
  • What I would like to see
  • Links

What is OpenJDK

OpenJDK is the project to open source the development of the Java platform and virtual machine. Java has always been free to download and use, and the source has been available under the Java Research Licence. Now it is also available under a Free Software Foundation approved licence - GNU General Public Licence 2 with Classpath exception. This is not a separate project to Sun's "ordinary" Java. It is not a "ok kids, go play with this and don't bother us anymore" abandonware - the engineers at Sun will use the organization and tools described here exactly like external contributors do, and this source will be the base for the release of Java 7 and future releases as well as possible alternative distributions.

Note that the OpenJDK project is only for collaboration around the implementation of the Java platform. The specification is still being decided by the Java Community Process, which you really should join incidentally... free for individual members, you get to vote about once a year about who will be in the expert groups that decide the future of the platform.

Why contribute

Why should you waste valuable time contributing to open source when you don't get paid for it? Here are the reasons I have to do that:
  • Increase your competence as a programmer. Perhaps you have a few hours a week at work dedicated to increasing your competence? Gaining a better understanding of the JVM and seeing how common algorithms are implemented is a pretty good way to do that.
  • You increase the value of your chosen platform. You make it more likely that there are good jobs for you in the future. Considering how much stuff have been written in Java the last 10 years I don't think there will be any lack of jobs for competent Java programmers for as long as I live, but perhaps you want some new development in the future, not just maintenance programming.
  • Make new contacts. When I was at JavaOne this year people at Sun who work in the management/JMX areas recognized my name when I came up and talked to them because I had submitted a couple of patches in that area.
  • It is an excellent merit. You have code that you are legally allowed to show to potential employers. This is not just a little open source project that you and your closest friends use - if you submit patches to Java (or Linux), your code will be used in critical applications by tens - make that HUNDREDS of millions of end users daily.
  • If you have a reoccuring bug that you have had to do an annoying workaround for - here is your chance to get rid of it permanently, not just for yourself but for all programmers around the world.
  • You will contribute to a more free and better society. Ok, I realize we are getting dangerously close to starry-eyed idealim territory here, but knowledge is power in today's world and computers are our primary knowledge-management tool. Therefore I think it is unwise to allow all control of our computers to fall to any singular entity, be it a state or a few large companies.

Who are in charge

Currently there is a "interim governance board" which I believe was selected by Sun, with help from the open source community. They will write a constitution and decide the final form the project will take. The members are:

Organization - Groups and Projects

OpenJDK has two main concepts - Groups and Projects. I think this could be changed in the future by the governance board in theory, but I doubt that will happen. Groups and projects are described on the official OpenJDK site, but here is a brief summary:


A group is a collection of people with a common interest. There are three levels of participation: 1. Participant 2. Member 3. Moderator. A participant is anyone who has subscribed to the group mailing list. A Member is someone who "has demonstrated a history of significant contributions to a Group, has been granted Membership by that Group, and has signed the SCA" (more on the SCA later). A Moderator looks after the mailing list, counts votes etc.

Groups usually have web pages describing them and mailing lists for discussions, but they DON'T have code repositories. A group can chose to sponsor a project. The initial groups were more or less the engineering teams at Sun - Java2D, Security, Hotspot, etc. Any group Member can suggest new groups. An examples of this is Dalibor Topič's Porters group suggestion which was approved just a few weeks ago.


Projects exist to create some form of "artifact" (code, documentation). Projects, unlike groups, do not have member lists, they are open to all who want to contribute. Projects often have code repositories, and are often limited in time. A new project is formed if a group decides it wants to sponsor it. An example of this is the JDK7 project proposed by Mark Reinhold.

Getting the code

The Java source code was previously available as a read-only Subversion repository, but the project has now moved toMercurial (hg). Mercurial is a distributed version control system. If you can read the repository, you can create a local clone - indeed, that is what you must do to work with it. Doing experimental forks of the code is therefore trivial, and it is hoped that increased local influence creates happier participants and a decreased risk of permanent "political" forks. If you haven't worked with Mercurial before, the greatest difference to svn/cvs is that you always have a local clone of the repository to work against, and that downloading patches and applying patches are two separate steps (unlike svn/cvs "update" command).

Once you have downloaded it, "hg help" is your first command. There is a plugin in Netbeans (and in Eclipse too I'm sure) but the original program is run from the command line so I recommend you try it out that way first, to get a feel for all that is possible. A short list of useful commands -

  • hg clone ${localpath_or_url} - create a local copy of a repository
  • hg status - how do your work files diff against your local repository?
  • hg commit - save work file changes to local repository
  • hg incoming - what has changed in parent repository (the one you cloned from)
  • hg pull - download remote patches. Again, this step does not apply them.
  • hg update - apply downloaded patches
  • hg push - send your changes to the parent repository (if you have write permission there)
  • hg merge - merge changes, best done with a tool (kdiff3, meld, Netbeans, Eclipse)

All of these commands take lots of different parameters of course, but rather than me repeating it, there is a really good free book available on Mercurial at

Mercurial extensions

One of the advantages of Mercurial is that it is easy to script extensions using Python. Sun has chosen to use the "forest" extension for OpenJDK, presumably so that subteams can administer themselves more easily. If you have already installed Mercurial, you can download the extension with it, using the following command:

hg clone hgforest

Next you should edit your Mercurial configuration file. In your home directory, create a file called .hgrc and add the following lines to it:

#Mercurial configuration
username = your_name_and/or_mail_here

The username defined there will identify you as the author in the commit metadata. At the public web repository of the code your mail address will be obfuscated, but your username string is not automatically obfuscated in the patches you submit. If you are sensitive about spam/privacy issues you may want to get a separate mail account. It is not improbable that some spamming scumbag clones the repository one day and combs through it for addresses.

Once the extension is installed and configured, some commands will be replaced with their forest equivalent (fclone, fpush), so to finally download the code you do:

hg fclone

Preparing for the build

You should read the README-builds.html page included in the source to begin with, these days it is very informative and helpful. You have to install the usual development libs. What differs OpenJDK from many other projects is that you have to download a bootstrap JDK - I think it is JDK6 now - and also the "binary plugs" which contain proprietary code that Sun doesn't own and did not get permission to release as open source. You do not need the binary plugs if you chose to download the Iced Tea version of the OpenJDK code. The Iced Tea project was created by RedHat and aims to replace all non-open source code so that you can build a completely free JDK from scratch. RedHat has signed the OpenJDK participation agreement I mentioned before, so their fixes will hopefully make it back into the core repository. When that has happened you won't need the binary plugs or a separate download from IcedTea anymore.

I have only built OpenJDK under Linux, but if you are planning to build under Windows there are a few things to consider. First, the compile process is oriented towards a Unix like environment so Windows style file paths, environment variables etc do not work. Therefore you must download and install Cygwin. According to the README-builds file you MUST use Visual Studio .NET 2003 Professional, the 2005 or later versions do not work, at least not out of the box. Luckily, Tim Bell and others are looking at getting the "free-as-in-beer" Visual Studio Express for C++ to work (and in the future hopefully also "free-as-in-freedom" tools).

In theory only tested and perfectly functioning code is in the repository, but in reality people have mistakenly checked in non-compiling/non-working code often enough that it might be an idea to do as Elliotte Rusty Harold suggests - download a source snapshot first and try to get that to build, and then go on and try the latest repository code.


There is a file in the project source code you checked out -


which sets all environment variables needed for the build. Look through it and edit it if needed, and when everything looks ok try running the following commands:

. jdk/make/
make dev-sanity
make dev

The "dev" version of the build is a bit smaller, if you really really want to build everything, including an installer, replace the last two lines with:
make sanity

Once you have built the whole project, you can build just the subprojects you are working on by guild into the corresponding "make" subdirectory and run the "make" command from there, this will save you time. Doing builds of subprojects depends on tools created by the global make, so the first time you must unfortunately build everything.

Code overview

For easier maintenance the source has been split up into separate projects - langtools, jaxp, jaxws projects mainly consist of java code, hotspot is native code, corba is mixed.

The sources for the core Java classes you use daily are usually in
Some of these classes are just interfaces or abstract classes. The implementations are usually in
(These classes in the sun package are sometimes used by applications, but it is strongly adviced that you never do that. It ties your users to Sun's JVM versions, and these classes are not a public API and therefore can change without any warning between JVM releases.)
Operating system/platform specific Java code can be found in
JNI created files usually end up in
but these are usually just header files. All the fun stuff tend to happen in

TODO - expand this part of the article.

Requesting to participate

A lot of the following information is taken from OpenJDK contribution page. First of all print out the Sun Participation Agreement and read it through carefully. Basically you agree to "dual ownership" of the code, both parties can do whatever they want with it without asking the other part first. More details at the FAQ.

If you decide these terms are acceptable, sign it and mail it back to the provided address, or scan it and fax it to them. If you have signed this for any earlier Sun open source projects (Glassfish, Netbeans, OpenSolaris...) you are already covered and don't have to do it again.

Getting started with a bug

First of all find a suitable bug or Request For Enhancement (RFE) in the bug database. If you know of a bug but can't find it in the database, please start by submitting the bug! Note that even though a bug has been accepted into the database, the submitter's synopsis can be misleading or completely incorrect. If there is an evaluation there you are on firmer ground, but I have known these to be out of date or incorrect also, so don't trust everything you read, you must check the code and the specs and think carefully about how things really work, and how they are intended to work. Sometimes bugs are even fixed but not closed in the database. When you have a good bug, search through the mailing lists and see if you can find any discussion about it - perhaps work on it has already started. If there is no discussion, announce your intention to start. Send a mail to the appropriate mailinglist with the subject "{Bugid: Synopsis}". For instance:
162111: Incorrect Descriptor handling in ModelMBean classes

Body of the mail is usually just something like "My name is... and I'd like to get started on this bug". Wait a few days for comments. Perhaps Sun engineers have already started working on this bug, perhaps they will re-evaluate it now and close it for some reason. In general, changing any public APIs (adding new methods for instance) is VERY DIFFICULT. You have to provide a convincing argument why this is needed, if the bug synopsis doesn't make a convincing case you could try to add some arguments to the body of your "starting intention" mail. Also, changing incorrect behaviour that applications already depend on is pretty much impossible - backwards compatibility has been holy so far. Still, just because Sun won't merge your patch into the core OpenJDK repository doesn't mean that others won't find it useful...

Testing changes locally

Before submitting a patch you probably want to try out your changes. If you have compiled with the default build target and everything worked, you will have a newly compiled JDK located at build/{platform}/. One way is to just set the $PATH and $JAVA_HOME variables there and then try running all your favourite Java applications. On the other hand, perhaps you want to try to isolate your changes so you can test just those classes you changed together with an already installed JDK that you know works fine. You do this with the Xbootclasspath parameter. For instance -
java -Xbootclasspath/p:jarname.jar
The "/p" part of the command is important, it prepends classes. This means that if the JVM finds any of the core java classes in the jar files or directories you specified (jarname.jar in my example above), these class versions will be used instead of the internal ones in your installed JDK. You can specify several jar files or directories as parameters.

Automated tests - Unit/regression testing

If you want your patch accepted you must also provide test classes. Most of you are probably familiar with JUnit/TestNG or similar test frameworks. Sun for a long time used an internal testing framework called JavaTest with the "jtreg" extension to run many of the JDK tests. This framework has now been open sourced. You can define test suits in java files, shellscript files or html files. The tests executed by jtreg can test not only ordinary Java files, but also applets and shellscripts. The Java classes you test do not need to implement any special interface, you can define the test to just run the main method of the class. If the process started by the test returns normally (the main method or shellscript finished) the test passed. If the JVM terminates with an uncaught exception, or the JVM or shellscript returns an errorcode (-1 usually) as it terminates, then the test failed. You can run tests with

jtreg -jdk:${jdk_path} ${testdir_or_testfile_path}

I'd like to write more about this works, but documentation is a bit sparse and when I last submitted my patch it was still JUnit that was asked of external submitters. Hopefully this situation will improve.

It is difficult to give any rules for how much testing you should do... if you are just changing how GUI are drawn or documentation you can't do any tests of course. As a rule of thumb, perhaps you should consider spending at least as much time writing tests as you did fixing the code.

Submitting your patch

Now we are finally getting to the fun part! You submit your patch by sending a mail to the appropriate mailing list, with a subject of the following pattern:

[PATCH] 162111: Incorrect Descriptor handling in MBean classes

The mail should contain the following:
  1. A discussion of the change: A rationale (if the bug synopsis didn't have one good enough). Briefly what you have changed and why. If you had any alternative solutions that you rejected, you may want to write a little about why.
  2. A diff in the "unified" format (-u). Remember to write which version of the source you created the diff against!
  3. Your tests classes.
Within a couple of weeks a Sun engineer (or someone with the same responsibility in a project) should reply and say if the patch will be accepted, or if it needs further work.

Making a good patch

Here are a few rules of thumb to maximize your chances of getting your patch accepted:
  • Follow The Java Code Conventions. Your code comments should describe WHY you do something if that needs explaining, not HOW you do it. Writing how you do it in comments is unnecessary duplication, that should be immediately obvious when looking at the code or something is wrong with it. Clear and descriptive variable names, yadda yadda. You know the rest...
  • Idiomatic Java code that is readable even to junior programmers is preferable. Of course you shouldn't avoid writing smart and concise code, but don't show off for the sake of showing off, abuse "clever" tricks to fit the code into a single cryptic unmaintainable line, and so on.
  • Write lots of good tests.
  • Most important rule last - only change what is necessary, nothing else! This is a mistake I did when working on my first patch... Your patch will be carefully evaluated by core engineering teams, the smaller the diff is, the easier it is for them. Never run "fix imports", "autoindent all code" or similar in your IDE, start cleaning up cryptic variable names elsewhere in the class, etc, even if you think the original code looks like complete crap. The patch will probably be rejected immediately if you do. Stick to fixing your original bug. Do code cleanup as a separate patch later that doesn't change any functionality, if you think this cleanup is absolutely necessary for maintainability.
If the patch was not accepted into OpenJDK trunk by Sun, don't be discouraged. You probably learned a lot while doing it. Other projects or repositories may still be interested in your patch.

Another rule of thumb I like is - try to be nice, if you need to criticise try to make it constructive criticism. In my experience Sun engineers are almost always been polite and helpful, but as the community grows some highly opinionated (and also very skilled) open source contributors may not hesitate to let you know if they think your code is poor in no uncertain terms. If that should happen, see it as an exercise in maturity. Thank them (silently if you prefer) for the what you may have learned from the exchange, and disregard any possible personal attacks. Consider that current/future employers may read the exchange one day. The Internet has a very long memory, and your online reputation matters.

What I would like to see

For the OpenJDK to succced, Sun must continue their work to lower the barriers to entry. But a living and vibrant community is not something that Sun can create top-down with a wave of a magic wand, it is something that all of us who are interested in seeing OpenJDK succeed must try to help create. I'd like to see the following:
  • More participants! We want YOU for OpenJDK! There must be hundreds of thousands of active Java programmers on the planet. If only a few percent contributed a couple of good patches each....
  • More information from Sun employees what they are working with. Previously I have seen new contributors who have had their first patch rejected because a internal rewrite/planned rewrite fixes the bug, and they were disappointed. Luckily this situation has already improved now that Sun's engineers use Mercurial, and the same mailing lists for discussions as everyone else.
  • Cleaning up of old and inaccurate information online. The Starter bug list page for instance should be updated, I think half of the bugs on it are closed by now. I would also like it to be expanded so it covers not just individual bugs but whole areas with a low barrier to entry where beginner contributions would be welcome - something like the Linux Kernel Newbies community. Perhaps an OpenJDK Newbies Group could be created?


On the Open Road - series of articles about OpenJDK. Rustys article beat me to the punch by a week or so and made this article somewhat redundant, but it was good to see that I was on the right track.
Kelly O'Hair has loads of information on his two blogs about Mercurial, and building the JDK.
Ted Neward blogs about building the OpenJDK on Windows.
Volker Simonis has two very in-depth articles about HotSpot development on Linux with Netbeans.

Friday, November 2, 2007

Math test finally over

So, I finally have some spare time again, now that I have written my math test. Upcoming blogs will hopefully be about contributing to OpenJDK, and my attempts to install Nexenta/GnuOpenSolaris in order to use DTrace to help improve JRuby, Netbeans and other worthy open source projects.

In the meantime, a short post about games. People have been talking about PC gaming on the decline, but I'm not seeing it. The sales numbers are for US retail stores only, and PC stales are much bigger in Europe, and online sales through sites like Steam. These numbers conveniently also tend to ignore monthly MMORPG sales... if you include all those, I wouldn't be surprised if the PC is actually #1 in sales. I already know it is #1 in quality...

In fact, there are more good games to play than I have spare time. Real role playing games (as I define them.... not action games like Diablo or cliched linear JRPGs, but games where you actually play a role and have an impact on the world through your choices) are having a mini-revival it seems like. Neverwinter Nights 2 was pretty fun, a definite improvement on NWN1 and the closest I've gotten in a long time to recapuring the old Baldur's Gate magic, but I felt it didn't quite live up to its potential. Now that NWN2: Mask of the Betrayer is here, I think it has. There are other modules on the way for that game, both commercial and free (Black Hound and Planescape Trilogy look really promising). Also The Witcher looks good, though I haven't played it yet. Dragon Age should be released soon (I hope). Many shooters are growing up, becoming smarter, and finally becoming more inspired by Warren Specter and less by Carmack. Plot and mood are important. Bioshock, Portal are two good examples. Hey, even adventure games are back! Sam & Max season One was fantastic.

And then there are all the casual games! Bookworm Adventures and Puzzle Pirates are two excellent ones. The last one is even free!

Also thanks to Steam you can get previously hard to find classics like Vampire: Bloodlines and Psychonauts cheaply.

Tuesday, July 31, 2007

Wireless, the eternal headache

New computer means re-installing operating systems, joy. Wireless hardware has always been a constant headache, no exception this time.

Netgear WG121 USB in Windows XP, I had to go through the following steps:
1) Plug it in.
2) When Windows recognizes it and wants to install drivers, you must "cancel".
3) Pop in the CD and use setup.exe to install drivers yourself.
4) Reboot.
5) When windows wants to install drivers again after startup, "allow". Let it search the HD for drivers automatically, it will find and reinstall drivers - from what I can see, it copies from and to the same location.
6) Reboot
7) The Netgear connection wizard pops up and wants to disable Windows' own management of wireless connections - "allow".
8) Wait a couple of minutes while seemingly nothing happens, until the wizard window hangs and stops responding, kill it with Windows process manager.
9) Reboot. Now you can start the wizard from the start menu and you can finally configure settings and start using connection.
10) Discover that the connection hangs while downloading large files - for instance the new Kubuntu 7.04 installation CD ISO.
11) Swear a lot, reboot, download the 2.0 drivers and firmware zip from Netgear's site.
12) Go into control panel, uninstall the original drivers and tools completely.
13) Reboot and repeat steps 3-9, this time with the 2.0 drivers.

Any deviation from these steps will make the driver installation fail and the hardware unusable, you will have to uninstall and restart from step 1.

Netgear WG121 USB in Kubuntu 7.04 Feisty Fawn: This is what I had to go through
1) Read that some people claim it works out of the box. Plug it in, notice that nothing at all happens, plug in long network cable borrowed from work instead.
2) Find the following page.
3) Do NOT download the packaged version of ndiswrapper through Synaptic/Adept package managers, use wget to download the latest version from Sourceforge.
4) Remember to unplug the hardware if you have plugged it in, having it in will cause installation to fail.
5) Compile and "make install".
6) After following instructions on page from point 2 above and nothing works (only one light on device is on, /var/log/messages says probe failed with error code -22) after hours of trying to recompile and modprobe different versions, Google. Try to find relevant information without clicking on links from Google keyword bombing spam scumbags. Eventually I found that Feisty has a regression bug - wrong Prism firmware is included in /lib/firmware for that kernel version. So, download the latest firmware compiled by the maintainer and overwrite one of the files in /lib/firmware/ with a completely different name.... I'd post a link to the detailed instructions of course, if I could find it again! I believe I read it at the Ubuntu bug forums.
7) Reboot, now it works... for around 30 seconds, when it locks up until next reboot. Google some more, find that other people have the same problem but no one has found a reliable solution.

Give up and install the PCI card I bought last time for this. I think it is a D-link card. The drivers for Windows are even more horrible than the Netgear WG121. I haven't been able to get it to work at all with Windows actually, but it works fine with Linux and ndiswrapper. So I have to have two devices, one for Windows and one for Linux.... Bleh.

Perhaps newer generations of hardware are better? Can anyone recommend something that works with a minimum of hassle with both Windows and Linux?

Tuesday, July 17, 2007

Good Chinese food in Stockholm

Unfortunately it is difficult to find good Chinese food in Sweden. I have read that there is actually a reclusive Swedish-Chinese millionaire who lends money to families who want to start restaurants, providing they follow his guidelines. In other words, many restaurants are parts of a franchise just like McDonalds, which may explain why so many of them look the same, have the same muzak, the same price range, and the food at them is so similar and tastes so bland.... To me they fill the price and quality niche between fast food joints and "real" restaurants.

The "Asian restaurant" syndrome is another pet peeve of mine by the way.... Instead of interesting fusions of kitchens with new crossover dishes being invented like in Australia for instance, in Sweden we get generic "Asian" restaurants where sushi restaurants have started to include a few standard Thai dishes on the menu, Chinese restaurants always have some bad sushi, and so on. You get a lot to choose from but very little that has been cooked with any passion or finesse.

Enough negativity. Here are few tips for some better Chinese restaurants in Stockholm:
  • Lao Wai is a small vegetarian restaurant and definitely number one on my list. They always use authentic and fresh ingredients, for instance Chinese rice wine instead of sherry, never canned products or powders. They import Oolong tea from their own plantation and so on. They cook and serve orders to the table one at a time to be eaten immediately, so you will get the best experience if you share dishes with your friends the traditional way. They have tofu that tastes just like smoked sausages or chicken, so even meat eaters who normally don't like vegetarian food should enjoy it.
  • Formosa is the best one in Gamla Stan (Old Town) that I know of. Very crowded with Chinese tourists who come by the busload. Noodle soup with meat, shrimp and pak soi is my favourite.
  • Ming, just next door to the Crystal Plaza hotel used be really good, but I haven't eaten there in a while and I read in the papers that their star chef from China didn't get a renewed visa despite protests from the management of the restaurant and the hotel, so I'm not sure if it is still as good as it used to be.
  • Dragon House at Hornstull. This is a restaurant that gets very varied online reviews, from full marks to none, so either a competitor is trying to discredit them with a smear campaign or they have different chef teams with wildly varying skills. I have never been disappointed, but I always order from the special "traditional Chinese" menu and stay away from the buffet, the Thai food and the sushi. I recommend the small spicy chickens (beware of sharp bones though as they don't fillet the chickens, they just chop them up traditional style bones and all with a big meat cleaver) and the seafood pots with Chinese mushrooms (Seven Thunder Seafood I believe one is called). For the brave, they also have dishes like pigs stomach or crispy fried tripe with szechuan peppers (I don't know why so many are queasy about it though, the same people happily eat sausages after all). This is another restaurant where you should go as a big group and share the dishes with one another.

Wednesday, July 4, 2007

Opinions about Ruby

I have been reluctantly been forced to admit that some of the stuff you can do with Ruby is pretty damn cool. Now that I have had to try to debug a non-trivial (to me at least) application, I feel I can have an opinion on Ruby, and do this based on experience rather than prejudice.

First of all, documentation is poor for many libs. This is something that was raised at one of the general sessions at RailsConf 2007 in Portland, and got a very loud applause. I'm not just talking about tutorials or examples, many of them lack even minimal rubydocs. Many of them also do very little logging.

Secondly, I like checked exceptions. There, I've said it. This particular application failed silently somewhere, and from the few things I could get from the logs it seemed like a problem with SSL. After messing around for days trying to get this to work, I noticed something odd. At one place in the code, I had this:
@@services[wsdl_class].wiredump_dev ="#{RAILS_ROOT}/log/#{RAILS_ENV}.log")
@@services[wsdl_class].options['protocol.http.ssl_config.verify_mode'] = OPENSSL::SSL::VERIFY_NONE

Now, if you switch around those lines, you get something funny, the wiredump logs aren't written. In fact, you could change it to
@@services[wsdl_class].options['protocol.http.ssl_config.verify_mode'] = blahblahblah
for the same effect. This is what finally clued me in to what was going on. In a completely different place in the codebase, the "model" code that fetches the SOAP object does a begin/rescue, assuming that any exceptions that occur are network related. I think that this was a valid assumption when the code was written, but later on some code had been refactored and some meta-programming magic goes on in a sub-lib to generate convenient helper classes and methods, and if you have a bug there, the generated exception is also silently swallowed and discarded. And this was application code by a very experienced programmer. Once other less experienced Ruby programmers (like me!) starts to mess up the code it quickly gets very difficult to understand what is going on.

True, you can sprinkle your code with
try {
} catch (Exception x}
in Java as well, but I believe this is rarer or mainly done by beginner programmers. Some very good frameworks to it too, but generally wrap the exception in their own layer appropriate exception and passes it on. Knowing that introducing a new checked exception breaks client code does make Java code less malleable, but on the other hand it might make the lib developers more careful about how they structure the code, and reminds them when they have to handle exceptions that sub-libraries might throw themselves, and when they can wrap the the exception in another (layer appropriate) exception and pass it on. I might be wrong though, we'll see if my opinion changes as I learn more of Ruby and other languages.

Tuesday, June 19, 2007

Configuring Ant in Linux

I solved this problem a couple of years ago, but now it popped up again and I had forgotten how to solve it and wasted some time. So for my own sake, and in case people are Googling for it:

If you get
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/tools/ant/launch/Launcher
when running ant first of all run "which ant" and "which java" to see which programs are being executed. You might discover (like I did) that the server is running an old gcj and there is an old systemwide ant. Export ANT_HOME, JAVA_HOME to correct the dirs. Also
export PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$PATH

If you STILL get NoClassDefFoundError, you might find that there is a
file which trips you up, you might have to set ANT_HOME and JAVA_HOME properties there too! Or like Michael-N suggests, run ant --noconfig -version

The best solution though, tends to be to uninstall gcj, as well as all old system wide java tools that came with your distro. Instead of using RPM or similar, download the latest source directly from Sun. Things might improve now that Java is open source though.

Saturday, June 9, 2007


So I finally gave in and got a real blog, where I previously only had a few random Slashdot journal entries. Blame this guy! On a serious note, what convinced me was his argument that already today many in the computer industry find good blogs a more useful indication of a persons skill and history than does a CV or a long list of certifications. I like my current job, but I suppose I will switch some day, so I might as well get started.