dev@jsf-extensions.java.net

Re: [JSF-EXT] Avatar Status (Jacob, Dan and Craig, please read)

From: Ed Burns <ed.burns_at_sun.com>
Date: Tue, 20 Jun 2006 08:07:49 -0700

>>>>> On Mon, 19 Jun 2006 12:01:01 -0700, Adam Winer <adam.winer_at_oracle.com> said:

EB> The following headers are currenty supported in the AjaxLifecycle
EB>
EB> com.sun.faces.Async
EB>
EB> If this header is present, the AjaxLifecycle treats this
EB> request as an AJAX request.

AW> Could we get an extra layer of packaging under "com.sun.faces"?

Well, this is just a header name, not a package name. The package
happens to be com.sun.faces.extensions.avatar. I'd like to keep the
header names as short as possible, while preserving disambiguation.
However, I could live with com.sun.faces.avatar, but I don't really see
the need. I'll leave it as com.sun.faces unless someone strongly
opposes.

AW> Also, "async" vs. "sync" isn't a relevant distinction here -
AW> a client is free to issue a synchronous XMLHttpRequest request
AW> (in some cases, a good idea). The distinction should be "full page"
AW> vs. not (aka "PartialRequest").

Ok, that's good. I'll make it com.sun.faces.Partial instead of
com.sun.faces.Async.

EB> com.sun.faces.Subtrees
EB>
EB> This is a comma separated list of clientIds against which the
EB> lifecycle should be run. Each lifecycle phase is run on each
EB> clientId using invokeOnComponent() to ensure proper context.

AW> If absent, the entire tree should be executed. Is that how it works?
AW> I'd prefer the name "TargetIds", but "Subtrees" is OK.

I actually prefer Subtrees because it is more descriptive.

EB> com.sun.faces.lifecycle.RunThru

DL> Can the RunThru header indicate validation without update? I'm wondering
DL> what will happen to queued, value change events? I'm thinking of the
DL> scenario where I want to validate a text field value, but not update it
DL> until the user clicks an OK button, for example.

Yes, it can.

EB> This header gives the name of the request processing lifecycle
EB> phase through which the lifecycle should be run. For example, the
EB> replacement for Jacob's javax.faces.Update parameter is to define
EB> the RunThru header with the value of UPDATE_MODEL_VALUES. The
EB> response generated when running a partial lifecycle will be
EB> described below.

AW> -0.5. Why is this set on the client?

Basically, to support popular JavaScript widgets via jMaki. In this
case, the widget expects to get back a mere "value" rather than, "a
bunch of markup that renders a value".

If we go through the render phase, we end up with the extra markup, and
we have to somehow pick apart the rendered markup to extract the value
and hand it to the widget for display. Also, it is vital that
validation and conversion work on this case, so, the AjaxLifecycle will
send back a any validation and conversion errors along with the value.

To achieve this, I decided to allow the client to tell the server,
"don't render the component, just give me its converted value (along
with any validation/conversion messages)".

Adam, first, do you agree with the necessity to have JSF support popular
JavaScript widgets via jMaki?

Second, if you agree with that requirement, now that you have some
additional perspective on the challenges involved in providing this
support, do you still oppose my implementation choice?

AW> This should be determined by the renderer, or component, or event
AW> listener IMO. More generally, it's of critical importance that
AW> everything should be extensible programatically on the client; for
AW> instance, you have to be able to indicate on the server that an
AW> additional target ID needs to be processed. This lets you send
AW> across simple requests that only a button was pressed, but on the
AW> server decide that additional regions of the page need to be
AW> processed.

I agree we must support this story. However, I do not agree that this
story is appropriate for the com.sun.faces.lifecycle.RunThru header. I
intend the RunThru header to be for components that only want to send an
update (or validation, or invoke application, etc) to one or more
components in the view. In that case, the server does not have a right
to add additional values.

If the server is making decisions about processing additional subtrees
than what the user requested, then the full lifecycle is required, and
the RunThru header will not be used.

AW> Also, we have to separate two concepts:

AW> 1. Components that need to be processed (ARV through Invoke
AW> Application, but *not* Render Response)
AW> 2. Components that need to be rendered (Render Response only)

