Feeds:
Posts
Comments

Word has probably leaked around the InterTubes by this point, and it is in fact true, that I am now working on the JDK.

My new job (alluded to in this blog post from Joe Darcy) is to run through the JDK libraries and upgrade the code to use new language features of Project Coin (features listed here, JSR here). We’re concentrating on four of the Coin features, namely

I’m working on diamond first. I’ve actually been working on this for a few weeks, but a lot of this time has been spent getting up to speed, pulling over and building OpenJDK (most of this work is being done in the open), understanding testing requirements, development procedures, and so forth. So it wasn’t until earlier this week that I pushed my first changeset into OpenJDK. This changeset was a pass over the java.io, java.lang, java.sql, and java.util (exclusive of java.util.concurrent) packages to upgrade them to use the diamond operator. This consisted of a couple hundred conversions spread over 71 files. After hitting a few other areas of the JDK with diamond, I’ll move on to other Coin features.

First, what is this “diamond” operator?

If you’ve ever written any generic Java code, you’ll understand that it can get quite verbose. The “diamond” operator is a new feature in JDK 7 that allows the programmer to omit the type arguments in the construction of a generic object. The compiler will infer the proper type argument. Actually, the diamond “operator” isn’t an operator at all, it’s an empty type argument list. But it looks like a diamond. For example, instead of

List<String> myList = new ArrayList<String>();

one can simply write

List<String> myList = new ArrayList<>();

Big deal, so the code gets a bit shorter. Who cares? Well, sometimes generic types can get pretty complicated. Consider the following:

Hashtable<String,Hashtable<String,Vector<String>>> table =
    new Hashtable<String,Hashtable<String,Vector<String>>> ();

This can be shortened to:

Hashtable<String,Hashtable<String,Vector<String>>> table = new Hashtable<>();

This isn’t some crazy hypothetical example; this is from real code! The conversion hasn’t been integrated yet, but you can see the original code in src/share/classes/sun/security/krb5/Config.java.

This raises the question of how I found sites where diamond conversion could be done. Fortunately, there’s some pretty good tooling that does the actual finding and fixing almost automatically. I’m using Jackpot, a syntax-level code pattern matcher and transformer. Somebody has already written a Jackpot-based diamond converter, so all I have to do is run it. I’ll dig up and post more information about Jackpot in the future. Basically, though, it’s the same technology that underlies some of the hinting and refactoring features in NetBeans 7.

Actually, making the code changes is the easy part. The hard part is in “all the rest of the stuff.” That is: breaking down the JDK libraries into suitable chunks, filing bugs, sending webrevs around for review, testing, pushing changes, updating bugs, and keeping track of several changesets all at different stages of the process. It’s not really that hard, but it is a fair amount of work, much more than the code changes themselves. Isn’t that always the case?

Although the diamond conversion seems simple, it belies a surprising amount of complexity. I’ll cover some of those issues in future posts. Meanwhile, enjoy the JDK7 library code as it becomes more fresh and minty!

JavaOne is over! But before we cover the last day, back to day 3.

I’m still marveling about the Treasure Island party. Terri Nunn of Berlin said that “Oracle gives the best f*****g corporate parties!” and she’s probably right. I have never been to a corporate party on this scale, well, except for last year’s Oracle party. In fact, I’ve never been to a party of any kind that big, ever.

There were almost too many bands. I would have liked to have seen the English Beat but they played early and by the time we got onto the island the set was almost over. We heard some of Berlin but we were trying to get food at the time. I caught most of Don Henley’s set, which was great. Like all of us, he’s getting older, but he seems to be taking care of his voice. He sounded pretty good. I popped over to see the Black Eyed Peas for a little bit, but I just don’t get them. I’m really out of touch. When people started talking about Fergie I thought “What does the Duchess of York have to do with this?”

* * *

Looks like highlights videos from the keynotes are up on the web now. Check out http://medianetwork.oracle.com and click on News and Events and then choose JavaOne or Oracle OpenWorld.

* * *

We had another fabulous lunch at Henry’s Hunan!

* * *

Today’s sessions included Hardcore CSS with Rich Bair and Jasper Potts. I knew most of this stuff since I did my share of work on it in JavaFX, and I wrote a bunch of the manual, but I wanted to be there and show support for the team. The power of using CSS to control region backgrounds and borders and shapes is really amazing and I give Rich and Jasper a lot of credit for thinking it up and implementing most of it.

I also attended Rich GUI Testing Made Easy given by my colleague Alex Ruiz and Yvonne Price. The talk was basically about using the FEST to test Swing GUIs. The code was a bit small to read but I picked up on a few key concepts.

