2010-04-29

Finding out where your class files are

Sometimes, when you are writing a program, you need to install data (e.g. by unzipping example files) or to find additional data (e.g. plugins). If you know the location of your class files, you can put the data close to them or start your search there. Your program will usually be packaged as a JAR file, so this scheme allows you to keep everything in the same directory. But any solution should also work for unarchived files, because you want to test while developing your (un-jarred) code. Until now, I’ve always used hacks involving Class.getResource() and looking for exclamation marks in the returned URL to find out if the program is currently running from a JAR. Recently, I’ve discovered a simpler solution (source):
ProtectionDomain protectionDomain = HyenaDesk.class.getProtectionDomain();
File codeLoc = new File(protectionDomain.getCodeSource().getLocation().getFile());
For example, this code computes the following two values for codeLoc.
  • Unarchived: /home/rauschma/workspace/hyena_desk/bin
  • JAR: /home/rauschma/workspace/hyena_desk/build/hyena_desk.jar

2010-04-28

Mac OS Eclipse: preventing GUI tree memory

Since Mac OS Eclipse migrated from Carbon to Cocoa, the tree graphical widgets have changed their behavior. Previously, if you had a subtree that was deeply expanded, if you closed and re-opened its root, only its children would be visible, collapsed. With Cocoa, all of its descendants appear in the same fashion as before. This makes it difficult to clean up deep expansions.

Fortunately, there is a way to get the old behavior back, via a key combination: Right and left arrows without any modifier key open and close a folder. If you hold the option key, the right arrow expands everything (=be careful with that in the Eclipse Package Explorer) and the left arrow collapses everything. The next time you open a node you have open-left-closed, only its children are visible.

2010-04-25

Education and the myth of the correct solution

Suppose you have to solve a problem. An idea that frequently comes up next for me is that there is a correct, a perfect way of solving it. The associated image is one of a solution that is “out there” and just has to found. Obviously, this image has a paralyzing effect, because you can fail, by not finding the solution. That is, it stifles creativity. Ken Robinson has talked about how our education system often fosters this viewpoint. To illustrate, he mentions divergent thinking (the full talk is also available), coming up with as many and as diverse solutions as possible, one of the elements of creativity: A study revealed percentages of genius-level divergent thinking among test subjects. Ages 3-5 the percentage was 98%, ages 8-10 it was 32%, ages 13-15 it was 10%, and finally ages 25+ it was only 2%. Something happens that makes the divergent thinking go away. This is sad, as many of the problems modern society is faced with can only be solved by this kind of thinking.
Thus, I think it is better to replace the mental image of the perfect solution with one that involves creativity. One actually creates something new, that never has been done quite this way before and never will be afterward.

2010-04-18

Speeding up GWT

I’ve recently come across a few great resources on how to speed up client-side GWT:
  • Effective GWT: Developing a complex, high-performance app with Google Web Toolkit” Describes interesting tricks for making your application faster. One of the main challenges for them was to make everything work with IE 6. Interesting points were:
    • DeferredCommand can be used to execute code after the current invocation. Very handy in event handlers where performing complex user interface changes can lead to weird behavior, such as the “bleeding through” of return keys, etc. This may well have been the most important take-away of the talk for me (as I am currently not too concerned about performance in my projects).
    • Also cool: They describe how to go from GUI sketches on paper to a PhotoShop mock-up to a GWT implementation.
    • Generating HTML (on the client) and letting the browser parse it is fastest for generating DOM. I’m assuming that is as far as IE 6 is concerned where each created JavaScript object is very costly.
    • Foreach is slow, because an iterator (=JavaScript object) has to be created. With an integer index, this does not happen.
    • Programmatic manipulation of styles via widget.getElement().getStyle() is slow, using CSS is faster.
  • Simpler and Speedier GWT with Server Side RPC Serialization” It is a common technique to make the first remote procedure call (RPC) directly after the page has loaded. To improve performance, one can simulate that RPC and embed the result inside the web page on the server. The previous talk mentioned this trick which lead me to investigate further and find this article.
  • Resource Bundles and Linkers in Google Web Toolkit” This talk goes further into details how data can be served more compactly. It was linked from the previous article.

