You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Andreas Andreou <an...@di.uoa.gr> on 2006/08/04 19:59:17 UTC

ResponseBuilder thoughts

So, ResponseBuilder is 'responsible for managing all content
output that is sent to the client' and 'hands out IMarkupWriter
instances to *render* components'.

Additionally, it can also output content on its own, for instance
to writeExternalScript, writeImageInitializations, e.t.c.
In those cases, all ResponseBuilder implementations can
either ignore those requests
or use their own IMarkupWriter
My problem is that in the second case, that IMarkupWriter may not
be the correct one. This can happen when a component that
surrounds Body (which actually calls writeExternalScript, 
writeImageInitializations, e.t.c.)
renders its body to either a nested markup writer (perhaps to implement 
caching)
, or to a completely new markup writer ( perhaps to render to file or 
email )

So, I simply feel that some ResponseBuilder implementations may have
a use for an additional IMarkupWriter parameter in the
writeExternalScript, writeImageInitializations, e.t.c. methods.

And BTW, is there a reason why the IMarkupWriter parameter is needed in
ResponseBuilder.render(IMarkupWriter writer, IRender render, 
IRequestCycle cycle) ???

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


Re: ResponseBuilder thoughts

Posted by Jesse Kuhnert <jk...@gmail.com>.
Hmm....I guess I'm still not sure of the specific use case where this is
needed, but I do remember thinking the javascript writing portions of the
interface still felt dirty for some reason.

Go ahead and commit, if I see something I don't like I'll pipe up and post
another message for discussion. (Sorry for questioning you, just want to
make sure we're adding things in the most careful way possible. Ie I've
found however long something took to do in tacos, it's always taken at least
2/3x longer to add it into Tapestry, but only because a lot more careful
thought has to be put into it. )

On 8/5/06, andyhot@di.uoa.gr <an...@di.uoa.gr> wrote:
>
> From Jesse Kuhnert <jk...@gmail.com>:
>
> > To answer the question of why "not" allow people to pass IMarkupWriter's
> in
> > with certain methods and not others is because I believe I have properly
> > handled all scenerios for this logic already.
>
> Considering:
> <html jwcid="@Shell2 or even @Cache">
> <body jwcid="@Body">...</body>
> </html>
>
> Shell2 or Cache wants to render all its body (which is @Body)
> in a buffer before appending it to the output - i believe this
> to be a reasonable requirement.
> So, they grab a nested writer, and call renderBody on it. But
> then DefaultResponseBuilder steps in and says: OK, write all
> to the nested writer, but i want JS + image initializations
> written to the initial writer (the one that produced the
> nested one), so .... ooops
>
> Is there a way to handle such a scenario?
> Well, there might be a way but i'm sure we generally should
> avoid such tricks + i'm sure you didn't have this in mind.
> -> Create another implementation of IMarkupWriter that monitors
> its nested child until it (the child) gets closed. While it's
> open, the parent writer forwards all its calls to its child.
> BTW, i just thought of this...
> So, we're now left to having DefaultResponseBuilder handing
> over our writer whenever a page contains our Shell or Cache
> component, or always... it is doable, but is it cleaner?
> Well, i don't think so - it's a workaround... Components
> shouldn't need to worry about their contents.
>
> Regarding ResponseBuilder.render, i meant to show that if it
> was missing the writer parameter, nested writers would also
> fail there.
>
> And BTW, PageRenderSupport isn't really PageRenderSupport...
> It is BodyRenderSupport. It would need to support methods
> related to <HEAD> to 100% justify its name.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Jesse Kuhnert
Tacos/Tapestry, team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind.

Re: ResponseBuilder thoughts

Posted by an...@di.uoa.gr.
>From Jesse Kuhnert <jk...@gmail.com>:

> To answer the question of why "not" allow people to pass IMarkupWriter's in
> with certain methods and not others is because I believe I have properly
> handled all scenerios for this logic already.

Considering:
<html jwcid="@Shell2 or even @Cache">
<body jwcid="@Body">...</body>
</html>

Shell2 or Cache wants to render all its body (which is @Body)
in a buffer before appending it to the output - i believe this
to be a reasonable requirement.
So, they grab a nested writer, and call renderBody on it. But 
then DefaultResponseBuilder steps in and says: OK, write all 
to the nested writer, but i want JS + image initializations
written to the initial writer (the one that produced the 
nested one), so .... ooops

Is there a way to handle such a scenario? 
Well, there might be a way but i'm sure we generally should
avoid such tricks + i'm sure you didn't have this in mind.
-> Create another implementation of IMarkupWriter that monitors
its nested child until it (the child) gets closed. While it's
open, the parent writer forwards all its calls to its child.
BTW, i just thought of this... 
So, we're now left to having DefaultResponseBuilder handing
over our writer whenever a page contains our Shell or Cache 
component, or always... it is doable, but is it cleaner?  
Well, i don't think so - it's a workaround... Components
shouldn't need to worry about their contents.