The last session I attended was Concurrency Grab Bag by Sanjin Lee of eBay. This was a discussion of various concurrency issues and “gotchas” they’ve run into at eBay. I was familiar with most of the material already but it was good to see a treatment of the material rooted in practice, as compared to the somewhat more academic approach from people like Goetz and Lea. I’d have thought that the conference was winding down at that point, but the session was packed and there were lots of questions. In fact, I think this was a repeat performance of the talk. The earlier one was probably so popular that they had to schedule a repeat session. [Update: slides here.]

This session was in fact in the last session slot of the conference. The audio tech put on Scott McKenzie’s San Francisco (Be Sure to Wear Flowers in Your Hair) as people were leaving the room, which I thought was a nice touch.

* * *

I usually find the end of a conference a bit melancholy, as people drift away, take off early to catch their planes, leaving the final sessions sparsely attended and the conference center lonely and empty. This was a bit different. The conference hotels were as crowded as ever, buzzing with new batches of tourists, business travelers, airline staffs, etc. checking in.

Workers were scurrying about tearing down all the JavaOne and OpenWorld paraphernalia. A few JavaOne attendees were hanging around. It was pretty easy to spot them: developers’ sense of fashion contrasted sharply with the snappy Japanese airline crew uniforms and with the trendy European tourists. Oh, the laptops helped give it away too. 🙂 I wandered around a bit longer but it was clear that there was nothing left for me to do but go home.

On that note it’s time for me to recap of my impressions of the conference.

This JavaOne was unique in many ways, not only because it was the first run by Oracle, but because it was the first not in Moscone. Sure, there were activities and events and keynotes at Moscone, but those were primarily OpenWorld events. JavaOne itself took place in two conference hotels, the Hilton Union Square and the Parc 55. (The third conference hotel, the Nikko, seemed dedicated to Oracle Develop sessions.)

I have to say that I didn’t like having the conference in the hotels. Even within the same hotel, the rooms were fairly spread out. Then there was the matter of getting between the hotels. It seemed like you were forever going through the back door to get in. At the Hilton, you either walked in through the garage or you used the employee entrance! (But the latter made it easy to punch your Hilton employee time card on the way to the next session.) The hallways were narrow and between sessions they were quite crowded with people trying to get from one area to another.

The rooms were all too small and so they filled up quickly — too quickly. As an Oracle employee I couldn’t reserve places in the session rooms. This was irritating but understandable — paid conference attendees should indeed have priority. But I also heard that even paid attendees had trouble getting in. Some popular sessions were filled even before the conference started.

Since the conference was spread out, there were no obvious gathering places like there were in Moscone, like the movie/game area upstairs in Moscone South or the beanbag area downstairs in Moscone North. If you hung out in one of those places for a few minutes, you’d be guaranteed to see someone you knew and hadn’t seen since last year’s conference. This kind of networking is what conferences are all about! In the hotel setup, the foot traffic all led through various rabbit warrens of corridors, so there was no central gathering place or main artery of traffic. Things just seemed all scattered and disorganized and it was really hard to find people. There were people I knew were at the conference, but I just never ran into them. That didn’t seem to happen before.

It’s not at all clear to me that there is any benefit of combining OpenWorld and Oracle Develop with JavaOne. (With the possible exception of JavaOne attendees getting to attend the Treasure Island event.) I don’t know if there was any cross-pollination. The only JavaOne things at Moscone were a couple keynotes; everything else there was OpenWorld stuff the suits attended. Also, as I mentioned, Oracle Develop seemed segregated in the Nikko. The only effect that combining the conferences had was to make things more crowded and expensive and to push JavaOne out of Moscone.

The technical program seemed a little flat as well this year. Maybe this was because there were some talks I wasn’t able to attend because they were full. It also might have been because of Google’s last-minute pullout. I heard they had 13 sesssions and 6 BOFs. But I also think it’s because of a development slowdown caused by the waning days of Sun and the transition to Oracle. It took a lot of energy to get through that, and a lot of people left before and during the transition, so that took away from developing stuff that could have been presented at the conference. A lot of plans and roadmaps were announced, and there seems to be renewed momentum around Java development at Oracle, so let’s hope this will lead to more material for next year’s program.

JavaOne 2010 day 3 update

One thing I forgot to mention from day 2: the technical general session with Mark Reinhold and others. I was mainly interested in Reinhold’s stuff. He gave a brief overview of JDK7 and JDK8 roadmaps, including some interesting background on closures (the Lambda project) and default methods. Unfortunately this stuff won’t be in until JDK8 (2012). It’s notable how much closures have evolved from the CICE and BGGA proposals that have kicked around for a couple years, though the current Lambda proposal bears some resemblance to CICE to my eye.

* * *

I attended a Java Desktop lunch at Anzu. There were about 30 people there, including lots of FX folks, but also lots of others, including a special surprise appearance from James Gosling! James isn’t officially at the conference but is hanging around and meeting with lots of people. After his departure from Oracle he’s turned into a bit of a rabble rouser. See his eWeek interview for example.

* * *

Stephen Chin and Dean Iverson had a BOF on JFXtras. Historically the role of the JFXtras project has been to fill in the gaps and to add “extra” features that aren’t in the core JavaFX platform. With the transition of JavaFX from JavaFX Script to Java as the main API and implementation language, the role of the JFXtras project will change. Specifically, Steve announced an initiative to continue the development and evolution of the JavaFX Script language in open source, and eventually to rehost it on top of the new Java-based JavaFX APIs when they are delivered. Steve already has a grab bag of features he wants to add to the language, such as a map type and the ability to bind over a key in a map (even if it’s not yet present in the map). Steve’s provisional name for the project is “Visage.” He doesn’t have a site up yet for this effort, but keep an eye on his blog. I’ll update this post with links when they become available.

* * *

Kevin Rushforth and Jim Graham gave a talk on JavaFX Graphics. They gave an overview of the scene graph along with some information about JavaFX 3D capabilities that will be in the next release. They had some cool demos too, including a few snippets and behind-the-scenes information about the FX demo that was shown during Thomas Kurian’s JavaOne keynote. Kevin and Jim also showed some other, more pedestrian demos, some of which were based on my Flood Game sample program. Thanks for the shout-out, Kevin!

* * *

Of course, no JavaOne day 3 update would be complete without a description of the Oracle Appreciation party (“Rockopolis”) on Treasure Island. This is really part of Oracle OpenWorld, and one of the advantages of JavaOne being combined with OpenWorld is that JavaOne attendees get to partake of the Big Event. This year the top acts included Don Henley, the Black-Eyed Peas, the English Beat, and Steve Miller.

Now, officially this event is for Oracle customers and partners, not employees. The employee speaker badges don’t include tickets for the event, but it turned out that there were some extra tickets available so most of my team was able to go. In addition, a lot of regular (non-employee) conference attendees didn’t actually want to go, so that made more tickets available. Finally, through some … connections … several of us were able to score VIP tickets, which promised better food, shorter lines, and special reserved areas near the stages. Fortunately, I remembered to bring earplugs!

There was even a black market for the tickets. I heard that they were going on Craigslist for $100. Not too surprising really, since the ticket included free food and drinks, carnival games and rides, and six A-list musical groups. (No, I didn’t participate in the black market!)

Really the Treasure Island event was quite a spectacle. As I described last year, it was pretty much like an entire county fair that had been set up for one day. Truly amazing.

JavaOne 2010 days 1 & 2

I’m currently attending JavaOne, the first JavaOne hosted and sponsored by Oracle. So far the biggest change is that technical sessions start at 8:00am. I know, was speaking at one. 🙂 I had to get up at 4:45am to get into San Francisco on time. But, who am I to complain?

Actually, the real big news so far is the demise of JavaFX Script. The reviews from the blogosphere/twittersphere are mixed. Some people are loving it. Indeed, one of the comments I received on my JavaFX Script talk from last year’s JavaOne was “It’s beyond me why anyone would create such a language.” People such as this commenter are perhaps glad to see JavaFX Script go away.

On the other hand, there is also some disappointment, some criticism, some mourning, and even some denial. But this is the price — or perhaps the cost — of progress. (But see also below.)

There’s been some misinformation floating around the twittersphere about “JavaFX is dead” and some such. This is decidedly not the case. JavaFX Script is indeed on its way out (though existing programs will still run for a while, and you can still develop new ones, should you decide to do such a thing) but JavaFX itself is most definitely alive and will continue develop. Here’s a clarifying statement from the JavaFX Architect, Richard Bair (what Mr. Bair meant to say was…) about the changes coming in JavaFX 2.0:

http://fxexperience.com/2010/09/javafx-2-0/

Also, the official JavaFX roadmap statement is here:

http://javafx.com/roadmap

* * *

The talk I gave this morning (along with my colleague, Paru Somashekar) was on JavaFX UI Controls. Originally we were going to present a lot more code examples, but with the move away from JavaFX Script we had to retool the talk. In the end we showed a survey of the controls and some demos of the controls in action but relatively little code. We did do a small comparison of JavaFX Script to a new, provisional Java-based API for JavaFX. Overall the talk was well attended (better than I expected for an 8am tech session!) and I thought it was a success.

