"Marty, You're Just Not Thinking Fourth Dimensionally": Troubleshooting XPages
Paul Withers / 2nd Feb 2016
About Me
“My name is Darth Vader. I am an extraterrestrial from
the planet Vulcan”
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!
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!
BuzzQuote Bingo
• http://hermes.intec.co.uk/bttf
• Enter Name and Email
• Click when you hear
• Shout if you win!
Twin Pines Mall / Lone Pine Mall
Some Questions
• http://stackoverflow.com/questions/32256155/why-does-this-code-write-out-two-documents/32259533#32259533
• http://stackoverflow.com/questions/24400934/xpages-save-cancel-actions-scenario
• http://stackoverflow.com/questions/24407003/xpages-unid-of-documents-why-it-is-changing
• http://stackoverflow.com/questions/21015953/xpages-conflict-is-created-everytime-a-document-is-saved
• http://stackoverflow.com/questions/36013921/trying-to-open-document-in-xpages
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
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
2. ignoreRequestParams
• ALWAYS use ignoreRequestParams where appropriate
If no params, computed settings respected
If params passed, computed settings overwritten
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
Marty’s Family Photo
Some Questions
• http://stackoverflow.com/questions/33259105/xpages-button-unresponsive-after-4-ajax-calls/33260337#33260337
• http://stackoverflow.com/questions/32628012/xpages-losing-a-viewscoped-bean-again/32633453#32633453
• http://stackoverflow.com/questions/32482575/xpages-falling-out-of-server-side-cache/32483154#32483154
• http://stackoverflow.com/questions/33686362/xpages-page-loosing-context-weird-behaviour
• http://stackoverflow.com/questions/32628012/xpages-losing-a-viewscoped-bean-again/32633453#32633453
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!
5. viewState=“nostate”
• viewState=“nostate”
Don’t store a component tree for this page
Best practice for XAgents / REST services
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
Marty and the Tannens
Some Questions
• http://stackoverflow.com/questions/31561306/how-do-i-access-a-repeat-control-from-the-outside-e-g-via-csjs/31575723#31575723
• http://stackoverflow.com/questions/27982313/xprepeat-inside-xedataview/27982614#27982614
• http://stackoverflow.com/questions/34158779/inherit-index-from-repeatcontrol-in-nested-custom-controls/34158954#34158954
• http://stackoverflow.com/questions/34652364/slider-in-repeat-control-and-manipulation-of-text-via-jouery/34653561#34653561
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
8. Dynamic Content Control
• Only components from current facet exist in component tree
• Component tree dynamically updated
• Better than showing / hiding via rendered property
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
Power of Love
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()
ControllingViewHandler
PhaseListener
• Handles XPages lifecycle
• On page load, only RENDER RESPONSE triggered
• Runs for every partial refresh
Ensure optimised
Ensure error handling
• Crucial for identifying why partial refresh is not behaving “as expected”
PhaseListener
Some Questions
• http://stackoverflow.com/questions/20477153/xpages-server-validation-errors-havent-been-displayed-to-the-user
• http://stackoverflow.com/questions/28339422/ssjs-onclick-action-will-not-fire-on-xpage/28340759#28340759
• http://stackoverflow.com/questions/33024777/xpages-how-to-do-partial-refresh-correctly
• http://www.intec.co.uk/view-isrenderingphase-and-buttons/
• http://www.intec.co.uk/fully-understanding-rendered-property-and-components-with-events/
10. Understanding Partial Refresh
• Partial Refresh is SIX Phases
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
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
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
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
13. Troubleshooting
• Use PhaseListener
• java.util.logging.ConsoleHandler.level manages console logging of server validation errors, since 8.5.3
In workspace\.config\rcpinstall.properties
• ALWAYS including errors control in refresh area
• Be conscious of rendered property
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
BONUS 2 - Dialog
• To refresh area, getComponent(“dialog1”).hide(“myRefreshArea”)
POST
• Run SSJS
• view.postScript - XSP.closeDialog
GET
• Refresh myRefreshArea
Alternate 1985
14. What Requires Restart Task HTTP?
• Picked up immediately
Classic design elements
XPages*
Custom Controls*
Java classes*
* Provided not in SCXD - http://www.intec.co.uk/single-copy-xpage-design-some-learning-and-why-its-not-for-me/
14. What Requires Restart Task HTTP?
• Require “res task http”
JAR files
• http://stackoverflow.com/questions/30939347/jar-file-changes-in-lotus-notes-database-not-being-picked-up-by-domino-server
SCXD
OSGi plugin*
• http://stackoverflow.com/questions/33233724/while-in-development-in-xpages-libraries-changes-are-not-picked-up/33234041#33234041
Servlet / OSGi application*
* Without JRebel https://www.youtube.com/watch?v=EHbVgA2oqD0
Indians!
Question
• http://stackoverflow.com/questions/33190731/value-picker-get-error-typeerror-resp-is-null-in-xpages/33210520#33210520
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
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
It’s Erased!
Some Questions
• http://stackoverflow.com/questions/24735862/best-practice-for-storing-datetime-values-in-xpages
• http://stackoverflow.com/questions/34417067/xpages-notserializableexception-on-datetime/34417335?noredirect=1#comment56612210_34417335
• http://stackoverflow.com/questions/33168499/cannot-serialize-javascript-function/33168732#33168732
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
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
Summary
• Understand ignoreRequestParams
• Avoid simple actions
• Keep Pages in Memory – understand impacts
• Use viewState=“nostate”
• Understand detailsOnClient=“true”
• Understand repeatControls=“true”
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
Thank You!
Paul Withers
Intec Systems Ltd
IBM Champion
OpenNTF Board Member
@paulswithers
http://www.intec.co.uk/blog
Thank you