McQueeney.com
 

Tom's Blog

JDK 5: Learning to read Java again
Published by Tom | September 30, 2004 04:02 PM EDT |
With Java 1.5 released today, it got me wondering how many weeks it will take until I'm comfortable reading the new language syntax. Tiger's changes are the first major syntax changes to the language in seven years, when features like anonymous inner classes were introduced in JDK 1.1.

After reading Java code on a regular basis over the past six years, I can read Java code quickly. The syntax is second nature. Common idioms have become nearly standardized. And there are only a few common coding styles out there. But Tiger has a lot of new syntax. How long until reading code, like the snippets below, becomes second nature?

Generics

Map<String, Integer> m = new TreeMap<String, Integer>();
Code like the above is fairly easy to read. But code like (from java.util.AbstractCollection):
public boolean addAll(Collection<? extends E> c) {
    Iterator<? extends E> e = c.iterator();
    // ...
}
is a little less clear. When I first looked at this code, my first question was: Does that compile? A question mark extending an "E"? I'm sure I'll get used to reading code with generics over the next few months. But today, I say, "Huh?"

Static imports
    getContentPane().add(new JPanel(), CENTER);
With the above code, I'll first look around for a static final CENTER declared at the top of the program. When that fails, I'll do a text search. And I still won't see CENTER declared anywhere. Then I'll realize it's a static import, a terrible new feature allowed by writing code like import static java.awt.BorderLayout.* at the top of the class. Bleccch.

Annotations

Annotations probably will be the toughest new syntax for my eyes to scan over quickly and learn to ignore the boilerplate fluff in order to get to the meat of the code. For example, when I read a line like:
public static final void doSomething(int i) {
    // ...
}
my brain quickly skims past the modifiers and sees that it's a method declaration for doSomething.

But this code, taken from the Sun article J2SE 5.0 in a Nutshell, slows me down a lot trying to figure out what's being defined.
import java.lang.annotation.*;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @interface debug  {
    boolean devbuild() default false;
    int counter();
}

public class MetaTest {
    final boolean production=true;

    @debug(devbuild=production,counter=1) public void testMethod()  {
    }
}
Not only do annotations add more verbose modifiers to methods like testMethod above, my eyes see syntax like:
    boolean devbuild() default false;
and stop dead because of this alien syntax. (It defines an annotation type with a default value.)

I'm not saying annotations are bad. I like the concept of annotations. For instance, coding EJBs promises to become slightly easier, and remove the need for running the code through a pre-processor like XDoclet. And when you mark a method with the built-in @Override annotation, the compiler can tell you that you must have mistyped your method public String toStrng rather than allowing you to happily assume you are overriding the toString method in Object -- and spend hours puzzling over why your code isn't working.

Ultimately, I think annotations will allow creative people to write interesting code. For example, Cedric Beust's TestNG uses annotations for unit tests. TestNG's annotations allow you to write unit tests that don't need to extend a class or implement an interface, and allow you to mark a method as being part of one or more test suites rather than having to write separate test-suite classes.

On the other hand, I suspect some developers will go crazy with custom annotations and write a lot of cluttered code. Since annotations allow an unlimited amount of "stuff" inside them, I'm guessing I'll see multiline annotations that bury a method declaration beneath the clutter unless I'm using an IDE with syntax highlighting to point it out. Eventually, though, we'll settle into some standard annotations, and peer pressure will embarrass those who overuse annotations for marginal gain.

And soon, I know I'll get used to reading those annotation tags. My eyes will learn to skim over the annotations, glean the basic meaning, and see the code beneath. Just like the other new language features in JDK 1.5, we'll settle on some comfortable, common idioms so they become second nature. But until then, I'll be spending some time learning to read Java again.

20040930 Thursday September 30, 2004 Permalink
Mozilla Thunderbird RSS reader a nice addition
Published by Tom | September 28, 2004 01:54 PM EDT |
I finally found an RSS reader that fits my application lifestyle. I've tried a few stand-alone RSS readers in the past, including one that runs under .NET, but none worked well for me.

