Wednesday, March 24, 2010

300 Episodes

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


We had a milestone in the podcast last week: 300 episodes. That's more than one episode per week for the 4½ years we've been doing it!
We spent our 300th episode as a retrospective, looking back at highlights over the years.



We looked up some statistics, too. The most amazing one (to us) is that we are now up to 15,000 downloads per episode! Our feedback alias has over 10,000 e-mails (not counting spam). And our discussion forum has nearly 20,000 messages at this point! Wow! Thanks for listening and participating!






(Photo by Gunnar Hillert)


Thursday, March 18, 2010

Java Posse Roundup

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


I've spending the week in beautiful Crested Butte, Colorado at the Java Posse Roundup. It's the fourth year in a row, with record attendance. And as always, it's been fantastic. It's hard to explain an Open Space conference - it doesn't sound like it would work, and I was personally surprised to see how well it worked when I attended the first time. Now I simply expect it, and it always delivers. One key reason why this open space conference works so well compared to say "unconference" events attached to major face-forward conferences is that you need to be away from everything and really immerse yourself - and here up in the Rockies we certainly are isolated!



The day before the conference started we had a "Languages Dojo" day where people pick different languages they're interested and go off building something. We had planned in advance to build a JavaFX version of the "Ohm Writer", a Zen-like text editor that is full screen, has nice relaxing background music, background sounds and typing sounds. We had a great time, and made a lot of progress. Unfortunately, we spent a lot of the day fighting with git (the version control system). I'm a very happy Mercurial user, but I've had a little bit of git-envy since I know it can combine local changesets into a single changeset to be pushed to the repository. I could see myself using that a lot. And setting things up on github for collaboration was very easy. But that's where the fun ended - nothing worked, simple merges aborted, error messages were completely unhelpful, and in general we repeatedly ended up checking out new clean workspaces and hand applying changes. I liked Mercurial before but now I appreciate it even more. (I hear the guys who were doing functional programming also were ripping their hair out with git. P.S. Joel Spolsky just posted a Mercurial tutorial).



The app is functional, and more importantly we made the editor start up immediately, load images and audio in the background and gradually fade in the image as soon as it's available. We also had difficulty playing the keyboard "click" sound until we realized you don't want to just repeatedly call play() on a media player -- you have to reset it -- either setting mediaPlayer.currentTime = 0s or calling mediaPlayer.playFromStart().



We also ran into another bug -- and this is a gotcha I've seen before, so it seems useful to highlight it here: For JavaFX Strings, null and "" are the same! Therefore, you don't want to write code like this:


while ((line = reader.readLine()) != null) {
// use line
}

because this will terminate the loop as soon as you reach an empty line!! Be very careful about checking for nulls explicitly when dealing with Strings.



We've also had Lightning Talks in the evenings. If you're not familiar with Lightning Talks, these are very quick presentations, one after the other, on any subject, but limited to 5 minutes. Yes, with a HARD 5 minute limit. The advantage of limiting the lightning talks to 5 minutes is that it forces the presenter to really focus on the interesting parts of the subject, and if it's really not interesting, at least you're only bored for a couple of minutes! The topics this year were really great though - there was even a fire-eating demonstration!
One way to keep track of the time is to use a countdown timer. We wrote one in JavaFX last year, which displays a classic countdown timer (imported Photoshop graphics) and a sound file playing as the timer is expiring. It's available as a webstart app if you want to run it for your own lightning talks, or you can study the code.




In addition to the morning open space conference sessions, the evening lightning talks, the progressive dinners, we've had some afternoon technical presentations and coding sessions -- check out our improvised projector screen in our living room:



Monday, March 1, 2010

Using Mercurial over ssh without typing the password

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


We're using Mercurial. Our release engineering servers run web servers, so we can browse our repositories, just like the public NetBeans ones at http://hg.netbeans.org, and pull down new changesets anonymously. However, for authentication purposes, we also use ssh, so all pushes to the repository has to go through ssh.


$ cat .hg/hgrc
[paths]
default = http://our.server.sun.com/our/repository
default-push = ssh://our.server.sun.com//our/repository

(P.S. Notice how there are 2 slashes in the SSH path and only one in the http path - if you forget about that Bad Stuff(tm) happens.)



This means that whenever I pull (or determine incoming changes via hg incoming) it executes immediately, but whenever I want to push (or determine outgoing changes), I need to supply a password. And let's just say typing my password is not easy, since the password requirements at Sun (and shortly, Oracle) are really strict - no nice, short and simple passwords here!