AW> Inclusion in #1 does not require inclusion in #2. For
AW> example, if I have a button click that re-renders a table
AW> via Avatar, the button gets processed (but not re-rendered),
AW> and the table gets re-rendered (but not processed). This isn't
AW> just an optimization - re-rendering components unnecessarily
AW> has a major negative accessibility impact.

Yes, I agree. I see that my current implementation does not handle this
essential case. Let's fix that.

Does the button know that its job is to cause the table to be
re-rendered? Let's assume first that it does for discussion. The
browser would send a request with the following headers and post data

com.sun.faces.Partial: true
com.sun.faces.Update: form:redisplayButton
com.sun.faces.Render: form:table

form:redisplayButton=form:redisplayButton&javax.faces.ViewState=_id1:_id2

The server would run the whole ApplyRequestValues thru InvokeApplication
on form:redisplayButton, and then would render just form:table.

Now, let's say we want the server to be the one to make the decision
that the table needs to be re-rendered when that particular button is
pressed. The browser would send a request with the following headers
and post data

com.sun.faces.Partial: true
com.sun.faces.Update: form:redisplayButton

form:redisplayButton=form:redisplayButton&javax.faces.ViewState=_id1:_id2

We leave out the RenderSubtrees header and let the server decide what
needs to be re-rendered. This requires some server side smarts I have
not yet implemented.

So, Adam, my question to you is: do we need to enable the client to tell
the server what should be processed, vs what should be rendered. I
think we do.

>>>>> On Mon, 19 Jun 2006 15:07:17 -0400, jacob_at_hookom.net said:

JH> I don't think we can have a single spot for specifying the
JH> collection ids to process-- that's why I had Update vs. Encode, you
JH> don't want to update a chunk of the page that you want to re-render
JH> in all cases.

Adam's comment supports the inclusion of the RenderSubtrees header (this
is essentially Jacob's Update and Encode headers).

EB> I have the following header also in-mind, but not yet implemented:

EB> com.sun.faces.lifecycle.<LIFECYCLE_PHASE>

EB> If defined, this is a comma separated list of client ids to be
EB> used for that specific lifecycle phase. This value overrides the
EB> value of com.sun.faces.Subtrees for that specific phase.

AW> -1. I'd like a use case, especially before letting this be
AW> driven by the client.

Ok, I can leave this un-implemented

EB> 3.
EB>
EB> New XML application for AJAX responses from avatar server.
EB>
EB> If the request has the com.sun.faces.Async and
EB> com.sun.faces.Subtrees headers, with valid values, but no
EB> com.sun.faces.lifecycle.RunThru header, request will look
EB> something like this:

[...]

EB> And the response like this:

[...]

EB> <async-response>

AW> <partial-response> would be better, as noted above.

Ok, that's fine with me.

EB> <!-- additional cells omitted -->
EB> </tr><input type="hidden" name="form:scroller_action"/>
EB> <input type="hidden" name="form:scroller_curPage"/></table>
EB>
EB> <script type='text/javascript'>
EB> document.forms[0].submit = function() {};
EB> var a = $('form:subview2').getElementsByTagName('a');
EB> $A(a).each(function(e) {
EB> new Faces.Command(e, 'mousedown', { subtrees: 'form:table,form:subview2' });
EB> });
EB> </script>
EB> </div>]]></render>
EB> <state>
EB> <![CDATA[j_id3:j_id4]]>
EB> </state>
EB> </async-response>

DL> Avatar request? In some cases (e.g., the progress bar component), we
DL> will need to continuously poll for data without any Javascript event. I
DL> was thinking that we could use a Dojo subscribe/publish event here, but
DL> I'm wondering if the API can also generate the request immediately? For
DL> example:

DL> new Faces.Command(e, null, { subtrees: 'form:table,form:subview2' });

How about using setTimeout() to kick off the Faces.Command requests
periodically?

EB> To support simple updating (with validation and conversion properly
EB> handled) of one or more values in the component tree, use the
EB> RunThru header with a value of UPDATE_MODEL_VALUES. A request with
EB> this header looks like this:

AW> I don't much like this; it requires the client has knowledge of what's
AW> meant by "setting the value" of a particular component on a client,
AW> which requires deep markup knowledge once you get past basic input
AW> components.

I understand your reservations, but suspect you did not have the "smart
JavaScript Widgets" story in mind when you formed your opinion of it. I
ask you to reconsider in light of that story.

DL> Will this solution automatically update component state on the client?

Yes, it does.

DL> If so:

DL> 1. Does this work with client-side state saving, where the encoded state
DL> saving string is present in the page?

Yes, it does.

DL> 2. Can we control when it is necessary to return client state (e.g.,
DL> when components are updated)?

That is not implemented, but it's a good idea. I'll put that on the
idea wiki. [1]

DL> 3. Any chance responses could be handled out of order and newer state is
DL> inadvertently overridden?

I assume total ordering of requests and responses.


AW> Additional feature that would be very useful: return any
AW> FacesMessages in XML blocks, then call a user-defined callback
AW> with an array of those messages.

I already have the <message> part. I haven't implemented the client
side. I prefer to leave it up to the client to note the presence of
messages and decide what to do with them.

EB> Next Steps - Concrete Tasks
EB>
EB> Currently, the result-set.jsp example, in the run-time-test
EB> module, is the only one that works. My next step is to take
EB> Jacob's JavaOne demo and move it into our repo and make it work
EB> with the avatar impl. This will require support for Jacob's
EB> javax.faces.Event header, which I don't think will be too hard to
EB> add, but we'll see.
EB>
EB> After that, I want to get the ajaxZones implementation updated to
EB> use the new framework, and remove as much of my old procedural
EB> JavaScript code from com_sun_faces_ajax.js as possible. In concert
EB> with this task, I will make the jsf-ajax-carstore example work
EB> again. This will prove out the fully functional ajaxZone concept.

AW> Why do we need any AJAX zones? -1 on any solution that requires
AW> explicitly marking zones. It should be sufficient to have an "id"
AW> set on any JSF component.

I'm not ready to give up on zones yet. I think there are cases, such as
ajaxifying the cardemo app, for example, that do require zones. Of
course, if it shows up that we don't need them, I will take them out.

[...]

EB> Another idea is to make the rendering of the response pluggable so
EB> that one could send the response back in JSON instead of hard
EB> coded XML. Perhaps Dan Labreque can help with this.

DL> The main thing I'm looking for is to bypass the mechanism which replaces
DL> HTML. I expect that our components will need to return both XML and
DL> JSON, but we will not always replace newly rendered HTML. I just need a
DL> simple hook to process the data from the response myself.

DL> If the response is wrapped in XML, my Javascript function could parse
DL> out the data, but it's extra processing. With the previous Avatar
DL> source, the custom UIViewRoot wrapped the output, of each
DL> avatarZoneRenderer, in XML. However, this forced my component renderers
DL> to wrap JSON in the same XML format used by the ajaxZoneRenderer.

DL> I'm not really looking for a pluggable rendering solution here, I just
DL> don't want my response to be wrapped in XML. If I want to return XML, I
DL> can easily set the response myself in my own renderer. However, I'm just
DL> looking to set a simple flag indicating that the custom UIViewRoot/life
DL> cycle should not wrap the response in XML.

Well, that's easy enough to do. We could have another header,
com.sun.faces.ResponseContentType. If absent, it's XML. If present, it
sets the content type blindly and lets the renderer do the thing.

DL> That said, I'm willing to help if I can. For example, I can take your
DL> latest source and apply it to our components. Although, I'm not certain
DL> my last example was useful to you? Want to meet tomorrow afternoon and
DL> discuss possible solutions?

I'd like to get Adam's issues straightened out first before we talk. Is
that ok?

Ed

[1] http://wiki.java.net/bin/view/Projects/AvatarIdeaWiki

-- 
| ed.burns_at_sun.com  | {home: 407 869 9587, office: 408 884 9519 OR x31640}
| homepage:         | http://purl.oclc.org/NET/edburns/
| aim: edburns0sunw | iim: ed.burns_at_sun.com