One questioner at the session criticized the dropping of support for JavaFX Script and in particular its declarative syntax. He was very polite, apologizing for making a statement instead of a question and also for shooting the messenger. I didn’t get a chance to talk to the gentleman, but I wanted to say that I wasn’t offended by his comment. On the JavaFX team we knew that dropping JavaFX Script would be painful for some. Anyone who’s affected needs to speak out about it. I don’t think the decision will be reversed but it might be possible for those impact to get some help with migration.

* * *

We had a great lunch at Henry’s Hunan. I’m still full. Oh, well there was also that big cookie I had during the afternoon break.

* * *

It’s a bit odd not being in Moscone. Unlike I think all prior JavaOnes, this year JavaOne is in a trio of hotels: the SF Hilton, Hotel Nikko, and the Parc 55. The hotel meeting rooms are smaller, so they fill up sooner, and in general Oracle employees (such as myself) can only get in if there’s space available — which there often is not. As a result I’ve been unable to get into a few sessions that I wanted to attend. Oh well, I’ll have to pick up the presentation slides later on. But, who am I to complain?

* * *

This evening I’m attending a few BOFs: on Jigsaw, OpenJDK, and on Visual Design with CSS. After that I’ll head home, attempting not to fall asleep during the drive, and fall into bed at the end of a very long day.

Anyone who’s used any of the JavaFX UI Controls (in javafx.scene.control) has probably noticed that most of the controls don’t have any listeners. Why is this? Without listeners, how can you detect when the user has changed the state of the control?

The first, easy answer is that you can often avoid the need for listeners by binding to the state of the control. Let’s consider a simple CheckBox example. Suppose you wanted to change the visibility of something based on whether the checkbox is selected. In Swing, you’d do something like adding an item listener to the checkbox, and when it got called, you’d look in the event to see which checkbox got changed and whether it was selected or deselected, and then modify the visibility of your component (or whatever) accordingly.

In JavaFX, you’d do something kind of the opposite. Instead of having a listener get called that “pushes” the side effect of the checkbox state change into some target object, you’d instead bind the “visible” state of the target object to the selected state of the checkbox. Here’s how:

var cb:CheckBox;

Stage {
    scene: Scene {
    content: [
        HBox {
            spacing: 10
            padding: Insets { top: 10 right: 10 bottom: 10 left: 10 }
            content: [
                cb = CheckBox {
                    text: "Check Me!"
                    selected: true
                }
                Label {
                    text: "sample label text"
                    visible: bind cb.selected
                }
            ]
        }
    ]
    }
}

The bind-expression makes sure that the Label’s “visible” variable will always track the state of the CheckBox, and so the Label will appear and disappear as you check and uncheck the CheckBox. Simple.

This is all well and good if your situation calls for some state to be updated when the CheckBox changes state, and the update computation is something simple enough to be written using a bind-expression. But what if you have some kind of process that you need to perform, say, one that requires having some function called. Wouldn’t you need a listener? Yes, but it’s fairly simple to construct your own.

Like many languages, JavaFX Script has block structure, where any code block “{ … }” can declare local variables that are scoped to that block (i.e., they are not visible outside that block). It’s also legal to declare local variables within the “{ … }” of an object literal, even though it’s a syntactically different construct from a code block. What’s not very well known is that it’s also possible to override variables of the class you’re instantiating. By itself, overriding a variable doesn’t let you do much except to override the initial value of a variable. Since this is already within an object literal, you’re providing initial values already, so what’s the point? Overriding useful because it provides a point of (re)declaration of the variable where you can supply an “on replace” trigger. This is code that gets called whenever the value is changed … just like a listener!

Let’s try this out. Instead of just toggling the visibility of the label, let’s toggle a timeline that rotates it:

Stage {
    scene: Scene {
        content: [
            HBox {
                spacing: 10
                padding: Insets { top: 10 right: 10 bottom: 10 left: 10 }
                content: [
                    CheckBox {
                        text: "Check Me!"
                        override var selected on replace {
                            if (selected) tl.play() else tl.pause();
                        }
                    }
                    label = Label {
                        text: "sample label text"
                    }
                ]
            }
        ]
    }
}

var tl = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames: [
        at (2s) {
            label.rotate => 360
        }
    ]
}

(See Footnote 1.)

This is a little non-obvious but it works quite well.

Now, there’s a problem with this technique. In order to override a variable, that variable must be public. Let’s say that we wanted to create a ListView and create the equivalent of a listener that gets called whenever the selection changes. We’ll just do this, right?

ListView {
    items: [ "One", "Two", "Three" ]
    override var selectedItem on replace {
        println("selection is now {selectedItem}"); // ERROR
    }
}

Oh no, this doesn’t work! The “selectedItem” variable isn’t public, it’s public-read. (Why? See Footnote 2.) This is a bit of a pain to work around. We cannot override public-read variables, but we can still bind to them. This means we can use the foreign trigger idiom to create a new variable that tracks the value of the variable we’re interested in, and then add a trigger to our new variable. Here’s how:

var list = ListView {
    items: [ "One", "Two", "Three" ]
    var sel = bind list.selectedItem on replace {
        println("selection is now {sel}");
    }
}

This is fairly cumbersome, since we have to create and name a new local variable and hang our “listener” code there, and we have to make sure the ListView is accessible to it via a named variable. This is probably about as much boilerplate as adding a listener using an anonymous class in Java. Still, we’re used to much more concise syntax in JavaFX Script. It’d probably be nicer to have a function variable such as “onSelectionChanged” whose value is a function that gets called when the ListView’s selection changes. Adding callback APIs like this hasn’t been a very high priority up until now, though, since it’s possible (if inconvenient) to use the controls without them using the bind or override-and-bind-with-trigger techniques. We’re definitely considering adding them, though, since it makes the API much more approachable.

Footnote 1. This is a bit sloppy. Those of you who compile this code will note that the “label.rotate => 360” line gets a compiler warning to the effect that “label is not a constant but will be treated as such”. This means that, at the time the KeyFrame object of the Timeline is created, a snapshot of the current value of “label” is taken and stored within the KeyFrame. This means that “label” needs to have been initialized to the right value before the Timeline and KeyFrame are created. In fact, I first created the Timeline above the Stage/Scene/HBox hierarchy, and the animation didn’t work! Moving it below makes it work, but the compiler still issues the warning. ↩

Footnote 2. Why are selectedItem and selectedIndex public-read instead of public? If they were both public, the implementation would have to have triggers to handle the cases where the application wrote to them. Each trigger would have to write to the other variable, which in turn would invoke its trigger. This doesn’t cause infinite recursion, though, since the trigger won’t fire if the variable is set to a value equal to its current value. But it’s still a pain. Oh, another problem is, what if the application set selectedItem to an object that’s not a member of the ListView? The trigger would have to set the variable back to a legal value, and add a flag to avoid recursive trigger invocation as noted here. (Also note that Toggle.selected and ToggleGroup.selectedToggle are both public and have this problem. Trust me, dealing with this kind of situation is a real pain.) ↩

We’ve just updated the JavaFX API documentation. The main documentation is here:

http://java.sun.com/javafx/1.3/docs/api/

Probably the most significant change is the addition of a new CSS Reference Guide. This document is linked from the javafx.scene package docs and from the Scene and Node class docs, but it’s actually a bit hard to find. For your convenience, the direct link is here:

http://java.sun.com/javafx/1.3/docs/api/javafx.scene/doc-files/cssref.html

You’ll probably want to bookmark it. A lot of the information is out there already, having been derived from the examples in the caspian.css file (which is included in one of the jar files in the SDK). The styles in caspian.css show a lot of what you can do with CSS in JavaFX. However, even caspian.css doesn’t show everything that you can do with CSS. The CSS Reference Guide is comprehensive. For instance, check out all of what you can do with a Region using CSS. Or, take a look at all the properties of charts you can customize. There’s really a lot in there.

I’ll post some examples later. Meanwhile, dive in and enjoy!

There’s been some confusion about styling scenes and what it means to have a CSS rule that uses “.scene” as the selector. For example, the caspian.css file that’s included in JavaFX, the JavaFX tutorial Applying CSS to UI Controls, and Dean Iverson’s article Into the Background all include style rules that look something like this:

.scene {
    -fx-background: cornflowerblue;
    /* ... */
}

There have been a bunch of questions about this, for example in the forum threads here and here, and in comments at the bottom of the Applying CSS to UI Controls tutorial. People are tinkering with this rule and it’s not working the way they expect. The pieces of this part of the system fit together in funny ways, so I certainly can see why there’s lots of confusion. Let’s dive in.

First, let’s create a simple scene:

Stage {
    scene: Scene {
        width: 150
        height: 150
        stylesheets: "{__DIR__}styles.css"
        content: [
            Rectangle { x: 50 y: 50 width: 50 height: 50 }
        ]
    }
}