I've been putting up with it for a year now - after all, it's just a couple of seconds here and a couple of seconds there - but I knew it should be possible to fix this, since back in my hardcore Solaris days I had all this stuff configured correctly via the ssh key agent so that I could ssh from one account to the next. On the other hand, I've googled it (mercurial + ssh) a couple of times, and the information I've found has always been for doing more complicated things (1,2) than the simple authentication setup I wanted. So I just put it off.



I decided to bite the bullet and look into configuring it - and it was really trivial. I'm bummed I haven't tried earlier! I thought I'd write this up in case it helps anyone else in a similar situation.



The reason it's trivial, is that it turns out there is nothing specific about using Mercurial here. This is actually a case where Googling something was harmful! If I had just tried it, instead of searching for a recipe and getting confused, I would have had this set up a long time ago! Hopefully this blog entry will help anyone searching for "hg ssh passwords" ! Anyway... You just need to ensure that you can ssh directly into the system you are trying to push to, and if you can do that, then mercurial can do the rest. And this setup is easy and well documented.



First, you need to generate a local key.


$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/tor/.ssh/id_rsa):
Created directory '/Users/tor/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/tor/.ssh/id_rsa.
Your public key has been saved in /Users/tor/.ssh/id_rsa.pub.
The key fingerprint is:
... (omitted) ...

Next you need to copy this file to the server and call it ~/.ssh/authorized_keys. Actually, that file may already exist and you really want to append to it, not replace it. So first ensure the directory exists:

$ ssh tor@our.server.sun.com mkdir -p .ssh
Password:

And finally copy your authentication key over to the server:

$ scp .ssh/id_rsa.pub tor@our.server.sun.com:.ssh/authorized_keys
Password:
id_rsa.pub 100% 422 0.4KB/s 00:00

That's it! Now try logging in again:

$ ssh tor@our.server.sun.com

On my Mac, this actually pops up the system authentication dialog:



Not only can I enter my password in the dialog, but I can tell it to remember this key in the keychain, and from now on, the system supplies the password to ssh when it wants to log in to hosts.

$ ssh tor@our.server.sun.com
Identity added: details omitted
Last login: Mon Mar 1 19:22:18 2010



And now, the whole point of this exercise -- I can run "hg out" and "hg push" (as well as scripts which operate over multiple mercurial repositories) without the need to type that annoying password again. On the other hand, how will I remember it now that I'm not repeating it like a mantra dozens of times per day?


$ hg out
comparing with ssh://our.server.sun.com//our/repository
searching for changes
no changes found



P.S. Here's a copy of my own authentication keys in case that helps you configure your own system. Please don't use these to log into our system.


Thursday, February 11, 2010

How to Render a JavaFX Node into an Image

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


Sometimes you want to render a Node tree into an Image. For example, you may want to do it for performance reasons (such as this example), or you may want to create thumbnail views, or perhaps you want to create a nice drag & drop effect where there is a ghost image of the object being manipulated showing both the current position (the real node) and its target position (its image).



There are some solutions posted for this, but they rely on pretty deep ties to AWT and scenegraph internals. There isn't a way to do it using public APIs yet, but here is a simpler solution. This uses a method on Scene to render the scene to an image, so the trick is to temporarily remove the Node from its current location in the node hierarchy, place it in a new Scene, render the image and put the Node back. This is all pretty simple - you just have to take care of some minor details - like the fact that the scene render will render from (0,0) to the size of the scene bounds, rather than from minX to maxX and minY to maxY. So, we have to add a reverse Translation to place the image back. There is also a problem that the scene render will truncate the bottom and rightmost pixels, so we need to explicitly set the scene size and padd it by 1. And finally, with CSS in the picture we want to duplicate the stylesheet reference from the Node's scene in the render scene, and we also need to preserve the style context. (There are more issues here around CSS; it is a key new feature in JavaFX 1.3 and central to the controls, and there are implementation aspects here for when the CSS phase is running, and it turns out currently the layout styles stay intact - they only get recomputed on the next layout pulse - so this all works beautifully. But the implementation is changing a lot these days so this may need tweaking before this ink dries!)



The only limitation here is that we need to be able to move the Node to render it - which means you cannot render any Nodes that are bound to its parent, e.g. you have a parent group whose content property is a bound sequence including the Node.


http://piliq.com/javafx/?p=1108
http://forums.sun.com/thread.jspa?threadID=5392972

Note - NOT official APIs - much cleaner.
Limitation
Couple of necessary tricks: must set scene bounds, and shift it to (0,0); scale

def platformImage = scene.renderToImage(null);
image = Image.impl_fromPlatformImage(platformImage);

Anyway, I wrote some code to do this today. This doesn't only render the node; it also has the possibility to scale the image if its width or height exceeds a certain number. We do that because in the authoring tool we show a little preview of the selected component, and this uses the render to node facility.
(Screenshot here)


