Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Tuesday, March 22, 2005

Tapestry Portlet Hello World

Well, it's only been a few weeks of hacking, but I do have Tapestry Portlet Hello World running side eXo:

For the moment, I'm calling these "Taplets" (Tapestry Portlets). There's still a lot of work to be done, but this is very encouraging.

Meanwhile, the changes in 3.1 continue to mount and the other committers (including Erik Hatcher, who has been a Tapestry 3.1 alpha guinea pig) have started to chant 4.0! 4.0!. That's one option, another is to restore a few missing things, like RequestContext as access point to the HttpServletRequest. Also, the fact that the AbtractComponent base class makes the getMessages() and getComponentId() methods abstract is giving Eric more headaches.

Of course, if it becomes Tapestry 4.0, I would start really fixing things, starting with abstract classes and required inheritance. Here's a thumbnail of what Tapestry 4.0 would do:

  • The page/component hierarchy still exists, but there's exactly one implementation of IComponent.
  • Each component has a peer; this is the class you provide.
  • The peer has the component injected into it.
  • The peer does not extend any class, though it can implement the various listener interfaces (such as PageValidateListener).
  • The peer may implement IRender, in which case the component will delegate rendering to the peer (otherwise, the component will render using a template).
  • The page/component specification is optional.
  • Page/component names must map directly to Java classes (by searching for classes within a list of packages). These classes are for the peer.
  • The .page file must be in the same folder as the .class file.
  • Each page or component must have a unique peer class.
  • The class loader will be extended to modify the peer class as it loads:
    • Instance variables are self-encapsulated (i.e., _myProperty --> getMyProperty()).
    • Accessor methods are rewritten for transient, persistent, or parameter properties
    • Other enhancements as with 3.1 today (i.e., to inject assets, components, ASOs, etc.).

It's pretty daunting, especially considering my current schedule, and it needs to be fleshed out some. The end result will be more distant from Tapestry 3.0 than 3.0 is from 2.3. It will be a chance to clean house: to clearly separate APIs (such as IComponent) from SPIs (such as TemplateParser or ComponentSpecificationSource). In fact, I would love to have a internal package where backwards compatibility from release to release is a non-issue. It's also a chance to get rid of the leading 'I' on interfaces!

Scary stuff; times like this I really feel the weight of the world on my shoulders.


James said...

Nice work on the Taplets! Now we just need some Ajax / Flex like components and the worlds problems are solved... At least in my world. :) Thanks Howard!

Brian said...

Very nice seeing the portal support. And your list for the next major release does appear daunting - but the beauty of it is... put it in a roadmap and there's a community to help. Take some of that load off. :-) [yeah - I'm one of the chanters for 4.0 ;-)]

Great work!

Numa said...

Hello Howard,
That's really great to hear!!!!
I am happy to here that the IBaseComponent or IFormComponant inheritance will not be required, this will make page and component logic more like simple POJO services.
I have some other requests and suggestions:
- How hard would it be to have the output of the printwriter not rendered to the client browser but inside a buffer that would be available from within a component. This would allow us to use Tapestry to render custom html email or text files or even pdf. It would allow page caching, and for this it would be grate to plug a cache provider and the cache would vary by component or page property and duration. I mean we could say cache the page for 2 minutes varying on << myComponent.name, myComponent.hotel >>. The page or component will be cached using a (plugable) cache provider, the cached html will keep special tags for the session_id eg: < jwcid="sessionId" /> that would be replaced before rendering to the browser, this means even session aware components or page are cacheable, of course this won't be useful if the component or page only displays session information, but in many case it won't be the case.
The problem then for caching will be component hierarchy, shall a cacheable page that contains two component that are not cacheable be cacheable or not? Of course if the cacheable page is keeping the same component output then we might be out of synchronization. But the page could render itself and keep a place older for all cacheable components. Thus when the page render to the client browser, most of its rendering will be cached and all non cacheable components will be rendered. I hope i was not too unclear.
- A second request suggestion would be regarding form components, i think all form components should be valid, be cause it creates a confusion that you must use to different type of component for an inputField. All field should be valid field with a default validator that we could override in component parameter, the default validator could be the same for any component, it would not do anything (empty validator or maybe only required).
Another request that was unclear in your book or in the Tapestry documentation are how to develop form component and what are the difference between getName and getId, why do you have to do a setForm etc.... (I now have found out, but I have found out by trial and error)
- Another request or suggestion for forms would be that all form component implement the comparable interface (or injected at runtime), this would allow multi field validation using components name. Indeed must of the multi field form validation are of the form: "if (fieldOne != null && fieldTwo < fieldOne) then errorMsg". If we have comparable components then we can write this expression in ognl easily, the < or > or <= etc. will use the comparable interface, thus a comparable component could implement itself how to compare its contained value, of course the value itself could implement comparable thus the previous expression would be fieldOne.value != null etc...
Another thing that would be very interesting would be an email notifier in case of exception page, thus the exception page would be sent by email to a list of recipient defined in the application file, this should be rather easy if we have the ability to get the output of the printwriter.
- Would it be possible to have some documentation on how to do a datasqueezer for some complicated object (passing object in parameter for session less applications)?
- one last thing, a behavior that i find strange is that if you click on an action link it will trigger the rewind cycle, but if you click on a directLink it won't, why?
That's all the ideas i had using tapestry since 4 month, i must say that Tapestry rocks! it is one of the greatest tools available for developing webapps (I have tried JSF and struts and still look at it but there is no comparaison)
I would be happy to help especially for the printwriter output to make emails and to add an email error notification tool. I have been digging in the code, but i don't know exactly where i could catch the printwriter output (well i have an idea but not sure), the other thing is i don't know exactly how to be able to do:
myPage page = cycle.getPage("myPage");
out = page.render(cycle);
//send out by mail ...

Howard thanks for Tapestry and for your great book Tapestry in Action!!!

if i can help or some suggestions are interesting you can send me an email at: numa at euroconsumers.com


bobbyrullo said...

Hey Howard,

Looks like great stuff so far!

I have one minor gripe with the stuff you are proposing for 4.0:

"The .page file must be in the same folder as the .class file."

The way I like to develop is that the web context root is actually in my cvs sandbox, so that when I make a change to a page or component I can see the results immediatly (well, after a call to the reset service anyway) without redeploying and restarting my app server.

Requiring that the page spec be in the same folder as the class makes this a lot more difficult, as my (as most people's I believe) have their classes all jar'd up.

If you can show me a way that I'd be able to work around this issue in future versions of Tapestry, you'd be doing a lot to help me sleep easier at nights.



Numa said...

Hello Howard,
I wanted to correct some comments in my previous post. I found out a new page on the wiki explaining the data squeezer, and i found the documentation of 3.1 much much better than any previous documentation (form components are explained with more details).
One new request that i forgot to post is the labelField for validField, it is a bit redundant to have a displayName in the validField and also a LabelField that can be also the displayName, it would be nice not to have the displayName mandatory in ValidFields.
Sorry for the error in my precedent post and thanks for the great work.


Ken Yee said...

I'd also echo 4.0 as well.
It sounds like you're going to add some incompatibility with 3.1 anyways. Might as well bite the bullet and do the huge changes at once (and hopefully get them right) if users have to rewrite their 2.x apps for 3.x anyways...