2010-04-02

GWT, an important Java technology: features, future and wishes

The Google Web Toolkit (GWT) has become one of the most important Java technologies, as it gives that language a credible web platform strategy. I used to be doubtful of the extra compilation step and developed with DWR and Dojo, but have since become a convert. Cool features:
  • A single code base for client and server.
  • Great development tools, via Eclipse: refactoring, code navigation, etc. This was one of the reasons the creators of GWT chose Java as the source language. Server-side JavaScript certainly would have been a possibility, and compiling JavaScript to JavaScript is not unheard of, either.
  • Quick turn-around: after making changes, the server and client can be reloaded quickly to reflect those changes (only the first start of the client is a bit slow, subsequent reloads are fast).
  • Easy install of development tools: All you need are two Eclipse plugins and you are done.
  • IDE support: One of the Eclipse plugins helps with various coding tasks and errors (such as keeping Service and AsyncService consistent).
  • Easy deployment of applications: GWT produces a WAR file. Drop it into a servlet container such as Jetty or Tomcat. Done.
  • Fast and reliable GUI layout: Still limited compared to what Swing and SWT offer, but for the first time acceptable.
  • True client-side technology: GWT is tightly integrated into the browser environment and stays close to JavaScript. This makes it easy to keep pace with the rapid progress that browsers are making. GWT is also one of the few Java frameworks that can be used to write offline web applications, because it relies so little on the server.
Extending the basic features: For someone who has already programmed Swing or SWT, it is very easy to get started with GWT. After a while, you will probably be looking for advanced features. Luckily, a lively community has grown around GWT to fulfill this kind of need.
  • gwt-dnd: Implements Drag and Drop in pure GWT.
  • Smart GWT: GWT does currently not have too many widgets. Smart GWT is a GWT wrapper around the SmartClient JavaScript library which has lots of widgets. While GWT is really good at this kind of wrapping, there is some baggage involved: load times of web applications increase, and there is a new API to learn.
  • GWT Mosaic: Also extends GWT, but as pure GWT and with less widgets/features.
  • Other wrappers for JavaScript libraries exist. But beware, some of them have very restrictive licenses.
What the future will bring:
  • Currently, the GWT incubator hosts experimental features. Long-term, its parts will be migrated to either separate projects or the GWT core.
  • A post reveals interesting things about GWT’s future. For example, it will get data-backed widgets.
What I am missing:
  • More widgets: The current widgets are limited (menus don’t ensure that they are visible, no support for shortcuts, no resizable dialogs, no context menus, etc.) and there are not enough of them. I expect this area to improve quickly, though, now that all the important foundations have been laid (event handlers, modular CSS, layout panels).
  • Switching back-ends: Many computers are only intermittently online. Programming an offline mode for a GWT application is difficult, because the server usually hosts important functionality. A hypothetical way of solving this is by installing a back-end locally. The client could switch between this back-end and the server. Managing installed back-ends should work similar to Java Web Start. A local back-end could also provide a GWT application with desktop features, because it has access to desktop resources such as the file system.
  • Better client-side modularity: I love Eclipse’s modularity, especially when working in a team. You can have a core plugin that is extended via other plugins residing in separate projects. It would be nice if one could extend a GWT application in a similar fashion. On the server side that is possible via OSGi. On the client side, that is currently not possible.
  • Sending binary data from server to browser: For example, one cannot create images on the server and send them to the client via RPC. Data URIs are a work-around, but a poor one.
  • Annotations for hiding code from the client: If an object is transferred back and forth between client and server, there are often some server-only methods. An annotation would allow one to hide those methods. There is an issue for this feature. You can star it, if you would like to see it fixed.
  • Instantiating classes via class literals: There is no Class.newInstance() in client-side GWT. One has to resort to sending a factory to the client.
  • Two two useful methods: Class#getSimpleName(), String.format() are simple to implement, so I don’t see the reason for not doing so in client-side GWT.
  • Simpler unscrambling of GWT method names: If you want to invoke GWT code from JavaScript you need to prevent GWT from scrambling your method names. Doing this is a bit more complicated than it should be. A simpler solution would be to add an annotation to methods whose names one wants to preserve.