« Previous day (Jul 12, 2005) | Main | Next day (Jul 14, 2005) »

20050713 Wednesday July 13, 2005

com.sun.* classes in Creator applications

One of the nice people I met at JavaOne was Dave Johnson, the guy behind Roller, which is the open source blog server software we're using at Sun. In this blog entry he describes his recent experiments with learning JSF and using Creator 2:

I was hoping to build a simple JSF front-end for Roller, just for fun. Creator looks great and the form designer works well, but when I noticed how many com.sun.* classes end up in the generated code I backed off. According to the release notes the whole JSF implementation and com-sun-web-ui-appbase jars are redistributable (...), but the idea of IDE specific code makes me uncomfortable -- especially in an open source context.

The same issue came up last year when we released Creator 1.0 beta. So in this blog entry I'd like to explain why you'll notice a number of com.sun classes in your Java files maintained by Creator, what they're for, and what you can do about it.

Creator 1.0 provided only the standard JSF components (javax.faces). If you drop a command button, you get a <h:commandButton value="Submit"/> entry in your JSP - just like your JSF books tell you.

The big problem is that the standard components are extremely limited. When you build applications using the standard components, you've created a web page that would look right at home in 1995.

In addition, the component set shipping with JSF is limited in functionality. We've gotten tons of requests for additional components: file upload, tree, tabs, calendar, etc. Therefore, in Creator 2 we're no longer focusing on making web applications that look identical to what you'd find in an off-the-shelf JSF book. Instead, we've provided a new component library, consisting of pure JSF components obviously, which have additional value add. Buttons can be configured to be primary or secondary (affects visual appearance), they can be configured to disable themselves when clicked (so you don't get double submits on forms), they follow theme styling, etc. And of course, we have new components like trees and calendars to address those needs. Obviously, if you use these components, your page beans will include references to additional com.sun.* classes.

Don't despair however - if you want to use the standard JSF components, you can do that - just look in the palette for the component categeory named "Standard". This is where the standard JSF components live - drop these and you'll get your familiar JSF commandButton, outputText, panelGrid, etc. components. To make it easier to spot these in the palette, so you don't grab the "wrong" button for example, all the icons for these components are now tinted blue as shown in the screenshot on the right.

There are a couple of more areas where you wind up with com.sun classes. First, your page and session beans themselves. If you look at your Java files corresponding to your pages, you'll notice that they're very small and simple; you basically have several empty stub methods where you can add code that is run during different parts of the page's life cycle: initialization, render, and cleanup. JSF doesn't make it that easy. That's why we've created an abstract class you can extend (and our page beans automatically do this) where the super class has all the convenience methods you want. For example, your page beans code can simply call getFacesContext() to get the FacesContext object, or it can call getValue to perform value binding expression evaluation. Just look at the code in the ancestor classes to see the PhaseListener magic that is necessary on the programmer's part to make these simple callbacks possible.

So this was a deliberate choice in order to make it really trivial and easy to write "event handlers" for your web component's events, like button presses and text field validations. There is nothing special about this code - its source is fully included and in Creator 1.0 you can simply press Alt-G over the parent class name in the java file to open it. Unfortunately this doesn't seem to work in Creator 2 EA. But the source code is all there; go extract rave2.0/docs/jsfcl-src.zip and you'll see it. (It's in the wrong place which is why the normal IDE facilities for warping to it doesn't work. This will be fixed before ship date.)

There's one final area where you can end up with com.sun classes: data providers. Standard JSF lets you hook its Data Table up to arbitrary data structures (and I've described how before). However, it's pretty inconvenient and not done in a general fashion. In Creator 2 we have a new abstraction layer in the middle, which all components know how to talk to. We then implement these interfaces for a wide variety of data sources. The net result is that you can drop not only a JDBC table, but a web service method or even an EJB method on GUI components, and all the binding is handled correctly. These data provider wrappers can also end up in your code.

So in short, yes, if you choose to use the new components and databinding facilities, you end up with additional com.sun.* classes in your code. You also get this in the page beans from the app model. Our focus in Creator has been to make web apps easy and feature rich, which resulted in adding some convenience classes around the standard primitives provided by JSF, and of course a new set of JSF components.

As JSF matures there will hopefully be fewer and fewer areas where this is needed.

(2005-07-13 19:24:17.0) Permalink

Don't Code Like This!

I was trying an open source web framework yesterday, and couldn't get it to work so I stepped through some of the code on the server with a debugger, and came across some code fragments that I thought I would submit to the Hall of Shame.

Besides, it's fun to blog about this, because each time I mention coding style I invariably get passionate responses from people defending their beloved style.

In the following, the class and method names have been changed to protect the guilty.

At first, I simply got a generic JspException. The code was doing this:

        ...
    } catch (ConfigNotFoundException ex) {
        throw new JspException(msg);
    }
The original stack trace is not chained to the new exception! Please pass it in - JspException has a constructor which takes both a message and the root cause exception, ex in the above. If you're using some Exception class which is older and doesn't let you pass in the root cause, such as DOMException, then first create the exception, then call the initCause method on it, and finally throw the exception object.

The second code fragment I came across was this:

    try {
        return findConfig(servletContext).getResult(foo, servletContext);
    } catch (NullPointerException ex) {
        throw new ConfigNotFoundException("Can't find configuration");
    }
The above code is using exceptions for flow control. Rather than first calling findConfig, then checking if it is null, it just goes ahead and tries calling it anyway, relying on the NullPointerException to handle this case.

The code also has the bad effect of catching all unintended null pointer exceptions in the subsequent getResult method call. These are unrelated to the ability to find the configuration, so the error message would be misleading. (And again the original exception is not chained).

(2005-07-13 19:01:59.0) Permalink Comments [4]