All the feed readers required me to run a separate application, and most ended up showing me blog entries in such a terrible format that to read them efficiently, I had to visit the web site of the blog. I ended up dumping each of the RSS readers after a couple of days.

My solution was to "subscribe" to RSS feeds by bookmarking them in my web browser and visiting my favorite ones when I had the time. In other words, I was back to the "pull" model, defeating the whole "push" model of RSS syndication.

But Mozilla's new email client, Thunderbird 0.8 now offers RSS feed support. The reader acts in some ways like a regular email account. You can subscribe to feeds, and tell Thunderbird how often to update the feeds. Each feed gets organized under its own folder under the RSS account.

The RSS feed reader is a good start. It really makes sense to integrate an RSS reader into an email client. In fact, I previously was considering dumping Thunderbird and going back to MS Outlook after Dion said he really likes Outlook's NewsGator ($30) plug-in to read RSS feeds.

I have two critiques so far with the Thunderbird RSS reader. First, the formatting of many blog entries often is horrid when Thunderbird is set to display email bodies as "simplified" HTML, which I do to avoid seeing all the advertisements. I'd like to set Thunderbird to display full HTML for RSS entries but "simplified" for all other email. But so far, Thunderbird has one display setting for all accounts. Second, I'd like to be able to configure the frequency of the RSS updates on an individual basis. Some RSS feeds should be updated daily, while others I'd like to have updated hourly. Currently, all feeds are updated on the same schedule.

Even with those faults, the RSS reader is a nice addition to Thunderbird. And this is Thunderbird's first crack at including an RSS feed reader. I should think the functionality will only get better in later releases. Thank you, Thunderbird team.
20040928 Tuesday September 28, 2004 Permalink Comments [1]
Fast Web Services for Warfare?
Published by Tom | September 25, 2004 06:37 PM EDT |
It's been more than a year since Sun Microsystems introduced its Fast Web Services technology at JavaOne 2003. I've been following the status of binary Fast Web Services because of my interest in increasing the speed of SOAP messaging in my projects, and discovered the U.S. military shares my interest.

On Tuesday and Wednesday this week, the U.S. Air Force and the MITRE Corp. held a conference in Virginia on "XML for Binary Interchange: Addressing Machine-to-Machine Interoperability & Tactical and Mobile Computing." MITRE is a not-for-profit corporation managing research centers for the Defense Department and other federal agencies. At the conference Tuesday, Santiago Pericas-Geertsen, one of the inventors of Fast Web Services, gave a presentation on the technology during the public portion of the conference. (Wednesday afternoon featured "military only" sessions.)

The primary Air Force group co-sponsoring the conference is the "AFC2ISR Center" at Langley Air Force Base. The Air Force Command, Control, Intelligence, Surveillance and Reconnaissance Center helps develop technologies that allow reconnaissance aircraft and satellites to communicate real-time battle information to troops on the ground. The conference's primary objective was to help build the Global Information Grid by looking into using XML technologies for messaging "in tactical and bandwidth constrained environments," combining "the advantages of XML with the efficiency of binary-format information exchange."

In order to increase the transmission speed and processing of XML, various standards bodies have developed, or are looking into, binary equivalents to XML technologies, including binary SOAP messaging for faster web services. Not everyone agrees binary XML is a good idea (more on this below). But apparently the military thinks it is. In announcing the XML for Binary Interchange conference, a MITRE conference organizer wrote in an email to the xml-dev mailing list that he was sorry he didn't have time "to engage in a protracted xml-dev discussion. Suffice to say we believe there to be real issues that must be addressed."

If you haven't heard of Fast Web Services, here's some background. FWS is a mix of technologies that attempt to solve the web-service speed problem by using binary equivalents of XML for messaging. Binary XML encoding not only makes SOAP messages faster to transmit over the wire, the format also makes it faster to create and parse the messages, including serializing and deserializing the message from and to programming-language objects.