Now let’s try to style the scene. The various examples use the -fx-background and -fx-fill properties. Which one is correct? Let’s try both, using different colors so that we can tell which one took effect. Place the following into the styles.css file:

.scene {
    -fx-background: cornflowerblue;
    -fx-fill: orchid;
}

What happens? Basically, nothing. We get a black rectangle on a white background, just as if we hadn’t specified any CSS at all.

Well, that sucks.

The main problem is that Scene objects don’t have any CSS-settable attributes. There are a couple things on Scene that seem like they ought to be settable from CSS, such as the fill and cursor variables. But they don’t work, and that’s a bug. See JIRA issue RT-8653. If you want to set the background color of a Scene, you have to use a rectangle or ScrollView and style that instead. See Dean Iverson’s article Into the Background which covers this pretty well.

If a style rule for “.scene” doesn’t apply any properties to the Scene, what does it do? Let’s first examine an assumption here, which is that a style rule with “.scene” actually applies to Scene objects. This is a reasonable assumption because we’ve set things up for the controls so that “.button” styles apply to Button, “.slider” styles apply to Slider, and so forth. This convention that applies to the controls, but it doesn’t apply everywhere. You can’t, for instance, declare a style rule for “.rectangle” and expect it to apply to all Rectangle objects. Try it! It doesn’t work. To style a Rectangle, you have to give it a styleClass value and then use that in your CSS. For example:

// Main.fx
Rectangle { styleClass: "myrect" ... }

// styles.css
.myrect { -fx-fill: dodgerblue; }

gives the following result:

Now back to Scene. If the “.scene” styles don’t apply to Scene objects, what do they apply to?

Let’s examine a little puzzle in the scene graph API. The scene graph is a tree of nodes, and all trees have a root. Every Node has a parent variable, which is of type Parent (a subclass of Node). If you walk up the scene graph following the parent variable, you’ll eventually get to the root. That’s the Scene, right? But it can’t be, because a Scene isn’t a Node. What is the root Node then? Let’s find out.

var rect:Rectangle;
...
Stage {
    scene: Scene {
        ...
        content: [
            rect = Rectangle {
                styleClass: "myrect"
                x: 50 y: 50 width: 50 height: 50
            }
        ]
    }
}

println("parent={rect.parent}");
// and while we're at it
println("styleClass={rect.parent.styleClass}");

The output will be something like this:

parent=Scene$Root@27d314cc
styleClass=scene

Whoa, what’s that? Inside of every Scene, there’s a hidden node called Scene$Root that’s the parent of every Node in the Scene’s content sequence. It’s a subclass of Parent. It’s the actual root node of the scene graph. And, most importantly for this discussion, it handles CSS on behalf of the Scene. Indeed, its styleClass is “scene”. So, style rules that use “.scene” as their selector are really applying styles to this hidden Scene$Root object.

We’re a little closer, since we now know that “.scene” styles apply to the Scene$Root object and not the Scene object itself. But Scene$Root doesn’t actually have any properties that are affected by CSS. What good does it do to set properties on Scene$Root if they don’t actually affect it?

To understand what’s going on, we have to talk about two features of CSS. First, a feature of JavaFX CSS is that colors can be specified not only using standard color names such as “dodgerblue” or by using RGB syntax like “#0093ff”, but they also can also be looked up by name using properties defined by styles above them in the hierarchy.  Second, as in standard CSS, some properties are inherited. Let’s examine these features in more detail.

Color Lookup

Continuing with the simple rectangle example from above, let’s define style rule for .scene that defines some new color names:

.scene {
    -smarks-special-fill-color: #40d080;
    -smarks-special-border-color: #d02040;
}

I just made up the property names -smarks-special-fill-color and -smarks-special-border color. They don’t exist anywhere else, and merely setting these properties won’t have any effect on anything. However, the property names and values are applied to Scene$Root, so we can put them to use. Define

.myrect {
    -fx-fill: -smarks-special-fill-color;
    -fx-stroke: -smarks-special-border-color;
    -fx-stroke-width: 5;
}

(I also made the stroke width thicker so that it’s easier to see the border.) The result is as follows:

This works because in JavaFX CSS, you can use an arbitrary property name as the value for a color property. This property name is looked up on all ancestor nodes, and if a value is found, that color is used in its place.

Now, I could have specified those colors directly in the .myrect rule and it would have worked just fine. However, if I had several different style rules (say, for different shapes) that wanted to use the same colors, I’d have those color values spread around in a bunch of different rules in my style sheet. If I wanted to change a color, I’d have to change it in several places. Since the Scene$Root node is the ancestor of every node that appears in any Scene, and since its styleClass is “scene”, I can place some color definitions in the “.scene” style rule and they’ll be visible to be looked up from any node in the scene graph. The “.scene” style is thus about as close as we can get to a global repository of color properties. Indeed, if you look at the “.scene” rule from the caspian.css file, just about all if its declarations are for color properties.

