Skip to main content

[jsr362-experts:] Re: Some general thoughts on Ajax, Portlets and JSF

  • From: Martin Scott Nicklous < >
  • To:
  • Subject: [jsr362-experts:] Re: Some general thoughts on Ajax, Portlets and JSF
  • Date: Wed, 13 Nov 2013 09:59:51 +0100

Hi Neil,

Thanks for your comments, I really appreciate your insight.

And I'm sorry it took so long for me to get back to you - I got caught up
in a project and was unable to extricate myself until yesterday.

The PartialActionURL from Faces is interesting - thanks for the link to the
JSF Javadoc for that. I understand that for a portlet, the PartialActionURL
results in a resource request that causes the complete JSF lifecycle to be
executed and the resulting markup returned to the client. Now I understand
the background of your suggestion much better.

Applying that idea to a non-Faces portlet, it could work as follows:

1) The portlet would render a PartialActionURL into the markup when it
wishes to perform an Action through use of Ajax.
2) When activated, the JavaScript portion of the portlet would use Ajax to
send a request containing the PartialActionURL to the portal.
3) The portal would drive the portal action phase, allowing parameters to
be updated and events to be fired.
4) The results would be rendered through serveResource and returned to the
client
5) The JavaScript portion of the portlet would update the portlet UI
appropriately.
5) A JavaScript event would be fired informing other portlets (and
JavaScript entities) on the page that an update has occurred.
==> need more detail:
==> a) who would fire the event? I don't think it would be good to rely on
the JavaScript portlet programmer to fire an event that other portlets rely
upon.
==> b) What information would the event contain? The IDs of the affected
portlets? The updated page state (parameters, portlet modes, windows
states)?

Did I capture the idea correctly?

Actually, there are similarities to what I suggested in proposal #2,
although there are differences in form. So we might not be that far apart.
An outline of proposal #2 (for lack of a better name) would be:

1) The portlet renders a regular ActionURL into the markup.
2) The JavaScript portion of the portlet registers an "onParameterUpdate"
handler with the "portlet.js" implementation in order to receive updates
when the portlet state changes.
3) When activated, the JavaScript portion of the portlet uses the "action"
method of "portlet.js" to communicate the request containing the action URL
to the portal.
4) The "portlet.js" code transmits the Ajax request to the portal, noting
that an Ajax action request is to be handled.
5) The portal drives the portal action phase, allowing parameters to be
updated and events to be fired.
6) The portal returns the new navigational state for the page to the
"portlet.js" code on the client.
7) The "portlet.js" code decodes the navigational state and calls the
"onParameterUpdate" handler of each portlet whose state has changed.
8) The affected portlets each retrieve their markup through resource
requests as required and update their UI.

One big difference is that the PartialActionURL idea defines a special URL
that marks an Ajax action request. In proposal #2, a regular ActionURL is
used, but the "portlet.js" code on the client informs the portal (in an
implementation-specific manner) that an Ajax request is being handled.

Another difference is that proposal #2 defines a "portlet.js" JavaScript
module that handles the action request, decodes the resulting new
navigational state, and calls handlers for the JavaScript code representing
individual portlets. And I have to say that I am still pretty much
convinced that we will need some form of dedicated handler code on the
client in order to make sure that updates on the client side get performed
properly without relying on Ajax portlet developers to "do the right thing"
by sending events.

Note also that proposal #2 can easily be extended to handle portlet mode
and window state as well as the portlet parameters.

That is about all that comes to mind right now, so I'll close and move on
to updating the minutes for last week.

best regards,
Scott

Hi Scott,

Thanks for considering the PartialActionURL idea and for the detailed
reply. I'll attempt to provide answers to your questions inline ...

On Oct 31, 2013, at 4:58 AM, Martin Scott Nicklous <
>
 wrote:

      Hi Neil,

      I understand your idea to provide a PartialActionURL that would only
      render
      the single portlet, but I think there are additional things that need
      to be
      worked out.

