Monday Sep 18, 2006

Tabs Are Evil, Part 3

For part 2, see here.

We've got a new forum set up for the Java Posse. There's quite a bit of activity there already. One entry in this thread argues once again that there is nothing wrong with tabs and that they are a good way to express indentation. (We keep mentioning that Tabs Are Bad on the show). I've gotten similar feedback from my previous anti-tab blog entries.

A couple of weeks ago I was taking a look at the findbugs source code, and here's what I saw:

Findbugs follows a coding style where it uses tabs for indentation. In the above you can see that the tabs are really standing out since I have them highlighted with the NetBeans fixtabs module.

The thing to notice is that there are lines where spaces are (probably accidentally) used for indentation. For example, line 2, the beginning of the method signature. And also on line 3, where there is first a tab, then eight spaces, to indent the throws clause.

If this source file is interpreted with tabs expanded to anything other than 8, the code will not be aligned properly. And this is precisely what is problematic about Tabs. Tabs, in most editors, are visually indistinguishable from spaces. Thus, when you're editing, you can't tell that you've accidentally just indented a line with spaces. Obviously, developers might do this by accident, since they already hit the spacebar to insert whitespace between symbols. You can't have the IDE automatically insert tabs instead of spaces. But you can certainly do the opposite. And if you do, you'll avoid problems like these.

Tuesday Aug 22, 2006

Code Advice #13: Don't spot-fix null pointer exceptions

(See intro for a background and caveats on these coding advice blog entries.)

One pattern I've seen some developers use is to respond to NPE (NullPointerException) bugs by inserting a null pointer check at the location of the NPE. Frequently this will be accompanied by some sort of comment like "Why is this null?".

My advice is simple: Leave the NPE until you've investigated the root cause. You need to have a null-policy. Decide which references can be null, and which can't. The problem with spot fixing an NPE is that in many cases, you've only moved the bug from one place to another. And in particular, you've moved the symptom further from the cause.

First, decide whether for your own methods, you ever allow null as a return value. Instead of returning null for an empty or uninitialized list for example, always return an empty list. That doesn't mean you have to create an "unnecessary" object to indicate null; you can call Collections.emptyList(). This will return a shared object which is used for all empty lists - and through generics you still get to keep type checks:

   public static final <T> List<T> emptyList() { ... }

You also need to make sure that you handle nulls properly at the boundaries of your own code. If you're calling a library, make sure that the return values are only null if your program universally allows null for the particular piece of data being passed around. If you're providing an API, make sure that you either handle null parameters (if you want to be lenient), or throw IllegalArgumentExceptions if you expect clients to be well behaved. (I don't throw NullPointerException.)

This is clearly asking a lot of you. You need to keep track of which parameters and fields are allowed to be null. For that reason, it's smart to pick a simple policy. However, with tools we should be able to do better. Annotations are ideal for this. You can annotate parameters and fields to indicate whether or not they are allowed to be null. With that information, tools can check whether your code is correct (and even without tools, when you're calling an API, these annotations help document what is expected of you in a more accurate way than English javadoc descriptions, which frequently say nothing on the subject.) For example, if the static checker discovers that you are calling a method with a null parameter where that parameter is known to not be nullable, it can complain and alert you to the potential problem.

Annotations for nullability will probably find their way into the standard set of annotations. For now, you'll need to use some third party libraries and sprinkle your code with third party class names. That may be a bitter pill to swallow. (Update two days later: See this entry for a solution.) On the other hand, it may pay off. These annotations allow you to state your intent, and without that additional information from the programmer, tools cannot easily help you track down NPE problems.

Here's findbugs' set of annotations related to null checking - CheckForNull, Nullable, NonNull. Obviously, findbugs can also do the static analysis to alert you to errors in your program where you are violating the constraints. IntelliJ has support for this built in. It would be nice if NetBeans would do the same, but on the other hand, NetBeans tries hard to follow the JSR standards closely, so perhaps this will have to wait until we have java.lang.Nullable. In the mean time you can use the findbugs NetBeans plugin, available from nbextras.org. Just grab the annnotations.jar and add it to your project, and then code completion will find the annotations and handle imports for you.

Monday Aug 07, 2006

Code Advice #12: Use final on constructor and setter parameters