Inheritance

Let’s change the scene’s content to have some Text nodes in order to show inheritance of font properties:

content: [
    Text { x: 30 y:  60 content: "Hello, JavaFX!" }
    Text { x: 30 y: 100 content: "CSS is fun!" }
]

This will use the default font, which will give a result like this:

Now let’s modify the .scene style rule as follows:

.scene {
    -fx-font: 18pt "Times-Italic";
}

The result will change to the following:

Why did this have an effect? The reason is that, as in standard CSS, font properties are inherited down the hierarchy. More precisely, if a font value isn’t provided for a particular node, the font property is looked up in ancestor nodes until a value is found. Since Scene$Root is at the root of the hierarchy, and the “.scene” properties have been applied to it, the font defined there ends up being used by the Text nodes. Of course, I could override the font by specifying a font value directly in the code, or by creating a style with a font property and arranging for it to apply to the Text nodes or to an ancestor. Since I didn’t do that, the font property from the “.scene” rule applies. It’s effectively a specification of the default font to be used everywhere in the scene graph.

In summary, the “.scene” style rule doesn’t apply properties to the Scene itself (though maybe it should). Instead, it stores properties on the Scene$Root node. These properties aren’t used directly, but can be inherited (for fonts) and can be looked up (for colors) by nodes anywhere in the scene graph. Thus, the “.scene” style rule is where global color and font properties can be defined, which makes it easier to develop and maintain consistent style sheets.

A recent article named Jonathan Schwartz the worst CEO of all time.Well, it’s hard to tell whether it said that he was actually the worst, but the article is entitled Worst CEOs in American History and Schwartz was listed first.

There’s much to criticize about Schwartz’s tenure at Sun. While CEO, he did the following:

  • Published a book of slogans entitled What We Must Do.
  • Came up with eleven words — more slogans — to codify the company’s priorities.
  • Changed the company’s stock symbol from SUNW to JAVA.
  • Pushed a 1-for-4 inverse split of the stock. This caused the stock’s nominal price to jump from about $5 to $20, after which it steadily fell back to $5, erasing 75% of shareholder value.

In my opinion the worst move occurred in November 2008, when he announced a reorganization of the company — and yet more layoffs. That reorg simply shuffled things around into different groups, but it didn’t change anything fundamental.

You might also have noticed a similarity with the items listed above. They didn’t change anything fundamental either. So yeah, the company wasn’t doing very well and Schwartz failed to turn it around.

However, we need to put this into perspective. The articles states, “Schwartz’s promotion to CEO in April 2006 was followed by a long series of losses.” That’s true, but recall that Sun never really recovered from the dot-com bust. On an annualized basis, the company had lost money every year since 2002 so Schwartz’s tenure was also preceded by a long series of losses. Scott McNealy was president and CEO until 2006, so he deserves  blame for Sun’s poor performance as well. Even after that McNealy wasn’t really out: he was still chairman. Do you think Schwartz’s hands were tied? Schwartz might have undertaken more radical changes, but for the fact that he was still running Scott’s company, with Scott looking over his shoulder.

And recall that McNealy picked Schwartz as COO, and eventually CEO, over some possibly better choices. (See here for instance, though Zander didn’t do very well at Motorola.) If Schwartz really was so bad, Scott deserves the blame for choosing him. (HT to Mark W for pointing this out.)

We should also look where Sun ended up. It was sold to Oracle for $7.4bn, over three times its value at its lowest point, which recovered at least some shareholder value. Thousands lost their jobs, but thousands more kept their jobs and made the transition to Oracle (including me). There is enough of a viable business left at Sun that Oracle thinks it can be grown back to profitability, not cut, scrapped, or shut down.

Schwartz’s tenure at Sun was far from successful, but it could have been much much worse. How much worse? Look at others on that list: Ken Lay, Bernie Ebbers. They defrauded investors of billions of dollars and robbed employees of their retirement savings. Also look at who’s missing from the list. Dennis Kozlowski (Tyco) was convicted of taking more than $80m in illegal bonuses. Q.T. Wiles (Miniscribe) was hired to turn the company around, but instead led a scheme to defraud investors that included shipping bricks instead of disk drives. These guys are criminals. Compared to them, Schwartz ain’t so bad. That’s not saying much, but hey, the article is supposed to be a list of the worst CEOs in history, right?