BTW, forgot to mention that the name PartialActionURL originates from the
JSF API:
https://javaserverfaces.java.net/nonav/docs/2.2/javadocs/javax/faces/context/ExternalContext.html#encodePartialActionURL
(java.lang.String)


      1) It might be that the active portlet (the one initiating the
      action)
      would only need a partial update, which would make it more
      appropriate for
      that portlet to obtain its data from serve resource rather than from
      the
      render method. Naturally it would be possible to handle that as a
      special
      case in during rendering, but that would potentially introduce a
      certain
      degree of ugliness into the portlet Java code.

With JSF, this is always the case, not just a special case. There is a
condition by which a JSF navigation rule causes the outermost
<div>...</div> of the portlet to get swapped out of the DOM entirely, but
this is still considered to be "partial" (in a sense) by JSF. I hope the
code isn't too ugly, but here is an example:
https://github.com/liferay/liferay-faces/blob/master/bridge-impl/src/main/java/com/liferay/faces/bridge/BridgePhaseResourceImpl.java#L81


      2) We need well-defined events and reliable actors on the client side
      to
      fire and handle the update events. Many (pretty modern) browsers
      support a
      DOMObserver that watches for updates to a specified branch in the DOM
      tree,
      which one could use to determine that something has changed. But then
      what
      would you do when you find out something has changed? I don't think
      you
      would want each portlet to just blindly do a server round trip to
      discover
      if there is new data available,

Agreed -- a blind round trip is not good. I didn't intend to imply that as
a requirement. Browsers are limited to two simultaneous requests per domain
(for all requests, including images, etc, not just ajax). So we would have
to take things like that into consideration.

      I think we need a mechanism that
      specifically identifies the portlets that need to update themselves.
      I
      don't think it would be good to rely on (or place the burden on) the
      portlet programmers to insert script to fire the appropriate event.

I discussed it with the JS engineers at Liferay and they are OK with a
client-side eventing API defined by portlet.js. One of the JS engineers
said that a basic pub/sub impl can be written in less than 50 lines of JS).
Usage of DOM Level 2 events should be fine as well since (like you said)
they are supported by modern browsers.
http://en.wikipedia.org/wiki/DOM_events


      3) It has to work both ways: A JSF portlet that changes public render
      parameters to fires events needs to be able to cause other non-JSF
      portlets
      to (partially) update themselves and active non-JSF portlets that use
      portlet coordination needs to be able to cause a JSF portlet to
      update
      itself, either partially or entirely.

      Would it be possible for the JSF bridge to inject JavaScript into the
      portlet markup to deal with the portlet-specific updates &
      communication on
      the client side?

Yes indeed.


      Last night a scenario occurred to me that I would like to understand
      better. It's a general JSF scenario, independent of portlets. Can you
      handle the following with JSF?

      Scenario: You have a JSF page that embeds a non-JSF javaScript
      component
      (call it a widget) on the page. This might be due to legacy reasons
      or
      because the widget was developed by a different company or team. Both
      the
      widget and the JSF portion of the page carry out Ajax communication
      with
      the server, and they both have a form that can be submitted. You want
      the
      page as a whole to work in an Ajax manner.

      a) When the widget form is submitted, it might change something on
      the
      server that would necessitate at least a partial update to the JSF
      portion
      of the page. Is there a way for a general JavaScript routine to
      inform JSF
      that it should update its markup? ... I haven't found any such
      mechanism in
      my reading, but I may have overlooked something.

Such widgets are typically wrapped as JSF components (either JSF 2
Composite Components or old-style Java-based UIComponent + Renderer) and
therefore fully participate in the JSF lifecycle and rendering to the
response. While the widget can of course acquire data from any URL, it
would typically do so from a portlet ResourceURL. If it needed to trigger a
partial update of the JSF rendered markup, then it would invoke a portlet
ResourceURL that triggers the JSF lifecycle and a corresponding JSF
partial-response. The jsf.js library would parse the partial-response and
handle the DOM update.


      b) When the JSF form is submitted, it might change something that
      would
      necessitate a partial update of the widget. Is there a way for JSF to
      inform the widget that it needs to update its markup? This way around
      is
      easier for me to imagine a solution - you might be able to use the
      JSF
      onevent callbacks, or you might be able create a solution by
      intercepting
      the jsf.ajax.request() method.

