Helma Logo
main list history
previous version  overview  next version

Version 3 by hannes on 21. September 2007, 10:57

What I propose here started out while thinking about ways to de-uglify res.debug(). My goals were:

* Give developers control about how the debug output is formatted and displayed.
* Allow developers to include debug output anywhere they wish, either via macro or programmatically (it is currently just appended to the main response buffer).

After trying some superficial plastic surgery, it became clear to me that this is a model case for what Tobi proposed *here|Handler for rendered skins* and was implemented as res.pushBuffer() and res.popBuffer() in Helma 1.6. (This wasn't immediately obvious because I didn't think "skin rendering" when thinking about res.debug().)

=== res.pushBuffer() and res.popBuffer() in Helma 1.6

These new response methods allow to slip an existing java.lang.StringBuffer on top of the resoponse buffer stack (as opposed to res.push(), which always creates a new one), and get the StringBuffer out of the response buffer stack without converting it to a String (versus res.pop(), which does just that). In other words, the new methods allow you to get a StringBuffer in and out of the response object multiple times without the penalty of StringBuffer to String conversion.

Unfortunately, res.pushBuffer() and res.popBuffer() is not quite as powerful as it should be. The problem is that the managing of StringBuffers is left to the application, which makes it quite difficult to implement a generic res.debug().

=== Proposed enhancement: manage buffers in res.buffers

In my eyes, we should enhance res.pushBuffer() to allow putting response buffers in a well-known, accessible location, and/or get them from there. Let's assume this location is called res.buffers. res.pushBuffer() would then optionally take a String argument:

  * Use buffer as new response buffer,
  *  without registering it in res.buffers.
  res.pushBuffer(java.lang.StringBuffer buffer)
  * Use the StringBuffer in res.buffers[name] as new response buffer,
  * creating it if it doesn't exist.
  res.pushBuffer(java.lang.String, name)

A third variant may or may not make sense:

  * Use buffer as new response buffer and register
  * it as res.buffers[name], overwriting any previous buffer
  * with that name.
  res.pushBuffer(java.lang.StringBuffer buffer, java.lang.String name)

=== Auto-Expanding res.buffers

For programmatic access to res.buffers, it might be useful to auto-expand by automatically creating buffers that do not yet exist:

  // res.buffers.debug is automatically created if it doesn't exist
  res.buffers.debug.append("Some debug output");

The nice thing here would be that for programmatic access we didn't even have to push/pop the buffer in question.

=== What it would mean for res.debug()

res.debug() could then be implemented as a method that writes to a buffer called "debug" (or "helma_debug"). Applications could simply provide their own version of res.debug(), and it would be easy to render skins to the response buffer, in addition to using res.write().

=== Other uses ===

Another area where this feature might prove useful is handling of javascript resources or style sheet resources included in a page. Sometimes individual modules of a web application need to add a script or style resource to an HTML page. Therefore, creating the <code>script</code> or <code><link></code> tags by a central function or macro may be impractical. By allowing modules to render these tags to a separate buffer and including that buffer in the <code><head></code> element of the final page this problem could be solved in a simple and elegant way.