This post originated from an RSS feed registered with Java Buzz
by Matt Raible.
Original Post: Tapestry by Example with Erik Hatcher
Feed Title: Raible Designs ~ We Build Web Apps
Feed URL: http://static.raibledesigns.com/500.html
Feed Description: Opinions and tips on how to build web applications using Java. Currently using Hibernate, Struts, XHTML, CSS, Ant, JUnit and XDoclet.
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
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.
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 sour
8
ce
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.