Schwartz deserves criticism, but he doesn’t deserve to be on this list.

I’m talking at the Silicon Valley JavaFX Users Group tonight. The topic is Hands On JavaFX — Scripting The Scene Graph.

Time and location information is available at the SVJUGFX website. If you’re not in the SF Bay Area, a webcast will also be available. Information is at that link.

I’ve posted the presentation materials on my website here. They’ll be helpful if you miss the talk and want to review it, or if you’re watching remotely and want to follow along (or read ahead).

See you there!

A recent exchange on the JavaFX Forums (see here and subsequent messages) has prompted me to write a note about function return types and type inference in JavaFX Script.

JavaFX Script is a strongly-typed language. You don’t have to declare types everywhere; usually the compiler can infer the right type based on usage. For example, in the following:

var msg = "Hello";

The msg variable is of type String. Occasionally the compiler won’t be able to infer a type, in which case it will issue an error message, and you’ll have to declare the type explicitly.

Now, what’s the return type of a function? If you don’t declare the return type in the function declaration, the function’s return type will be the type of the last expression in the function body. (Also, the return value will be the value of that expression.) This is often just fine. For example,

function getMessage(count:Integer) {
    def verb = if (count == 1) "is" else "are";
    def suffix = if (count == 1) "" else "s";
    "There {verb} {count} item{suffix}."
}

The return type is clearly String. You can use the return statement to return a value from a function, but you don’t have to.

Unfortunately this isn’t documented very well at all in the JavaFX Script Language Reference. The section on function return type inference is extremely short, and I’ve quoted it below in its entirety.

Type inferencing can generally determine the return type of a function. In most cases the parameter types can be determined by type inference as well.

However, functions which, by virtue of their access modifiers, are visible outside the script should be explicitly typed.

[To do: detail on type inference]

The advice about explicitly declaring the return type is a good one, but it doesn’t explain why. I’d prefer a stronger rule and say, always declare the return types of functions.

Functions are used for different purposes. Sometimes they’re used to compute a value and return it to the caller. Other times they contain sequences of statements that mutate state, but that do not return any value. Some languages, such as Pascal, distinguish between these cases by calling them different things: a function must return a value, whereas a procedure cannot return a value. In Java, all methods are declared the same way, but the return type must always be declared. A Java “procedure” returns no value and has a return type of void.

If you want to write a “procedure” in JavaFX Script, you can just declare its return type to be void. But why bother, since the compiler will infer the type for you? The last expression in the procedure might have some value. The compiler will return that value, and use its type, even if you didn’t want to return a value. Consider a banking application. You might want to allow someone to have deposit-only access to an account, but not allow them to make withdrawals or to check the balance. You might code up the interface like this:

function makeDeposit(amount:Number) {
    balance += amount;
}

Whoops! The compiler inferred a return type of Number, and you just leaked the account balance. The obvious fix is:

function makeDeposit(amount:Number):Void { ... }

Function return type inference can have some surprising effects, especially in the presence of subclassing and overriding. Consider the following example:

class A {
    var count:Integer;
    var status:String;

    function update() {
        count++;
        status = "update() was called {count} times";
        println(status);
    }

    function doSomething() {
        // other stuff
        update()
    }
}

class B extends A {
    var subCount:Integer;

    override function doSomething() {
        // more stuff
        super.doSomething();
        subCount++;
    }
}

This works fine. Oh, you left a debugging println in A.update()… just take it out. The compiler now gives you an error, complaining about incompatible types at the end of B.doSomething(). Whut??

The return type of B.doSomething() should be Integer, since the last expression in the body is an Integer. Since it’s an override, it has to match the return type of A.doSomething(). What’s that? Well, it’s inferred from the return type of A.update(). Now, in the original code, the last expression in A.update() is a println(), which is one of the few things in JavaFX Script that has a return type of void. So that’s the return type of A.update(). When you removed the println, the last expression became a String and thus the return type of A.update(). That also affected the inferred return type of A.doSomething(), which also became String, which caused the mismatch with B.doSomething().

The fix here is to declare the return types for A.update() and A.doSomething() explicitly to be Void. It might also be reasonable to declare the return type for B.doSomething(). In this case it’s less important, though. The return type of an overriding function is determined by the type of the function being overridden, so the type won’t be inferred from the last expression in the body. Even though the last expression in B.doSomething() is an Integer, its return type must always match that of A.doSomething(). It’s good documentation to put in the return type, so you don’t have to go hunting through other source files to find out what it is. The compiler will flag an error if there’s a mismatch.

Like I said above, always declare the return types of functions.