(See intro for a background and caveats on these coding advice blog entries.)

In my previous code style entry I recommended a setter pattern where the parameter is identical to the field name, as in the following:

    void setTemperature(int temperature) {
        this.temperature = temperature;
    }
I mentioned that there is the potential of a bug here if the parameter name has a typo; the code will compile just fine but not work as expected since you will be assigning the field back to itself.

There is another problem that can occur when you are "masking" the field with a parameter name. What if you add some code where you don't realize that the name is referring to a parameter, not the field? If you try to update the field, you will update the parameter instead:

    void setTemperature(int temperature) {
        this.temperature = temperature;
        ...
        ... // Other code here
        ...
        if (temperature < -273) {
            temperature = -273;
        }
    }
Ooops!

This motivates another good pattern (besides validating before assigning): Use the final modifier on parameters in constructors and setter methods:

    void setTemperature(final int temperature) {
        this.temperature = temperature;
        ...
        ... // Other code here
        ...
        if (temperature < -273) {
            temperature = -273; // Won't compile
        }
    }

The final modifier can be used in many other contexts as well. You can place it on fields to indicate that they are constants, not variables. You can place it on classes to indicate that they cannot be subclassed. You can place it on methods to indicate (and enforce!) that they cannot be overridden. In the old days, some programmers used to sprinkle final all over their code to get a performance benefit. Be careful here - the performance benefit is typically not significant, and you can introduce some tricky bugs into your code. final should only be used on fields that truly are constant in a logical sense, not just on fields that happen to not be written to yet. This is especially true for public fields, because final fields get copied into clients that access the field. That's right - if you change the value of a constant, any clients that have already been compiled against a previous version of your class will continue to use the old value of the constants, until they are recompiled.

Using final on your method parameters on the other hand has few if any disadvantages. It does not show up in the signatures for your methods. It has no impact on anyone overriding your methods. It does not show up in the javadoc. It simply allows you to state the intent of parameters. And in constructors and in setter methods, parameters should reference state that is to be copied into the object. The references themselves should not be modified, and any attempts to do so will typically be bugs of the form shown above.

Static analysis tools can find the above bug too. PMD will flag cases where you are reassigning any of your parameters. Thus, it is making the assumption that all parameters are final. I've found that to be a bit too restrictive (for example, I sometimes want to adjust a parameter to a method based on some initial validation), so I don't like to run with that rule. Clearly it's easy to work with that assumption - rather than ever reassigning the parameter, copy it and work with the copy. However, marking parameters as final feels right - it's stating the intent of the parameter in setters and constructors, and stating intent is a good thing.

I'd like to get NetBeans to automatically use this pattern when encapsulating fields for me... Anybody listening?
P.S. Thanks to Rick for the inspiration for this entry.

