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!

Wednesday, March 08, 2006

From the fanciful ideas category ...

I was just thinking about a kind of half-measure between normal Tapestry useage and Trails.

One of the tedious aspects of building a lot of web apps (using Tapestry) isn't the managing of data in and out of Hibernate or JDO, it's just the repetition of building a table, inside a form, with each row containing a FieldLabel and a TextField (or PropertySelection, or whatever).

Wouldn't it be nice if I could just plop the following into the middle of my form?

<span jwcid="@edit:EditObject" object="ognl:pojo"/>

And this magic EditObject component could build the rest for me? This, certainly, would leverage Trails code, or Trails-like code. I'm sure there would be additional parameters to control CSS, and to control which properties were to be editted. And, of course, some set of annotations to define the validation of those properties. Maybe even so carefully named Block components to provide row overrides? Again, very Trails.

I think this logic would kick ass when building prototypes.

I was just sending a reply to Matt Raible about Java web framework sweet spots. At the core of my response to why Ruby on Rails is gaining so much mind share is because its represents a solution, not a tool. The Java space, especially the open source crowd, has gotten really good a churning out extremely useful tools. However, we tend to leave the solutions to the motivated students. The lesson of Ruby on Rails is for us tool-makers to get fired up about creating solutions.

This is just the opposite of how Tapestry has evolved, which (of course) parallels the evolution of how my coding and design skills has evolved. Earliest Tapestry was a very pure tool, focused entirely on "animating" HTML tags, as well as the transient and persistent state management. Over time, the components evolved from a focus on a single tag to many tags, to entire behaviors (including early precursors to Ajax techniques). That's great, but it's been left to the imagination of the user to see how those tools fit together to allow you to create a useful application.

This is more than just a question of examples, it's really about the emphasis of the overall framework. "Here's how you edit your object (in one line)" should be the first thing new users see and learn ... giving the users the ability to exactly control the HTML should be lesson three or five or ten. That's where Trails is getting things very, very right.

12 comments:

jesse said...

I should probably invest some more time in learning what trails can do, but the application of hibernate & tapestry is particularly compelling.

Having done some local patches to hibernate for one reason or another I've seen enough of the internal api's to know that there is an equivalent construct for each object to your IComponentSpecification..So, right out of the box you could probably do all of the grunt work validation for most things. Email/other more specialized logical things wouldn't be able to be caught, but 80-90% isn't too bad ;)

I probably don't know enough about RoR to say this either, but at least as far as out of the box DB support we know that the hibernate spec equivalent would also allow someone to know about all the foreign key relationships/etc...Making it easy to decide that a particular set for an entity should be a "PropertySelection" by default since it appears to be a lookup table...Er something?

Sounds like good stuff though! Who's going to write it? ;)

Ron Piterman said...

I must disagree on that last paragraph. It reminds me of a few features in tapestry that are there to make the user do anything he wants and which are really a pain in the ass, like template/page-spec search path and
allowing one to declare components in the html.

If its a framework, then its a framework, and not an implementation. Watch the wonder that trails does using this framework, and improve the framework, also to make trail's life simpler, but thats no a framework role - not in the scale I see tapestry involving to.
Once it gets to be an apache top project it could embrace trails as a subproject, but I don't think one should add more features to this too-many-features framework.
Instead, make what is there work good (add validation strings customising :) ), improve its functionality (like changing how it does things in order to support ajax) and be good documented. (see contrib:table, thats a real shame for the project.)

Cheers,
Ron

Ron Piterman said...

I must disagree on that last paragraph. It reminds me of a few features in tapestry that are there to make the user do anything he wants and which are really a pain in the ass, like template/page-spec search path and
allowing one to declare components in the html.

If its a framework, then its a framework, and not an implementation. Watch the wonder that trails does using this framework, and improve the framework, also to make trail's life simpler, but thats no a framework role - not in the scale I see tapestry involving to.
Once it gets to be an apache top project it could embrace trails as a subproject, but I don't think one should add more features to this too-many-features framework.
Instead, make what is there work good (add validation strings customising :) ), improve its functionality (like changing how it does things in order to support ajax) and be good documented. (see contrib:table, thats a real shame for the project.)

