Wednesday July 13, 2005 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) PermalinkI 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).