Fast Web Services uses Abstract Syntax Notation One, developed 20-years ago by the International Telecommunication Union. Sun has worked with the ITU's telecommunication standardization group to create a mapping standard between ASN.1's schema language and XML Schema so ASN.1 can be used as a replacement for XML. Once XML is turned into its ASN.1 equivalent, it can be compressed using Packed Encoding Rules, another ITU standard.

As an aside, anyone I've talked with who has used ASN.1, including two Sun engineers, has made it pretty clear they never want to see ASN.1 again. It is a horrid data language, apparently. But on the positive side, web services developers using Fast Web Services should never have to deal with ASN.1 directly, just like they don't have to deal with the underlying HTTP protocol when writing web services today. The web-service transport layer handles the creation and parsing of the ASN.1 messages.

Binary XML has been a topic among XML developers for more than 5 years. Critics have argued that binary XML
  • Is an abomination that flies in the face of everything that human-readable, self-describing XML was invented for in the first place.
  • Will let unskilled developers create fine-grained web services that will increase server loads unnecessarily.
  • Compressing SOAP XML messages using GZIP works just as well
The first two criticisms are good points, but I don't think they're strong enough to quash a binary web service standard. Web services are here to stay, especially with the big vendors pushing service-oriented architectures implemented through web services. If we can make web services faster in the CPU and faster on the wire, why not? But as far as compression goes, verbose XML is only one reason web services are slow. Creating and parsing the XML, especially if the XML is being deserialized into Java objects, accounts for a lot of the slowness.

Sun implemented a prototype of its Fast Web Services, using a modified version of its Java Web Services Developers Pack. Sun then compared the speed to RMI, RMI-IIOP, JAX-RPC SOAP encoded, and JAX-RPC XML literal. Its tests, running on one machine to eliminate network-connection latency, shows Fast Web Services took 165% the time of RMI, was 2 times faster than RMI-IIOP, and was about 4 to 10 times faster than regular web service calls. You can read Sun's Fast Web Services article for details.

Sun's goals for Fast Web Services are to:
  • Speed processing of web service messages by using a binary format that is faster to create and parse.
  • Speed transmission of web services messages by using a more-compact format.
  • Lower the memory needed for web-service applications, opening web services to limited-capability devices like PDAs and mobile phones (and maybe battlefield gizmos?).
  • Minimize any changes needed to existing specifications (like WSDL).
  • Maintain the interoperability of web services by keeping the message format platform- and language-neutral.
Another major goal is to shield developers from having to know anything about the binary XML format. In Sun's implementation, APIs like JAX-RPC will remain the same. Programmers will continue to write and call web services the same way as today. The transport layer will perform the FWS magic by talking to the server hosting the web service (probably by examining the service's WSDL) and inquire whether it supports FWS. If so, it uses it. If not, it reverts to standard XML SOAP messages.

When Sun unveiled the technology in 2003, it said it should have an implementation available for developers in early 2004 as part of the Web Services Developer's Pack. So far, I have heard no updated plans to release the technology to the public. Perhaps Sun is waiting for the ITU's Study Group 17 to come out with a planned fast web services specification. Rima Patel Sriganesh, a technology evangelist at Sun, said during an online chat in July that she expects ITU's Fast Web Services specification to be completed by next summer.

The W3C also has an XML Binary Characterization Working Group looking into whether a standard binary XML format is desirable. If the answer turns out to be yes, perhaps the W3C will pursue a binary web services standard. In July, the working group published its first draft of use cases describing the need for a binary XML format. The group cited "Web Services as an Alternative to CORBA" and "Web Services for Small Devices" as two uses for binary XML. (By the way, Robin Berjon, the chair of the W3C XML Binary Characterization Working Group, also spoke Tuesday at the military conference.)