Regarding ResponseBuilder.render, i meant to show that if it
was missing the writer parameter, nested writers would also 
fail there.

And BTW, PageRenderSupport isn't really PageRenderSupport...
It is BodyRenderSupport. It would need to support methods
related to <HEAD> to 100% justify its name.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


Re: ResponseBuilder thoughts

Posted by Jesse Kuhnert <jk...@gmail.com>.
Sorry it took so long to respond, have a lot of things going on right now.
Before I add my inlined responses I wanted to give an overview of what is
going on. (in my current thinking)

ResponseBuilder is currently a sort of poor mans version of AOP. It allows
me(you) to control exactly what happens before/during/after rendering of a
component. It certainly isn't the only player involved, like the new
ComponentRenderWorker hivemind chain that allows similar functionality to
that previously provided by tacos javassist enhancements. (Only without the
runtime compilation enhancements, and the additional flexibility of being
able to add as many to the chain as you like without having to constantly
duplicate javassist code.)

The overall goal was to introduce a sort of middle man in the chain of
component rendering. It's not exactly the purest/best implementation
possible. Partly because of my inexperience in designing API logic, and
probably partly because of some of the limitations of the existing design.
(do I even need to mention T5 ?)

The additional issue I had to design around was the concept of completely
new OutputStream wrappers that have nothing to do with html markup, as in
JSON responses. I wanted to try and provide familiar interfaces and flow of
render, but also not hack and butcher IMarkupWriter into something it wasn't
in this instance. So, I created a new interface that basically mimics (but
hides, somewhat) the json.org javascript object interface.

The largest nightmare I had trying to do certain portions of Tacos was in
handling JavaScript contributed response content. (Ie PageRenderSupport /
Body ) . These presented some of the trickier/peskier API's which I had been
foaming at the mouth to refactor into a more publicly controllable API since
day one.

To answer the question of why "not" allow people to pass IMarkupWriter's in
with certain methods and not others is because I believe I have properly
handled all scenerios for this logic already.

The RepsonseBuilder.render(IMarkupWriter writer, IRender render,
IRequestCycle cycle) method that you were questioning the existance of does
precisely this. It's the foundation upon which all of this logic works.
Aside from doing certain type checking of the writer passed in to account
for the scenerio where people have created Nested/other writers, it also
gets called by certain key parts of the framework.

If you right click on the method in eclipse and do References - > Project
you will see some familiar classes pop up:

AbstractComponent.renderBody
AbstractPage.renderPage
BaseComponent.renderComponent
Form.rewind

These more or less represent the key inner-api areas in the majority of our
inheritance tree "foundation"al logic.

I could be totally off in my thinking, and very likely made some mistakes
along the way so I'm not trying to be overly pedantic here, only doing my
best to explain some of the thoughts going in in my mind when doing these
things.

Believe me, I'd love nothing better than to have someone be able to say:

@MarkupRender
public void renderComponent()

or

@JsonRender
public void renderComponent()

and be done with it, relying on AOP to guarantee my ResponseBuilder will be
consulted on how to handle these methods without mucking around with
inheritance.

That would make things 10x simpler than what I had to go through to get to
however confusing ResponseBuilder currently is :)

On 8/4/06, Andreas Andreou <an...@di.uoa.gr> wrote:
>
> So, ResponseBuilder is 'responsible for managing all content
> output that is sent to the client' and 'hands out IMarkupWriter
> instances to *render* components'.
>
> Additionally, it can also output content on its own, for instance
> to writeExternalScript, writeImageInitializations, e.t.c.
> In those cases, all ResponseBuilder implementations can
> either ignore those requests
> or use their own IMarkupWriter
> My problem is that in the second case, that IMarkupWriter may not
> be the correct one. This can happen when a component that
> surrounds Body (which actually calls writeExternalScript,
> writeImageInitializations, e.t.c.)
> renders its body to either a nested markup writer (perhaps to implement
> caching)
> , or to a completely new markup writer ( perhaps to render to file or
> email )
>
> So, I simply feel that some ResponseBuilder implementations may have
> a use for an additional IMarkupWriter parameter in the
> writeExternalScript, writeImageInitializations, e.t.c. methods.
>
> And BTW, is there a reason why the IMarkupWriter parameter is needed in
> ResponseBuilder.render(IMarkupWriter writer, IRender render,
> IRequestCycle cycle) ???
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Jesse Kuhnert
Tacos/Tapestry, team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind.