It's Saturday morning and I plan on learning more about Tapestry this morning.
There's pretty light attendence in the room. Too bad - I bet if it was a
JSF talk, the room would be packed. In this talk, we're actually going to
build a real application on-the-fly.
Why another web framework?
- HTML should be HTML
- JavaScript Embraced
- Reusable components
- Free developer from dealing with plumbing
- Request/Response
- Session/Application Scope
- URL Mappings (nice, but leads to ugly URLs)
- Event handler driven
- Asset handling
- Line-precise error reporting
Erik says its one of the few
frameworks that embraces JavaScript so much. I dig this b/c I think
JavaScript is important for web development. Look at what the GMail guys
have done with JavaScript. It'd be wicked cool to have this sort of thing
open-sourced so we could all create GMail-type interfaces.
Dirty Laundry
- Heavy Duty - can be overkill for small/simple app
- Potentially steep learning curve. More of an un-learning curve. The Servlet
API isn't in your face - so all that knowledge is useless.
- Not widely accepted - managers haven't heard of it
- Some awkward conventions
(i.e. abstract classes)
- and some non-intuitive necessary tricks
- Unit testing tough - do you unit test your swing app's listener methods?
- Tapestry Test Assist should solve this problem
- Howard's caught the TDD bug, so this should get better
- Lousy URLs
- there's a patch on the wiki to fix this
- Tough to do hit/stat tracking
-
J2EE declarative security
- Example applications
Workbench Demo - DatePicker
component does do i18n (very cool!). Client-side validation does one-field
at a time, like WebWork does. I prefer the "all messages in one pop-up" approach
that Commons Validator has. Pallete component looks very cool - you can move
and re-order items from a multi-select on the left to a multi-select on the
right. Chart component looks pretty cool - you can generate graphs very easily.
Unfortunately, it's not part of Tapestry, but you can see how to do it in
the Workbench app. If you want to see an online version of the workbench,
I have it setup on my server.
Repositories for components: Tacos,
Tassel, T-Deli
and a few
mentioned on the wiki.
To bring a component to life, you simply add a "jwcid" to an HTML
tag. You can specify initial values for page properties using <property-specification
initial-value=""> tag in your template's .page file. The value is implicitly
an OGNL expression, and you can define lists using "{'value1', 'value2',
'value3'}". This is great for prototyping before you have a backend or even
a page class. To remove elements in a page, specify jwcid="$remove$" on an
HTML element and it'll be removed at render time. The restriction is you
can't have Tapestry components inside a $remove$ component.
If you don't want to use abstract methods (and hence classes) in your page
class, you can use getProperty()/setProperty() methods. However, the recommended
way is to use abstract methods.
Templates - two different types. You can put the @component
stuff directly into your page - or you can use jwcid's and refer to a name
that's defined as a <component> in your page-specification XML file. The
Border component can be used to do page decoration like SiteMesh.
You can use the Shell component to declare stylesheets/scripts on
a per-page basis. This is something I do a fair amount, so it's nice to see
it's built into Tapestry.
Internationalization - Resource bundles are component specific
(one .properties per page). In a .page, you use <message-binding>. In a template
(.html), you use attribute="message:key" or <span key="">. The "key" attribute
can't be used on any ol' HTML element, only on the <span> tag. In .java,
you use getMessage() and format(). You can also define a custom message source
(i.e. read messages from a database). I'm impressed with how easy it is to
do i18n in Tapestry. It's also cool that i18n is built-in for templates.
Just include a locale extension on your page and it'll be rendered for users
with that locale. For example, home_fr.html will show up for users with the
French Locale.
Engine - gets all requests. Visit class
- POJO that acts as like an HttpSession. You can configure it in the .application
file. You can talk to your "Visit" class in a template using "ognl:visit".
To call methods on it, just use "ognl:visit.method". Majority of services
originate in the Engine. Generally override createXXX methods. Engines can
be pooled or created on a per-session basis.
If you override the createXXX methods in Engine, you change the
behavior for:
- message source
- global and visit
- property configuration
- template and component sources
contrib:Table - to override use <tr jwcid="columnColumnValue@Block">
- where "column" is the name of the column. Using this, you can easily put
links and such into a table cell. Built-in TableModel can be used
to talk directly to a JDBC DataSource. The TableModel is smart in that it
only brings back the rows it needs to display. Add an exclamation point to
the beginning of a column name to turn off sorting for that column. i18n
is built-in for headers - the name of the column is simply looked up as a
key in the page's .properties file.
Exception handling - Bail out by throwing an ApplicationRuntimeException.
This tosses you to the default exception page, which you can override and
"pretty up".
Validation - it's robust, but it can only validate <input
type="text">. Erik thinks that Tapestry's validation framework could be much
simpler and easier to use.
Dynamic Templates - can implement a IDelegateSourceTemplate
and pull templates from a database or content-management system. To register
your new TemplateDelegate, you can just register an <extension> in the .application
file and point it to your class.
Page Lifecycle - initialize(), PageRenderListener(), PageValidateListener(),
PageDetachListener(). Can use an ExternalCallback and ICallback to set properties
on one page from another. Callbacks look very cool and there's a lot of discussions
about them on the mailing list. The VLib app has a fair amount of callback
examples.
This was definitely a good Tapestry session - thanks Erik.
One of the major issues in XDoclet's JIRA has been the fact that XDoclet doesn't work with JDK 5.0 syntax. After many comments and lots of debate, Anton Adamansky has submitted a patch. If you want to use XDoclet with JDK 5.0 - you might want to give this patch a run for its money. Hopefully we can get it included in XDoclet in the near future.