It will be interesting to see where fast/binary web services go. Will the W3C come out with its own binary web services specification (and any necessary changes to the WSDL specification to support it)? If so, will those specifications compete or complement ITU specifications? Will OASIS modify its SOAP Message Security standard to work with binary SOAP messages?

The W3C binary XML working group has spelled out a need for binary XML, including binary web services. Members of the ITU have said there's a need for a binary web services standard. And the U.S. Defense Department is saying it needs binary XML and faster web services.

But for faster, binary web services to take off, we'll need clear, compatible standards to ensure interoperability. The W3C will need to work with the ITU to prevent competing standards. And we'll need product companies like Microsoft, IBM, BEA and Sun seeing a big enough market demand to implement those standards as part of their web service stacks.

20040925 Saturday September 25, 2004 Permalink
Problem installing extensions in Firefox
Published by Tom | August 21, 2004 03:03 PM EDT |
Today I tried to install some new browser extensions into the latest Firefox 0.9.3 browser and couldn't figure out why nothing was happening. I first tried opening the XPI file directly from the Mozilla Update extensions page. I clicked on one of the extensions I wanted (Adblock, highly recommended), and clicked the "Install Now" link. Nothing happened, like it wasn't recognizing my click.

Next attempt: Download the XPI file, and try to install it that way. I saved the adblock-0.5-dev.xpi file to my disk, then went into Firefox's File / Open File... menu to open it. Nothing happened. It was like Firefox was just going to ignore the fact that I asked it to open the file.

Next attempt: Drag the XPI file from the folder into Firefox and have it open the file that way. Still, nothing happened.

I went to the Tools / Extensions menu item to see if something was stopping me from installing extensions, an error message, something. No joy.

I searched around the Internet looking for people with similar problems. I checked out the Firefox help on Firefox forum. Nothing pointed me in the right direction.

Finally, I tried hunting around in all my Tools / Options... settings to see if something there would help me out. Hmm. Tools / Options / Advanced / Software Updates / Allow web sites to install software. There it was. I had, many months ago, unchecked this box for security reasons when I first installed my browser. Even though I was installing the XPI file locally and not from a web site, that security option was stopping the extension from being installed (which is a good thing).

Summary: User error. Firefox was doing exactly what I had told it to do. While I'm suitably chagrined, it sure would have been nice if Firefox would have told me what I was doing wrong rather than ignore my attempts to install the XPI files. How about an error dialog, "Your security settings prohibit installation of browser extensions."

Next stop: A check of the bugzilla site to see if this feature is on the to-do list.

Update: Bugzilla has this problem logged as Bug 248486.

Two duplicate bug reports were filed by others similarly frustrated. It looks like someone wrote a patch for it, so maybe the fix is in the nightly builds even now. But I'll wait until Firefox 1.0 comes out to enjoy the fix.


20040821 Saturday August 21, 2004 Permalink Comments [1]
Using JDK 5 varargs as bulk setter method
Published by Tom | August 18, 2004 12:45 AM EDT |
After thinking I couldn't see using the new varargs feature in JDK 5 every day, I thought of a potential use that could cut down on repetitive code: initializing a bean or value object.

As an example, say I wanted to create Person class that contains the person's first name, middle name, last name, and a nickname. I want all values to default to an empty string if not supplied by the caller.

For a standard Java bean, I could create a class with all the "name" instance variables initialized to the empty string, then write setters for the values. That way, Person bean instances would have the values set by callers, but contain empty strings for any values unset. For convenience, I'd probably include a bulk setter method that would take all four strings. Something like:
   setAllNames(String last, String first, String middle, String nick) {
      lastName = last;
      firstName = first;
      middleName = middle;
      nickName = nick;
   }
But maybe the caller would want to just set the first name and last name. Of course, they could call the method passing in empty parameters:
   setAllNames("McQueeney", "Tom", "", "");
but for convenience -- especially if there were more the two unneeded parameters, I'd probably want to provide the method:
   setLastFirst(String last, String first) {
      lastName = last;
      firstName = first;
   }
