NOTE: This is outdated information that applies only to Tapestry 4. For the current AJAX support see http://tapestry.apache.org/ajax-javascript.html

This is a sandbox page for a suggestion for some changes of the ResponseBuilder API, By Ron Piterman

The Problem

Currently, I am working on an application which makes a very extensive use of Ajax based on tapestry 4.0.

We started prototyping a few monthes ago and are moving into implementation just as 4.1 is released - and are considering moving to 4.1, but found that the current API is insufficient to cover some important use cases we deal with.

While giving answer to several Ajax Rendering use cases, the current API apears to be not flexible enough and non extendable:

Current Response rendering and processing

The ajax response builder (org.apache.tapestry.services.impl.DojoAjaxResponseBuilder) renders an xml in a general strcture as described below (the structure is described according to the tapestry.load javascript function):

<ajax-response>

</ajax-response>

Where TYPE is either "exception" , "script" or ignored and ID is either a script role ("initializationscript" , "bodyscript" , "includescript" ) or an ID of an html element in the document to replace.

The ResponseBuilder interface contains methods to support exactly these types and IDs - and some other which are used for example in the JSON response builder.

what this does not cover

The current use-cases we have, and which are not covered by this API are in general passing XML/HTML rendered by tapestry as parameters to function calls on dojo widgets.

For example:

Our application makes intensive use of tables. Many of these tables have hierarchical structure of :

The table is rendered by a custom component backed by a custom model, which is designed to render on demand only specific rows, according to the request - this is an application design decision, beacuase rendering the whole table is very expensive for the database and the backend.

When the user clicks one of the not-selected header-rows, only the needed child rows are rendered, and tapestry sends an RPC to the to-be selected row-widget, passing the rendered rows as parameters, which are then added to the document into the right position.

The rows of the group which was previously selected are discarded from the document.

It proved to be a very confortable praxis, of matching a tapestry component to its corresponding dojo widget and sending RPCs to this widget from within the tapestry component, without using javascript from tapestry, but instead, using a custom response-rendering.

suggestion

What the responseBuilder implementation does, specifically the DojoAjax one, is wrap rendering blocks inside an xml. It uses different methods to generate different types of "actions" - but is limitting the structure of the response to a small set - corresponding to to the tapestry.load javascript method.

My suggestion would be:

instead of the different write methods (writeBodyScript , writeInitializationScript, writeInitializationScript , writeExternalScript ) and the corresponding isXXXAllowed, use one single method:

write( String type, String script, IReqeustCycle cycle );

write( String type, IRender render, IRequestCycle );

and

updateComponent( String type , String ...ids );

create a hivemind configuration for the response builder and let different services handle the string/Irender and render any desired xml around them.

The services would need also some kind of event-calls to allow them to respond to response rendering cycle events.

On the javascript side, instead of using a predefined processing for some types of responses (currently "exception", "script", and none) make an object registry in form of a Map, which creates handlers for different types of response nodes, and processes them, adding also to them some event calls to "let them know" when the response is done, so they can do their job after.

This will not change the functionality of the ResponseBuilder or the javascript, but will make it extendable, in the same manner hivemind makes tapestry extendable, and allow all kinds of wierd use-cases be handled with ease.

alternative

Now the change described above is a major API change, but it does allow an easy refactoring with deprecation.

Alternativley, it would be enough for my company's case, if a method updateComponent( id , callbackName ) is added, which renders an <xxx type="callback" id="..." callback="callbackName"> -

The tapestry.load method could then call callbackName on the widget which is the source of the event which triggered the Ajax-request.

Tapestry_4.1_ResponseBuilder_sandbox (last edited 2011-01-02 21:18:55 by BobHarner)