Projects‎ > ‎

XForms - Improved Portlet Support

NOTE: This page describes an Orbeon Forms project, not a feature which is currently part of Orbeon Forms.


Orbeon Forms features portlet support. Improvements should provide:
  • Portlet 2 API support out of the box [DONE]
  • support for separate deployment within portlets [DONE]
  • caching of render portlet output [added here 2010-10-25]
The idea is that this should work out of the box with a recent version of Liferay (5.3 / 6).

XForms-aware caching of portlet output


When subsequent portlet render requests reach a portlet:
  • if the page was produced via a GET (i.e. NOTE the result of an action URL), the page content is retrieved again
    • this is wrong because the user does not expect the equivalent of a reload in this case
    • also wrong because if the page contained XForms and the user interacted with it, the updates will be lost
  • if the pager was produced via a POST (i.e. the result of an action URL), the page content is retrieved again with render parameters associated with the previous POST
    • doing a GET here is definitely wrong
    • same result for XForms content, which will be lost
Subsequent renders occur when:
  • you maximize or minimize the portlet
  • you interact with other, non-Ajax portlets on the page, as they request new renders/actions

General goal

Upon receiving a render request, a decision must be made
  • execute the entire page again as if it was newly loaded
    • based on orbeon.path and render parameters
  • OR produce output reflecting the current state of the page after XForms Ajax requests
    • based on cached render output
    • plus "all events" Ajax request sent to server

Random thoughts

  • if a user takes a portlet page URL and opens in a new tab, the portlet will get a new render request for the same parameters
    • Q: how to handle the duplication of the flow?
    • Q: is it possible to make a distinction between a portlet's new render request vs. tab duplication? A: likely not.
    • maybe just a scenario that we don' support
  • it is desirable/necessary to store more than one result per portlet
    • scenario:
      • open FR summary
      • click on form data → opens new browser tab with detail page
      • → both web pages have portlet w/ same id e.g. _orbeonformsportlet_WAR_orbeon_INSTANCE_2o1H_
      • re-render portlet (minimize/maximize) in one tab will prevent other one to handle Ajax update properly
      • ⇒ possibilities
        • store only new ones if we detect opening in new frame
          • issue: hard to detect
          • issue: doesn't handle user copying URL to new tab
        • use cache of last rendered pages
          • issue: could get out of sync with XForms doc cache
        • use something in sync w/ doc cache
          • NOTE: not possible with proxy portlet?
        • => try using PLT.22.2 Validation Cache and etag set to XForms doc UUID
  • Q: what identifies a "render"?
    • orbeon.path
    • orbeon.method
    • issue: upon render, can't add render parameters to portlet, otherwise could add page uuid

First experimental implementation

  • render request
    • if no response in session for path+params, run render + stored response
    • if already response stored in path
      • serve response
      • embed in page server events with all-events mode
        • add new
          <script type="text/javascript">orbeonInitDataPortlet[formid] = {"server-events":[xxx]}</script>
        • client will run this upon init
      • OR: just put flag in JS and have client test on it, e.g.:
        <script type="text/javascript">var portletRender[formid] = true</script>
        • ⇒ extract form id from content, or just use namespace+xforms-form?
        • client tests for portletRender -> modify JS
    • don't remove saved render from session
  • action request
    • always run the action
    • use  POST as pseudo-method for stored response

More thoughts

  • obvious optimization: if all-events asked to server and seq number is 0 (or 1), don't bother computing diff!
  • not sure can make use of uuid/sequence number for anything here
  • Could use full updates rooted at the top of the form? If the HTML for the page was kept around, then the XForms engine could generate new HTML. But this raises other questions, in particular how to deal properly with JavaScript stuff. What about listeners, etc.?
  • The output for such the Ajax diff diff could be cached, in case a user keeps interacting with other portlets, so that the diffs are not computed at every render.

Portlet 2 support [DONE]

Status: As of 2010-09, Portlet 2 mode is implemented and the older Portlet 1 mode is removed.

How things work

All requests including for resources and /xforms-server can go through the portlet instead of hitting a separate Orbeon servlet.
  • benefits
    • no need for configuring a servlet in addition to portlet
    • session handling is simpler
  • drawbacks
    • URLs are encoded and longer
    • different portlets get different URLs for the same resources (can portlet caching options fix this?)
    • aggressive client-side caching is harder
Q: Should we have an optional configuration where resources are still served by the servlet?

Changes to Orbeon Forms:
  • fix in xforms.js (and possibly Java) for finding /xforms-server base URL (current algo/regexp won't work)
  • update portlet.xml to use OrbeonPortlet2Delegate by default

Separate deployment within portlets [DONE]

Status: As of 2010-09, this is now implemented, see XForms - Separate Deployment with Portlets.

Form Runner Liferay proxy portlet [DONE]

Status: As of 2011-01-07, this is now implemented, see: Form Runner Liferay Proxy Portlet Guide.