(Confession: This pattern is a recent habit for me. We'll see if it stands the test of time.)

Tuesday May 16, 2006

JavaOne So Far

JavaOne is well underway. It's been great so far. We had our demo in the technical keynote this afternoon. It was short, but everything worked smoothly. I'll have a lot more to say about it later. Perhaps I'll throw in some screenshots and a narrative, similar to the keynote demo I did last year.

So by now it's no longer a secret: I don't work on Creator anymore, and haven't for about nine months. I'm on a new project, Project Semplice (pronounce that in Italian, by the way). This does not mean that Creator is in any way losing momentum - there are two new developers working on the page designer for example. But having been on Creator through two full releases, it was time to try something new. And the new project works on adding a new language to the VM. That seems like a major theme of JavaOne this year. We can accomodate multiple languages on the platform - both in interpreted mode ala JSR 223 Scripting Engines as supported in Mustang, as well as languages that compile down to class files just like .java files. Saying that I work on a "new language" may be a bit misleading: we're trying to target a language inspired by Visual Basic. There's no suitable marketing name for it yet, so in our slides, we're just referring to it as BASIC. Or, for a real mouthful, Project Semplice BASIC. We're going to have a technical session on Thursday at 9:45 (note the time! It changed from its original 1:30 timeslot). We'll have a lot more demos and in-depth coverage of aspects of the language.

Tonight we're having a session for the Java Posse. We're going to record a live session. The session is packed (according to pre-registration numbers). We've been promising on the podcast that we'll have a keg. That was the plan. Two-three years ago, when we launched Creator, we had a "Meet the Creator Team" session, and we brought a keg. We thought we'd just do that for our Posse BOF as well. But we discovered today that the BOF is going to be held in a nearby hotel, not Moscone center, and they have a no-keg policy!! They -do- allow us to have beer served - but we'd have to pay for each and every bottle of beer served, at $7 per bottle! With a couple hundred people attending that's going to be quite expensive. After all, this is just a hobby project for the four of us, un-affiliated with our jobs. We have no sponsors (which is why the podcasts have no commercials in them), so especially with some recent recording gear expenses, it's just not within our budget. So a big apology to those of you who are planning to attend the session purely based on the free beer we had promised :(

NetBeans Day yesterday went well. I was particularly impressed with some of the new demos I hadn't seen before -- like the new Subversion integration. I can't wait to get away from CVS! I also really liked the XML tools support. The platform development and the Java EE 5 demos were impressive as well, but I had seen that before and new stuff always has more appeal. I spent the evening with people I met randomly at the end of the event along with the Java Posse. We recorded several great interviews that we will publish as soon as we get time to edit them. One of the interviews were with findbugs founder Bill Pugh, and author and consultant Brian Goetz. It was a great interview covering subjects I think all developers find interesting -- bugs, tricky bugs, detecting bugs, concurrency issues, and so on. We also interviewed Steve Northover, the SWT lead at IBM. We've also got plans to interview the Swing guys this week (who did a fantastic keynote demo!), so that should be a nice pair of compare and contrast episodes.

I'm having a blast. So much fun that I can tell I'm losing my voice. I did this at the Java Polis conference back in December too. Hopefully I'll still have some speech left for the Posse recording session tonight.

Anyway, the big thing I want to get across with this blog entry is that you should NOT miss our technical session on Thursday, TS-3576, covering the new project - BASIC for the java platform! The other two speakers are the other two guys on the Semplice team: Herbert Czymontek and John "Get a blog" Kline .

Tuesday Apr 04, 2006

The year 2038 Problem

I usually never care about post dates, but the time event tonight is too symmetrical to miss:

        01:02:03 04/05/06
(This is assuming the American format where the month number is listed before the day number: hh:mm:ss mm/dd/yy.)

Remember back six years ago, when "millenium babies" were all the rage? People were trying to time it such that their babies would be born right at the turn of the millenium (and please don't post comments about millenium starting 1/1/2001, not 1/1/2000).

We didn't schedule our kids by desired birthdates, but my middle son ended up with an interesting birthdate anyway: 101000. Okay, I admit that the date is interesting in a very nerdy sense...

Time events like 1:2:3 4/5/6 are significant only in that they have a nice ring to them. Just like the switch from 1999 to 2000: three digits in the current year changed. In an absolute sense the event has no significance: it's only a round number relative to the point we designated as time 0. And let's not forget the historical fudging with the dates... take a look at the source code for the GregorianCalendar class in java.util for example and look for October 1582... Or just cheat.

Many unix systems use a millisecond counter to represent time. The designated begin time, zero on this counter, is January 1, 1970. Unfortunately, when older systems that still use 32 bit integers to hold this counter reach the magical moment when the bits all roll over, there's the potential for Bad StuffTM to happen. Which brings me back to another millenium craze: y2k. It was a giant flop - or a resounding success, depending on your perspective.

When we reach the millisecond timer limit in January of 2038, however, we've got a whole new set of challenges to look forward to: the y2.038k problem. And perhaps, lots of IT spending and OS upgrades. (64-bit Solaris uses 64 bits for time_t and has no year 2038 problem.) Here's more on the year 2038 problem.

And of course, year 2038 will bring a chance for truly nerdy parents to have a child with a birthdate of 0, when expressed in unix milliseconds, truncated to 32 bits. Take that, millenium babies!

Wednesday Jan 25, 2006

Ajax Made Easy

The latest episode of the SDN channel deals with AJAX. The show features interviews with Dojo Toolkit Project Lead Alex Russel, Ajaxian.com co-founder Dion Almaer, Servlet Spec and AJAX lead Greg Murray, and myself.

Also be sure to check out the Update Center in Creator 2. The preliminary AJAX component library should be available, and it features some new AJAX enabled components! More on those soon.

Monday Jan 23, 2006

Why AJAX was hard

I just listened to episode 12 of the Ajaxian podcast, where they interview Thomas Fuchs of Scriptaculous. In it they talk a bit about how after the AJAX craze started, Microsoft and others came out and said building AJAX is for rocket scientists. Thomas rejects that and states that it's trivial - it's just a call to a server. I'm one of the people who came out and said that AJAX is hard - in fact I said it during the keynote demo at JavaOne where I showed Creator's AJAX support. So, I thought I'd clarify why I said it since at the time it was clearly true.

AJAX applications typically consist of asynchronous server trips (via XMLHttp), CSS, XML, and JavaScript. It's the JavaScript which makes AJAX hard. JavaScript itself is easy - the problem is with the browsers. Even during the interview, Thomas talks about how Internet Explorer has issues - they have all kinds of hacks in place for IE, sending a separate CSS stylesheet to it to deal with quirks and so on.

In my own AJAX work, I quickly discovered that while it was really easy to get the component to work well on Firefox, getting it to work on IE was harder. Getting it to work on both was harder still. And then throw in the fact that Safari has its own quirks. Even Mozilla 1.1 and Mozilla 1.4 behaved differently in the kind of JavaScript code I was writing. And when you add a workaround for one you've gotta make sure it doesn't break the others. On top of that, even if Firefox has a decent JavaScript debugger, that doesn't help you when the bug only shows up in IE (or Opera, or Safari, or Konqueror, ...). You also need to be well versed in browser bugs such that you for example know to avoid the memory leak issues you can run into with IE.

THIS is what I meant by "AJAX is hard". No, asynchronous is not hard. XML is not hard. CSS is not hard. It's cross-browser stable, performant JavaScript that is hard.

So why am I using past tense - "AJAX was hard" as opposed to "AJAX is hard" ? The reason for that is that a number of great cross-browser JavaScript libraries are emerging. These have done most of the hard work for you. I still strongly believe that a library approach to AJAX is not enough - you really want components that do all the AJAX plumbing for you as well. I'll have more to say about that soon.

Thursday Nov 03, 2005

Creator AJAX tutorial

The JavaOne demo has been turned into a tutorial.

Friday Oct 14, 2005

AJAX+Java FAQ

Greg Murray has posted a comprehensive FAQ on AJAX as it relates to Java. If you want to dip your toes in Web 2.0, this looks like a great resource and starting point.

Monday Sep 12, 2005

Performance Tuning: Efficient CSS Handling

We have an update to Creator 2 Early Access which should go out any day now. One of the big things we fixed in the update is closing various memory leaks which caused Creator to slowly run out of juice. There are lots of other important improvements too - for example, Creator will finally run on JDK 5.0. But one big thing is still missing before we can ship it: Speed tuning.

I finally got done with my other 2.0 tasks last week, and have now started the performance tuning work in earnest.

It's really fun! I perform various tasks, look for hotspots, study the code and decide if (a) the code is doing something stupid, and (b) if the code is getting called too often. I've found several easy things to fix, so I've integrated a couple of things, sent e-mail to some other people when the bottlenecks are in their code. And in one case filed a NetBeans issue with my analysis.

The right way to performance tune is to measure the code looking for hotspots, rather than using your intuition about code you've written which is probably slow. So that's what I did - and I measured an enormous bottleneck in the CSS handling code.

This bottleneck has been there since 1.0. However, the bottleneck is proportional to the number of rules in your stylesheets as well as the number of elements in your document, so it doesn't show up for most pages created with Creator 1.0. However, in Creator 2, with our new nice themes, we have really large stylesheets which trigger the slowdown. And if your document has a lot of elements, which is pretty easy now with some of our new complex components, the slowdown is significant. As pointed out by the profiler.

This performance bug was really fun to analyze and fix, so I'll explain the gory details to you.

The problem is this: For each element in the document, we need to figure out which rules apply to that element. This was done by iterating over the rules, checking the selectors in each rule to see if they apply to the current element, and if so, "apply" the rule to the element.

The problem is that in Creator, the new Theme stylesheet contains nearly 800 rules! And of course, most of those rules contain multiple selectors, each of which must be checked! Then there's the possibility of additional stylesheets. There's the builtin user-agent stylesheet (which assigns HTML semantics for the element) as well as the project default stylesheet, and any stylesheets you've added yourself. Finally, some of the selector checks involved iterating up node hiearchies (for example, the :link pseudo tag means we need to see if the element is enclosed within an <a> tag.) To cut to the chase: some of the node iteration and selector check code would get called over a million times for a page render!

Clearly, this needs to be optimized. There is a straightforward technique to handle this which apparently is used by Mozilla's layout engine. I learned about it from reading David Hyatt's blog. That's right boys and girls - spending time reading blogs CAN benefit your daytime job! Give yourself a pat on the shoulder and resolve to return to my blog regularly :)

The technique is as follows: preprocess the stylesheet when it's first loaded, by setting up some extra datastructures which will make the later (frequently called) "find-rules-for-element" perform faster.

Consider the following sample rules:

 .Tab1Div table {border-collapse:collapse}
 .WizMst {background:#C6D6DF}
The first rule can obviously only match Elements where the tagname is table, and the second rule can obviously only match an element that has a class attribute which includes WizMst.

Therefore, when I preprocess the stylesheet I split up the set of rules into four categories. First, for any rules where I can identify a "tag name requirement", I add the rule to a hashmap indexed by the tag name. Then, for any rules that have a "class attribute requirement", I place these in a hashmap indexed by the class attribute. Similarly for the element id condition. Then I have a list of all the "remaining" rules, which don't have obvious tag/class/id requirements. These will need to be checked the old way against all elements. But amazingly, out of the 800 rules in the theme stylesheet, only 5 fit into this last category!

Now, whenever I need to compute matching styles for an element, I first look up its tagname, check for applicable rules in the hashmap, then do a full selector check on each one of these rules. Then I check the styleclasses in the class attribute with the class hashmap, and so on. Finally, I do the old-style iteration of the "remaining" rules. This effectively partitions the rules up into small buckets, one for each of the tag names, and one for each of the attribute names, so for each element I get to do a lot less work.

This does however add one complication: cascade order. I cannot simply process all tag-related rules followed by all class-attribute rules. Later rules in the stylesheet should "overwrite" earlier rules (modulo various cascade rules etc.). So after matching rules from my hashmaps and the remainder-list, I need to sort the rules into the right cascade order again.

The first thing to do was to verify that the optimization works - that pages still render correctly. They appear to. Check. Then I measured the performance differences to make sure I actually get an improvement and remove the bottleneck. To make it easy to check, I put the new code path under a global flag I could turn on and off. Then I ran style attribution with the optimization on, then with the optimization off, and compared the results. And the effort definitely paid off. For smallish pages, style attribution got a speedup of 12x. For large pages, I got a speedup of 8x!

Note that these speed improvements are not in EA Update - which has been out of our hands for a while now.

Saturday Jul 09, 2005

Creator and AJAX: The Demo

I did a demo at JavaOne during Monday's keynote on Creator 2 and AJAX. Being a keynote demo, it was obviously stripped down to the bare minimum with a three minute timeslot. Therefore, I didn't have time to motivate the example, or build up the demo in gradual steps. But in three minutes, starting from an empty project and using no code clips, I built a web page that does a google-suggest like thing where as you're typing in a textfield, you get autocompletion on words from a 180,000 word dictionary. I've received a number of questions about it, and so have the people who were working in the Creator booth at the conference, so I'm hoping a blog entry will clear some things up.

First, let's talk about AJAX. One of my favorite uses of AJAX is providing auto completion in text fields. You've probably used address forms where the State or Country fields use dropdowns with 50 or more items. You typically KNOW which state or country you want to select, so being able to type three or four characters to limit your visible choices is a lot more usable than scrolling through large popups.

However, doing autocompletion smoothly as a partial page refresh (e.g. no page submission) is somewhat tricky. It takes lots of JavaScript plumbing to do that - and to get it working correctly on lots of browsers.

This is an ideal domain for a JSF component. The JSF component can encapsulate all the hard work in its renderer, meaning that your JSP files contain no JavaScript code whatsoever. You get the benefits of AJAX without its usual high development cost.

So let's jump right into it. One of the points that was made in the keynote, but people have confused in their JavaOne summaries that I've read, is that the AJAX component I demonstrated is not part of Creator 2; it's developed in open source on java.net. Thus, you can get all the source code for this and enhance the component (or create similar components) to your heart's desire.

In fact, it gets even better than that. There's a whole write-up on this component which explains exactly how it works. It comes with a working sample application - a JSF address form providing city completion for all 25,000 U.S. cities. And if you want a more generic overview on how to create JSF and AJAX components, check out this paper written by Greg Murray, Ed Burns and me, which covers some different approaches and trade-offs for this technology.

One of the things you'll find in there is code to wrap the component up as a Creator component library that you can import right into the IDE. Once you've downloaded it, you can install it by right clicking on a palette category, bringing up Manage Component Libraries..., select Import, and drill to the component library jar. Ok your way out. You should now find a new "Ajax Component Library" palette category at the bottom containing the completion text field.

(What, only one AJAX component? Yes, we'll add more components there. If you look at the blueprints page I pointed to earlier, you'll see several additional JSF components written by Greg Murray, Ed Burns, and more are on the way. These will be packaged up as Creator importable components as well.)

Now, drop the text field on the page. Then double click on it. Notice how it will warp to the source code and show you a new event handler. This event handler has already been bound to the text field when you double clicked on the text field. (If you study the JSP you'll see that it has a completionMethod attribute set to a method binding expression pointing to the method you're currently editing.)

Take a look at the screenshot. That's what it looks like in my editor - and what it looked like at JavaOne. But it's not what you're seeing in Creator 2 Early Access. Here you have a component-specific event handler, with properly named method parameters, and a default event body that gives you some suggestions for what to do. This was added right after Early Access froze so your bits don't include this functionality, but needless to say it will be in the shipping release. This will make it easier to write editor validation event handlers or even button action handlers too, since the default bodies will guide you in the right direction.

Study the trivial sample code in the comment:

    public void ajaxTextField1_complete(FacesContext context, String prefix, CompletionResult result) {
        // TODO: Return your own list of items here based on the prefix
        //result.addItem("Hello");
        //result.addItem(prefix.toUpperCase());
    }

If you simply uncomment the last two lines, and hit Run, you'll get an editor which contains two items in the popup: "Hello", and whatever the user has typed in the browser - but uppercased:

That's a big deal. Notice that we've written simple Java code which runs on the server, yet as the user is typing in the browser, results are dynamically shown without any kind of page submit. The user gets nearly instant feedback. All the plumbing is taken care of by the component. So while writing one of these components is tricky (see the documents referenced above), using an AJAX component is downright trivial.

Ok, I know what you're thinking. "What, every keystroke in every client's browser is hitting the server? You're crazy!!". I addressed this point in the AJAX full hour session at JavaOne. AJAX functionality does have a price. Your users are getting a better user experience. It doesn't come for free. You need to have good server resources to support this type of interaction. (I know a company which will sell you a good server! :-) Think of Google Suggest for example. Every time one of their users types a character\*, it hits their servers and returns a portion of their index. (Yes, I'm aware that if users are typing fast multiple keystrokes get coalesced into a single request). This is clearly not free - they're using additional servers to be able to handle this load. But to them, and perhaps to you, the added user benefit justifies the additional cost.

Anyway, back to the AJAX demo. The previous step (where I simply do a trivial computation to show server computation reflected in the browser) was eliminated from the keynote demo due to time constraints. I jumped right to the part where I do something more complicated on the server with the prefix we're getting from the user's text field. I call a web service, which returns a small set of words that start with the given prefix. Calling a web service is easy. First I have to import the web service (by pointing to the relevant WSDL file), then drag the web service onto the canvas (to get a local proxy object I can make calls on), and finally I change the autocompletion event method to simply call the web service to get a String array of words, and then I add those words to the completion result object. (It has an addItem(String[]) method as well). Thus, after dragging the dictionary web service onto the page (which gives me a local field dictionaryServiceClient1), I replace the code in the event body with:

    public void ajaxTextField1_complete(FacesContext context, String prefix, CompletionResult result) {
       try {
           String[] items = dictionaryServiceClient1.matchPrefix(prefix);
           result.addItems(items);
       } catch (Exception ex) {
           log("Error Description", ex);
       }
    }
The try/catch skeleton here came from me typing "trc ", and I just typed dict followed by Ctrl-K to type in the full name of the service client object.

During the keynote demo, I had a typo - I wrote

   result.addItems(result);
rather than the correct code above. When I hit Deploy the compiler rightly complained. Somebody asked afterwards if that was intentional, since having errors in my code has happened a couple of times during keynote demos in the past. For example during James Gosling's keynote last year:
In another coding process, Norbye skipped a step, which Gosling noticed. Norbye quipped, "It's really great to have your very own James Gosling to help you code," which drew a big audience laugh.
Let me assure you that the step last year was accidentally missed, not skipped, and again this year it was definitely not intentional. You try to code in front of ten thousand people and see if you can do it flawlessly :) I'm only glad the mistake was trivial and easy to spot. It sure would have been annoying if I hadn't been able to catch it before getting chased off the stage. I gave a full-hour Creator 2 demo at NetBeans day the day before JavaOne, and towards the end I was going to build a nice demo utilizing the new file upload component. But each time I tried to submit, the file upload component threw an exception. We spent 5-10 minutes debugging it with the audience's help but to no avail. Annoyingly, shortly after the demo, Craig McClanahan (who was in the audience, and also works on Creator) discovered that the problem had been that I was doing the demo on Internet Explorer (which neither Craig nor I normally use). I hadn't noticed that on the demo box I was using it was the default. And it turns out that there is a bug in the EA version of the upload component where it doesn't work correctly with IE in a couple of cases. Oh well.

Anyway. Back to the scheduled programming. With the above code change, and deployment, you run and get the screen shown below. As you type, dictionary completions from a dictionary of 180,000+ words are instantly updated:

In the AJAX session I also went on to hook it up so that there's a lookup button which looks up the definition for the selected word and displays it below. I'll leave that simple exercise to the reader (hint: it took less than a minute in the session demo.)

One of the things I wished I would have thought of before the keynote, is a better "sample word" to type to show the application working. I typed "Java", but it would have been a lot more fun if I had typed "Brazil" !! (For those who don't know, many keynote speakers make a point of mentioning the word "Brazil" in their speeches because it invariably draws cheer and applause from the Brazillian delegation, each and every time.)

So that's the spiel. At this point you may wonder where the dictionary web service came from. I had really wanted to motivate the AJAX example with the simple deployment step first, such that it gets the "look how easy" point across. The web service call makes everything more "magical", especially when it happens so quickly during a 3 minue demo - but it's important to understand that it's just a method call which returns some good matches for a string.

The web service was deployed locally. It was extremely easy to create. I did it in one evening - and that includes the learning curve, since I had never created a web service before. However, I found this tutorial which shows how trivial it is to build one with NetBeans 4.1. So I went on the internet, found a free dictionary file, wrote a small program to take all those html files, extract all the words and definitions from them, and then sorted those and wrote them into two files: and index file, and a definition file.

The web service is very trivial. It has an interface with two methods: a method for looking up the definition of a word, and a method for returning the 10 closest matches to a prefix. The second method simply does a binary search in the word index, but rather than returning the matched word or null it returns the index of the closest match, so that the web service can return the 10 closest words in the sorted word array. Trivial, eh? You can download the web service project yourself, as a .zip file. Unzip it and open it in NetBeans 4.1.

It might complain about a missing server. Use the Server Navigator in the Tools menu to point to your Creator App Server 8.1 installation; it's running on port 28080 with username admin and password adminadmin.

You can now first run the project to deploy it, and then register the web service by going to the Web Service node in the project manager, right click and select Add To Registry... (or something like that). It will show you the WSDL URL for the deployed web service. In my case it was

  http://localhost:28080/DictionaryService/DictionaryService?WSDL
In Creator, you now go to the Web Services node, select Add, point to the above WSDL file, hit OK, and you've imported the web service into your Server Navigator. (You can test it too - look at the context menus for the web service method nodes.) Now you can simply drag the web service onto pages to get a local client object like dictionaryServiceClient1 in the code above.

Hopefully the use of a web service doesn't confuse the AJAX component issue too much. One of the nice things about separating the dictionary code into a web service (rather than having it included locally) is that the dictionary is only deployed once, not each time you deploy your Creator project. Thus, the 10 megabyte dictionary file doesn't get reparsed each time you start the project. (It takes a couple of seconds the first time it's called to "warm up", e.g. read its dictionary list into memory) but once it's up and running there's no delay at all.

....and that's all I have to say about that...
F. Gump

Saturday May 14, 2005

AJAX + JavaServer Faces: Better Address Entry Forms

I mentioned recently that the blueprints project on java.net is posting detailed articles and sample applications for various AJAX strategies. New entries are added regularly.

Well, I've participated too. My first entry shows how you can add some AJAX-style behavior to a JavaServer Faces application.

Many webforms, especially those involving online shopping, involve address forms. When you get to fields like states, provinces, and countries, you get these super unwieldy combo boxes or listboxes to pick an alternative from - see listbox image on the right from Amazon.com for example. For U.S. states you're looking at 50 alternatives, which isn't too bad, but country dropdowns usually involve several hundreds alternatives. Hope you brought your scrolling wheel. These pages are also slow to load since the HTML involves hundreds of <option> tags for the listbox contents.

A dropdown is not a good user interface element if you need to choose an item for a large number of possibilities. Take the city field. What if you wanted to let users pick a city instead of having to type one in? Well, for the U.S. alone the combobox would have over 25,000 entries - this is clearly not practical.

But it's an ideal situation for AJAX:

  • The server can easily store all possible cities and quickly provide a small number of completions upon request. Thus, each keystroke in the city field causes a request to provide the ten nearest city names for the given prefix.
  • The address form page stays small and lightweight
  • The user interface for completion is better than a dropdown for a large dataset like this
  • It downgrades gracefully: if the user has disabled JavaScript, they can still use the address form - they'll just need to type in the address without completion assistance

An application which does exactly this, using JSF as the application framework (the address stored in a session scope bean, text fields are marked as required, etc) is now available. You can access an intro writeup here . Be sure to click on the link at the bottom of the page to go to the design details document, which describes how everything works. And perhaps most importantly, you can get the code - it's checked into CVS on java.net in the bpcatalog module.

Here's how the form looks in my browser:
browser screenshot

One neat thing about using completion like this in an address form is that on the server we know not only the city and state you chose for the city field - we can also look up a zip code for the city too, and when the user clicks on a city in the completion dialog we automatically populate the given selection into the city, state and zip fields all at once! Actually obtaining the U.S. zip code dataset was quite a challenge and would almost be worthy of its own blog entry... When you adapt this technique for international address forms you'll have fun finding global data for this. The country list is especially going to be fun for you given the political nature of the issue - since there are disputes about whether certain territories are their own country!

Please note that this example is a very simple integration of AJAX and JSF; in particular, it's not using any custom JSF components or component renderers. It does however describe a couple of tricks that may be useful to you if you're trying to AJAXify your own JSF applications.

This was checked into CVS several weeks ago. In the weekends since I've been working on a custom JSF component which removes a lot of the complexity from the JSF developer. That's in CVS and works too, but is not fully polished yet. Stay tuned and I'll blog on that when it's fully cooked.

Thanks to Greg Murray for the helpful advice and obviously for the original non-JSF autocomplete blueprints entry, since the code is based heavily on it!

Monday Apr 25, 2005

AJAX

You've probably heard a lot about "AJAX" already. But if you haven't, it's a new term describing technology which has been around for a while, but has recently gotten a lot more popular because of some really well done AJAX applications from Google:

AJAX is really a combination of technologies. The most important piece is JavaScript code in the page making asynchronous requests to a server. When the server responds it calls back into JavaScript, and this JavaScript can then manipulate the content of the page directly.

Sun is working on this too; J2EE is an excellent platform for AJAX applications. See Greg Murray's Blog for more on the blueprints project on java.net; AJAX blueprints are available already with working sample web applications. And perhaps more importantly, it includes detailed documents explaining how it all works so you can take the blueprints and extend them for your own needs.

I find this technology really fascinating so I plan to blog more about it.

About

Tor Norbye

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today