Tapestry - "we try to make the simplest approach the correct approach." I haven't been blogging much of this session b/c I'm just sitting back and
soaking it up. It's a good session and Howard is a good speaker. I'm learning a lot about Tapestry and it's philosophy about web development.
I especially like the line-precise error reporting - it's something that all frameworks need to do better.
Tapestry looks very cool. You basically
write an abstract Java class that has abstract methods for properties you define in an XML file. Tapestry them implements this class and its abstract
methods. The class that Howard wrote to handle a login form is very simple - it's only about 7 lines long - and 4 of those are abstract methods!
The HTML form is cool too - not much of the HTML
has changed since it was bare-bones HTML. He's merely added some a few "jcwid" and "listener" attributes to some of the elements.
Tapestry is a large system of subsystems, all implemented behind interfaces. It ships with its default behavior (i.e. page/template pooling), but you can
(supposedly) easily change this behavior or implement custom classes. Internationalization is a first-class citizen in Tapestry - no surprise here since it is
in most MVC frameworks. Tapestry 3.1 will embed Hivemind at its core and will provide much easier integration with tools like Hibernate and Spring.
Tapestry's "Validation Subsystem" looks very rich - providing both client side and server side validation. It uses Field decorations to highlight both labels
and fields when validation fails. By default, it promotes using CSS to change colors, backgrounds, etc. There are a couple of Helper Beans for validation:
the Validation Delegate and the Validator. It's pretty neat that you can bind a label to a field in XML. Since HTML already allows binding
<label>'s to form elements - you'd think that Tapestry could harness this by parsing the template. I suppose it's just easier to require the
XML binding - then you don't have to worry about the user writing invalid HTML.
Howard is trying something new in this presentation - real-time coding. I use this in my presentations and it works pretty good. He's having some serious
issues b/c he can't mirror his laptop's monitor with the projector. This obviously makes it difficult to code since the slide show is his monitor. I
try to use pre-canned code (i.e. IDEA Live Templates) so there's less chance of fat fingering things. I also use a Mac - on which mirroring works great.
The "Page" object is pretty cool in that it contains a bunch of lifecyle methods you can override. Most frameworks don't have lifecycle methods. I guess
Spring's SimpleFormController does with onSubmit, onBind. Lifecycle methods are a Good Thing IMO. The formSubmit()
method is always called,
regardless of validation errors. Therefore, you have to get the IValidationDelegate and check if it has errors before continuing. I wonder what the logic
behind this is? Most frameworks seem to support automagical validation - with no further work required by the programmer. I guess it's kinda cool b/c you
can continue with validation errors if you want to. Choice is always a good thing.
Howard just showed us a client-side validation example. The wicked cool thing is that the client-side script is configured in a .page file rather than in the
HTML template. Most frameworks I've seen (that support client-side validation) require you put something into your template. This was a good
talk, I'm definitely interested in Tapestry and excited to start learning it in the next couple of months.
David is going to cover some JSF advanced topics: data table, tiles integration, custom components and validators. I was talking
with Rick Hightower last night. He mentioned that he's been doing a fair amount of work with JSF lately and really likes it. He
actually said he thinks he can develop a webapp faster with JSF than he can with Struts. He also said that JSF ships with a lot
of what you need - and a lot of the JSF books seem to cover how to add new stuff (custom components and validators) you don't need. This is to
say that the books tend to cover the features of JSF, rather than how to develop successful projects with JSF. I said I thought
it'd be nice if there were some JSF books by folks who'd used it to deliver applications. More of a "here's what you need to
know" kindof manual. I think that's what JSF needs.
The <h:dataTable> in JSF is pretty much the same as the <c:forEach> tag in JSTL. An interesting note on the JSF
expression language - it starts with a # instead of a $. For example:
<h:dataTable value='#{tableData.names}' var='name'>
...
</h:dataTable>
The major difference between JSF and JSTL's expression language is that JSF EL can access managed beans. The JSP 2.0, JSTL and
JSF expert groups are going to work together to try and synch up their expression languages. Personally, I don't see why the JSF
folks didn't just use JSTL and simply include managed beans in the lookup logic. Here's a wierd one - if you use any "template text",
i.e. in a dataTable - you have to wrap the text with <f:verbatim>text</f:verbatim>. David says this is one of the embarrasing
things about JSF. He hopes it'll be fixed in the next version.
The <h:dataTable> looks very similar to the
DisplayTag. Sweet - that's one less thing I'll have to worry about when creating a JSF app.
I've said it before and I'll say it again - my two favorite tag libraries are the DisplayTag and
Struts Menu. As I'm learning new frameworks, one of my major goals is to reproduce the same functionality I enjoy in my Struts+JSP
apps. It's been pretty simple so far with Spring and WebWork, since both support JSP. However, it might get a bit tricky with Tapestry
and JSF. I'm sure it'll be possible (and hopefully easier) to reproduce this functionality, it's just a big unknown
at this time.
"Form" beans in JSF are not like form beans in Struts. It's really just a class that doesn't extend anything and has action handler methods.
An interesting point - the actionListener's value (which is really a class.methodName) can be any class in any scope OR it can be a
managed bean. How about some code:
public class Form {
public void changeLocale(ActionEvent e) {
FacesContext context = FacesContext.getCurrentInstance();
Map requestParams = context.getExternalContext().
getRequestParameterMap();
String locale = (String) requestParams.get("locale");
if ("english".equals(locale)) {
context.getViewRoot().setLocale(Locale.UK);
} else if ("german".equals(locale)) {
context.getViewRoot().setLocale(Locale.GERMANY);
}
}
}
The major reason behind the FacesContext is to support Portlets. So rather than using a ServletContext or PortletContext, the FacesContext
provides a level of abstraction. The underlying theme of JSF: To be as flexible as possible. This is to say that there are many ways
to do things with JSF. I often think it's better to have less choices when learning a technology, but once you're versed in it - choices
are great. I guess I just wanna know the best way to do things, not all the options. Actions are for business logic, ActionListeners are for UI logic. ActionListeners are always fired before Actions - in the event
that you have an actionListener and an action defined for the same component. Listeners and Actions are really just methods on a class and they
can actually both be in the same class. JSF is starting to appeal to me. This session has been one of the fastest so far - there's only 20
minutes left and it feels like it's flown by.
JSF ships with converters for dates and currencies out-of-the-box - cool! Now David is explaining about a custom
CreditCard converter. This is what Rick was talking about last night. Why do we need to know this stuff? Would a normal talk on another MVC
Framework talk about converters and validation? I bet not. I think it's a good topic - maybe something that other frameworks should cover
more visibly. The Converter interface has two methods: Object getAsObject() and String getAsString(). The Validator interface has one method:
void validate(FacesContext context, UIComponent c). I just asked David about using Commons Validator instead of JSF's core validator. He said, "Yes,
it's possible." Sweet! You can use Commons Validator with Struts, JSF and Spring! Now if we could only get support for it in WebWork
and Tapestry - then I'd eliminate my need to learn another validation engine.
Now David is talking about using Tiles with JSF. It looks as simple as using the <tiles:insert> tag to insert dynamic content into an <f:subview>.
Any time you insert a tiles component, you need to wrap it in an <f:subview> tag. That was short - we're done talking about Tiles. I had some
questions - i.e. can you refer to a definition directly from an action or in the action's navigation definition? Oh well, onto custom components and renderers.
Custom components and renderers seems to me to be something that should be left out of these types of presentations. Sure, it's cool they're possible - but
who's using them? Have you needed them in a real-world JSF application? I only want to know the things I need to know to develop a real-world JSF webapp.
Sorry, I forgot - there aren't any real-world webapps written with JSF. If I'm wrong - send me a link. ;-)
This presentation was good - it inspires me to learn some more about JSF. Maybe there'll be some projects in my next gig that require JSF - that would
be wicked cool. After all, the best way to learn this stuff is to get paid to do it. If nothing else, I'll get to learn it later this year when I write
AppFuse's web layer in JSF.