3. About Me
“My name is Darth Vader. I
am an extraterrestrial from
the planet Vulcan”
4. Why This Session?
• XPages often doesn’t work “as expected”
 Custom Control -> XPage -> Browser
 Browser -> Server -> Browser
 SSJS / CSJS
 State management
 Partial Refresh
• Lots of StackOverflow questions
 Which wouldn’t be referenced here unless many developers hit
the same issues!
5. Agenda
• Buzz-Quote Bingo!
• Twin Pines Mall / Lone Pine Mall
• Marty’s Family Photo
• Marty McFly and the Tannens
• Power of Love
• Alternate 1985
• Indians!
• It’s Erased!
9. 1. Retrieve/Create Code in documentId
• ALWAYS use ${…} when calculating properties like
documentId
• Otherwise calculated FOUR times on page load
 If attached to a Panel, TWICE AFTER beforePageLoad
 If attached to XPage, TWICE BEFORE beforePageLoad
• Can’t use scoped variables set in beforePageLoad!
 Always TWICE DURING render response
10. 1a. Timing of Initialisations
• viewScoped variables can’t be set before PAGE LOAD
 Controller frameworks put variable in requestScope and move to
viewScope
• data, dataContexts etc
 attached to XPage / Custom Control - initialised alongside
component
 Attached to Panel – initialised during PAGE LOAD
11. 2. ignoreRequestParams
• ALWAYS use ignoreRequestParams where appropriate
 If no params, computed settings respected
 If params passed, computed settings overwritten
12. 3. Submit Button Type
• DON’T use save=“true” (“Submit” button type)
 Use script, not simple actions
• Greater control, less risk
• You save only what should be saved
• Preparing you for Java / beans / beyond
• Form with single rich text field can cause problems even with
script
15. 4. Keep Pages In Memory
• XPages is stateful
• Number of component trees restricted for performance
• Dumped xsp.session.timeout minutes after browser closed
 Browser doesn’t tell server session is no longer used!
17. 6. Explanation of “nostate”
• DataView and nostate
 Toggle expand/collapse is fine
 Navigating to specific pages is fine
 Next / Previous is relative to defaults
 Toggle detail is relative to defaults
• Unless detailsOnClient=“true”
• Details pushed to browser along with rest of content
• “Toggle” is client-side show/hide
20. 7. Repeat Controls and Component Tree
• Only one set of components in component tree
• repeatControls=“true” changes behaviour
 x many sets of components
 Hard-wired to specific entries at page load
 Pagers have no effect because of hard-wiring
 Allows “loaded” computations within the repeat, e.g. id’s
• Cannot compute repeatControls=“true” within compositeData
21. 8. Dynamic Content Control
• Only components from current facet exist in component tree
• Component tree dynamically updated
• Better than showing / hiding via rendered property
22. 9. Custom Controls and Scope
• Custom control is inserted into component tree
• Variable names outside custom control available
• As long as same variable used, no need to pass
• Same rules as for any component
 Is variable available by navigating upwards in tree?
 Cannot retrieve variables from another branch
• E.g. different repeat entry, repeat entry from outside repeat
24. ControllingViewHandler
• Creates component tree for specific XPage
• Runs before beforePageLoad event
• super.createView() loads component tree
• Also creates viewScope
 Not available before call to super.createView()
 Load variables to requestScope before super.createView()
 Move to viewScope after super.createView()
30. 10. Understanding Partial Refresh
• 1. RESTORE VIEW
 Get component tree again
• 2. APPLY REQUEST VALUES
 Pass String values from browser to executed component tree
• 3. PROCESS VALIDATIONS
 Run validators AND converters for executed component tree
31. 10. Understanding Partial Refresh
• 4. UPDATE MODEL VALUES
 Convert string values and update executed component tree
• 5. INVOKE APPLICATION
 Run application logic (SSJS / Java)
• 6. RENDER RESPONSE
 Update HTML for executed component tree and post refresh area
32. 11. Conditionally Hidden Save Button
• Set rendered property on button
 For best practice, use view.isRenderingPhase()
 Ensure set to true for other phases or code will not run
• Add partial refresh where appropriate
 Ensure refresh area correct or button will not show
 Ensure disableValidators=“true” or button will not hide again if
invalid
33. 12. Reasons Code May Not Work!
• CSJS returning false – check Firebug for POST event
• Conversion error – 1,2,3,6
• Validation error – 1,2,3,6
• Exec id not including components being used by application
logic
• Exec id not including component triggering application logic
• Event handler not rendered in phase 4
• Refresh area not including errors control
34. 13. Troubleshooting
• Use PhaseListener
• java.util.logging.ConsoleHandler.level manages console
logging of server validation errors, since 8.5.3
 In workspace.configrcpinstall.properties
• ALWAYS including errors control in refresh area
• Be conscious of rendered property
35. BONUS 1: Data View
• dataCache=“id” setting available on View datasource
• Better for performance, only caches id, not full ViewEntry
(wrapped)
• “var” not available during Apply Request Values
 Compute value only in Render Response
36. BONUS 2 - Dialog
• To refresh area,
getComponent(“dialog1”).hide(“myRefreshArea”)
 POST
• Run SSJS
• view.postScript - XSP.closeDialog
 GET
• Refresh myRefreshArea
42. 15. “Resp is null”
• Understand page load and dynamically
 “resp is null” – options for picker are not available
 Picker is client-side, but values are passed to renderer server-
side
43. 16. SSJS in CSJS
• SSJS in CSJS
 Computed server-side as part of script renderer
 Only re-computed by partial refresh
• To access component values
 Use dojo.byId or variants to access client-side element
 Trigger partial refresh to update SSJS embedded into CSJS
46. 17. Domino Objects in Scopes
• Domino objects can’t be stored in scopes.
 DateTimes are the most common culprit
 Use .toJavaDate() to store Java Date
• Similar issues with SSJS functions stored in variables
47. 18. Impact of Persistence Setting
• For Domino objects in scopes, depending on persistence
setting
 Keep pages in memory – value just lost
 Keep pages on disk – error thrown to server, redirect to error
page (fails to display)
 Keep current page in memory – value just lost, error 500 on
navigating
49. Summary
• Understand scope and custom controls
• Understand partial refresh is more than just “partial
refresh”
• Understand SSJS is computed and injected into CSJS
• Use Firebug or comparable tool
• Don’t store Domino objects in scopes
• Understand impact of serialization
50. Thank You!
Paul Withers
Intec Systems Ltd
IBM Champion
OpenNTF Board Member
@paulswithers
pwithers@intec.co.uk
http://www.intec.co.uk/blog