This is a very normal situation that in my experience is typically handled
in one of two ways, either:
1) The JSF lifecycle + render returns a partial-response with an update of
the DOM such that the entire widget is replaced
    -or-
2) The JSF component that represents the widget in the JSF component tree
on the server renders a <script>...</script> that causes the client-side
representation of the widget to update itself in some way.

Best Regards,

Neil


      regards,
      Scott

      Neil Griffin 
< >
 wrote on 30.10.2013
      16:39:32:

            From: Neil Griffin 
< >
            To: 
,
            Date: 30.10.13 16:39
            Subject: [jsr362-experts:] Re: Some general thoughts on Ajax,
            Portlets
      and JSF

            Hi Scott,

            (I was just about to send this message on the other thread you
            posted about the minutes, but I think the AjaxActionURL idea
            you
            mention the email you sent below might fit well with this)

            In the minutes, you wrote:
            Scott's comment, not discussed directly in call: If I
            understood the
            gist of the above
            arguments correctly, the suggestion would be that we introduce
            capability that would
            allow stateful Ajax updates without running through the portlet
            action-event-render
            lifecycle.)

            I would like to offer an idea that would be compatible with
            most
            JavaScript frameworks and also provide the ability to run
            through
            the action-event-render lifecycle....

            But first, here is (what I understand to be) the typical
            JavaScript
            framework use-case:

            Frameworks like JSF provide the jsf.js library and
            corresponding
            f:ajax tag. Component suites like PrimeFaces bypass this
            mechanism
            by providing the primefaces.js library and corresponding p:ajax
            tag.
            So in both cases, either jsf.js or primefaces.js expect to be
            in
            full control of issuing the XmlHttpRequest. The way JSF portlet
            bridges integrate with this is by simply providing a
            javax.portlet.ResourceURL that the underlying JavaScript
            library
            uses for the Ajax postback.

            Now, along that same line of thought, jQuery developers will
            want to
            perform Ajax via jQuery.ajax()
            http://api.jquery.com/jQuery.ajax/

            ... YUI3 developers will want to perform Ajax via Y.io()
            http://yuilibrary.com/yui/docs/io/

            ... and DOJO developers will want to perform Ajax via
            dojo/request/xhr:
            http://dojotoolkit.org/reference-guide/1.9/dojo/request/
            xhr.html#dojo-request-xhr

            My idea would be to introduce a new type of portlet URL called
            javax.portlet.PartialActionURL that would cause the portlet
            container to do the following:

            1. Execute the ACTION_PHASE for the portlet targeted by the
      PartialActionURL
            2. Execute the EVENT_PHASE
            3. Rather than return HTTP Status Code 301 (Redirect to a
            RenderURL), execute the RENDER_PHASE (BUT ONLY FOR THE PORTLET
            TARGETED BY THE PartialActionURL). The portlet container would
            not
            return a complete HTML document with all the portlets, but
            rather
            only the the fragment of markup for the targeted portlet.
            4. During the RENDER_PHASE, allow the portlet developer to
            render a
            <script>...</script> that would participate in client side
            event
            notifications. That way, interested portlets could listen to
            such
            events and subsequently invoke an existing
            javax.portlet.ResourceURL
            in order to update themselves. The developer would be free to
            use
            any type of client side eventing mechanism, but we could
            provide a
            default mechanism via portlet.js.

            I think that this approach could be integrated into JSF portlet
            bridges and also be leveraged by other JavaScript frameworks.
            It
            would also not require any changes to the portlet programming
            model,
            other than a new method called
            MimeResponse.createPartialActionURL()

            Neil





[jsr362-experts:] Re: Some general thoughts on Ajax, Portlets and JSF

Neil Griffin 11/01/2013

[jsr362-experts:] Re: Some general thoughts on Ajax, Portlets and JSF

Martin Scott Nicklous 11/13/2013
 
 
Close
loading
Please Confirm
Close