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