Cheers,
Ron

Hugo Duncan said...

Funny you should mention that, I am working on just such a component...I am spelling it <span jwcid="@edit@lt;EditObject>" object="ognl:pojo"/>

My basic approach is dynamically instantiate an editor class with a generic superclass, and then enhance it, controlled by annotations on the pojo.

I am thinking of giving the editor a "layout" parameter to control the style of the layout.

The Tapestry programmer could user the same class as a base component,(which would provide all the required components to edit the object), and provide a custom layout - a smooth progression from standard layout to fully custom.

James Carman said...

Yes, that's been one of my ideas all along is to have Trails be just a component library and not the entire application itself. You'd still be able to do something like you said...

<span jwcid="trails:EditObject" />

to put an object editor form in your application. You'd have to maybe have parameters for what method to call on submit and what "object" you're editing (and css and the like as you said).

James Carman said...

That's what I've been wanting all along is for Trails to become a component library rather than an application. What we need to do to make that happen is move everything out of Spring and into a HiveMind module!

plalloni said...

I've made something very much like this in the past, it was called LessCRUD, and the interface was sligthly different, instead of giving it a pojo to edit you give it a CRUD interface implementation from which it reflects everything it needs to render a complete CRUD form allowing you to do searchs by criterias (from findByXXX methods) and of course, editing any instance returned by a finder. I done this like a year ago with Tap3, so I think it could be nice to give it a little refresh towards Tap4 and all it's new stuff. If there's interest I could take on this refreshing and of course it would take some redesign to use the new features of T4.

jesse said...

I must disagree with you as well Ron. As much fun as it is developing all of these cool services with tapestry/hivemind, it is also very frustrating to see people re-inventing the wheel over and over again in the user forums.

It shouldn't be in the core, but at the very least tapestry could identify who they "like" for particular things and possibly go a bit further than just linking to the external project. A clearer message might be a "hibernate" or "ajax" link that provides a brief description of how the project in question supports this technology in tapestry, and then an actual link to the project.

That's what I'd like to see at least. Solutions ~are~ needed. The more things that allow people to just get going with an app and avoid the setup parts the better...Just so long as they don't try and stick everything into one monolithic project ;) That would be overwhelming and problematic.

Howie S. said...

I haven't had the opportunity to play with Tapestry just yet, but I'm reasonably certain this would be accomplished fairly simply in WOF, and we both know how familiar you are with that :)

Assuming you can dynamically assign a text input field to a variable, or even use NSMutableDictionaries (err, I mean, Maps, heh) to store values, this all becomes rather easy:

Get a list of all the properties a given class has (get* methods with no arguments). Use a repetition to iterate through the total number of properties -- the Tapestry equivalent of WORepetition or even jstl's c:forEach. I'm sure this comes standard with Tapestry. Inside the repetition, have a textfield bound to a setter that takes into account which property ID# the loop is on, matching that up to an internal list holding the property name. I've done something similar in WOF to faciliate a neat table with two rows of data -- the uppermost being a thumbnail image and the lower one being a series of actions you could perform on the image. Was a pain to write but the end result was very nifty, and made things align properly and be happy like that.

Anyway, something like that ought to work fine, albeit a little hackish.

Hugo Duncan said...

I have posted some initial code to implement such a component at http://www3.sympatico.ca/hugo.duncan/EditComponent.tar.gz and written a small description at http://planesailing.blogspot.com/

Anonymous said...

Found this post searching for exactly this kind of component... which means it doesn't exist yet... shoot!

Ben Eng said...

Instead of having EditObject be a concrete implementation of a generic object editor, I would like to see it behave like RenderBlock. Based on the object's class, it should look up the appropriate editor component and render it in context. That would fulfill a huge need to be able to control the specific editors that are appropriate to each object, because of usability issues (layout, styles, type of controls, derived values), security, validation, etc.