My Test Environment

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


Last year I documented my setup for running unit tests on my Mac. The solution relied on a quirk of how the window system on the Mac worked. And unfortunately, when I upgraded to Snow Leopard a few months ago, the solution stopped working.



However, after trying a few things I've found a new setup which works -- and thanks to some other improvements I now have a better setup than ever!



In short,


  • I run the unit tests via Hudson, the continuous integration server. The tests are running on a different account on this Mac, such that
    the UI tests never interfere with my work - no focus loss, no windows popping up, etc.
  • I use a special Hudson plugin to filecopy my source tree to the build server repository, such that I don't have to check in the code I want to run tests again.
  • Since Hudson is running locally it has access to my audio, so I have it speak when the build is done (and whether it succeeded or failed) so that I know immediately whether to push my changes or investigate the build or test failures.



The tri
AUDIO


Friday, December 11, 2009

How to determine the JUnit 4 current test name

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


In my unit tests I often want to know the name of the test that is executing. For example, I often want to have the golden file (expected test output) computed automatically from the testname. As another example in my JavaFX testing, I often generate screenshots inside failing tests and it's useful to name these screenshots by the failing tests.



In JUnit 3 this was simple, since your testcases would extend a builtin JUnit class which had a method you could call to return the current test. However, with JUnit 4 that's no longer possible. I've googled and found the "correct" way to do it - using a special @RunWith to run the test class - but I find that solution unsatisfying. My utility methods which are invoked to read golden files and screenshot etc are in one place and I now have to decorate all my tests. Besides, I already have a @RunWith annotation on my tests because I want to run them on the event dispatch thread so I have a special test runner for that.



So, I've found a better way to do it. Better for me I mean - this may have problems and limitations I'm not aware of, but for all of my tests this worked wonderfully, and doesn't have the @RunWith requirements (though note that I don't do multithreading in my tests, other than invoke them on the event dispatch thread, so if you try to call this from a thread that didn't invoke the test it probably won't work):


public static String getTestName() {
// Try to find a method on the stack which is annotated with @Test -- if so, that's the one
StackTraceElement[] elements = new Throwable().fillInStackTrace().getStackTrace();
for (int i = 1; i < elements.length; i++) {
StackTraceElement element = elements[i];
try {
Class clz = Class.forName(element.getClassName());
Method method = clz.getMethod(element.getMethodName(), new Class[0]);
for (Annotation annotation : method.getAnnotations()) {
if (annotation.annotationType() == org.junit.Test.class) {
return element.getMethodName();
}
}
} catch (NoSuchMethodException ex) {
} catch (SecurityException ex) {
} catch (ClassNotFoundException classNotFoundException) {
}
}

// Just assuming it's the calling method
return elements[1].getMethodName();
}

As with most of my test utilities, it's a public static method living in a class called TestUtils, which I statically import from my test cases such that I can simply reference the test name getter like I would in the JUnit 3 days:

import static org.junit.Assert.*;
import static my.package.name.TestUtils.*;

/* ... */

screenshot(scene, getTestName());

By the way if you're using JavaFX you might be interested in the screenshot utility method. It's really simple:

public static File screenshot(Scene scene, String fileName) throws Exception {
BufferedImage image = (BufferedImage) scene.renderToImage(null);
if (!fileName.endsWith(".png")) {
fileName = fileName + ".png";
}
File file = new File(getScreenshotDir(), fileName);
file.createNewFile();
ImageIO.write(image, "png", file);
return file;
}

(where obviously getScreenshotDir() returns a File folder where you want your screenshots generated. A decent default implementation is return new File(System.getProperty("java.io.tmpdir")); ...)


Sunday, November 8, 2009

JavaFX Coding Conventions

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


I've been writing a lot of JavaFX code over the last year. After some tweaking I've arrived at a style that I like a lot. I notice that even on my team there are some variations in how people format their code, so I thought I would document what I like in case this helps others get started. (I did a quick google search and didn't find any JavaFX coding convention documents anywhere. The closest thing I found was a blog entry, but while it contains a lot of good advice, the style it recommends does not match the practice of the JavaFX team (or the Sun Java style) either). Therefore, I thought I would document what I consider good JavaFX coding conventions.



Rather than post them here in a blog entry, I placed them in a Wiki page such that they can easily be improved and kept up to date as I get feedback and in case I change my mind :)



You can find the coding conventions document here:


http://wikis.sun.com/display/JavaFxCodeConv/Home



P.S. I will be speaking at Devoxx in Antwerp, Belgium next week! Hope to meet some of you there!