And now I can see where having a method that would take a variable number of arguments could help.

As a test, I wrote the following sample Person class. Instead of providing all the setters and getters and creating a bulk setter, as mentioned above, I put all property-setting in the constructor for two reasons: first, to keep the code short, and second, to show that a varargs constructor becomes the default constructor. This seems like a neat little feature. (While in the back of my mind I'm thinking, "How are programmers going to abuse this neat feature?")

Here's my Person class, coded using JDK 5.
public class Person {
    private String lastName;
    private String firstName;
    private String middleName;
    private String nickName;

    public Person(String... params) {
        lastName = firstName = middleName = nickName = "";

        if (params.length > 0) lastName = params[0];
        if (params.length > 1) firstName = params[1];
        if (params.length > 2) middleName = params[2];
        if (params.length > 3) nickName = params[3];

        if (params.length > 4) {
            throw new IllegalArgumentException(
                "Constructor called with too many arguments"
            );
        }
    }

    public String toString() {
        return "last: '" + lastName + "', first: '" + firstName +
            "', middle: '" + middleName + "', nick: '" + nickName + "'";
    }

    public static void main(String[] args) {
        System.out.println(
            "No args: " +
            new Person()
        );
        System.out.println(
            "1 arg: " +
            new Person("McQueeney")
        );
        System.out.println(
            "2 arg: " +
            new Person("McQueeney", "Tom")
        );
        System.out.println(
            "3 arg: " +
            new Person("McQueeney", "Tom", "X")
        );
        System.out.println(
            "4 arg: " +
            new Person("McQueeney", "Tom", "X", "Spiff")
        );
        System.out.println(
            "5 arg: " +
            new Person("McQueeney", "Tom", "X", "Spiff", "bad!")
        );
    }
}
(I'm not recommending the above coding style as a best-practice!) Here's the output:
> java -cp . com.mcqueeney.tiger.Person
No args: last: '', first: '', middle: '', nick: ''
1 arg: last: 'McQueeney', first: '', middle: '', nick: ''
2 arg: last: 'McQueeney', first: 'Tom', middle: '', nick: ''
3 arg: last: 'McQueeney', first: 'Tom', middle: 'X', nick: ''
4 arg: last: 'McQueeney', first: 'Tom', middle: 'X', nick: 'Spiff'
Exception in thread "main" java.lang.IllegalArgumentException:
  Constructor called with too many arguments
     at com.mcqueeney.tiger.Person.(Person.java:19)
     at com.mcqueeney.tiger.Person.main(Person.java:51)
The benefit of varargs now is I can provide a bulk property setter with only one method, and allow the caller to pick how many of the properties to set.

Of course, bulk setters like this suffer from the same problems as other bulk setters:
  • You can't name the parameters, so you have to read the javadocs to figure out what order to pass everything.
  • You still have to provide the missing values for properties in the "middle" of the varargs set that you really don't want to set.
(By the way, I think the Groovy language allows you to specify the parameter names when you call a method.)

I can see bulk setters using varargs reducing some code. For instance, the java.util.GregorianCalendar has constructors that takes initial values for the date and time:
    public GregorianCalendar(int year, int month, int dayOfMonth);
    public GregorianCalendar(int year, int month, int dayOfMonth,
                             int hourOfDay, int minute);
    public GregorianCalendar(int year, int month, int dayOfMonth,
                             int hourOfDay, int minute, int second);
which seem like they could be implemented with one Integer varargs constructor, using the new auto-unboxing feature in JDK 5 to easily set the integer properties. (Out of curiosity, I checked the source code for JDK beta 3 Build 60, and, no, they didn't retrofit GregorianCalendar this way.)

When searching around the Internet for code samples using varargs, one of the more-complete explanations was this Chapter 5 excerpt from Java 1.5 Tiger: A Developer's Notebook, by Brett McLaughlin and David Flanagan.
20040818 Wednesday August 18, 2004 Permalink Comments [7]