#XPages
標記為 #XPages · 12 篇文章
- XPages 效能:為什麼 computed 一次提交被算好幾遍
在 XPages 的 computed 值或 rendered 公式裡擺個 println,按一下按鈕,它卻跑了五六遍——這不是 bug,是 XPages 每次提交都跑整輪 JSF 生命週期,而 #{}(compute dynamically)的 value binding 每被讀一次就重算一次、跨多個階段加起來就是好幾遍。這篇講三個把 computed 重算壓下來的旋鈕:#{}(每次重算)vs ${}(載入算一次、靜態),rendered(在 tree 裡、每階段都算)vs loaded(根本不建進 tree、全程跳過),以及它們各自的使用時機與 ${} 的 caveat。
2026.10.12 - document1.getDocument(true) 的 true 到底在做什麼
XPages SSJS 裡 document1.getDocument() 和 document1.getDocument(true) 到處都有人用,但那個 true(applyChanges)到底套用了什麼、什麼時候非加不可、什麼時候加了也是多餘?加錯邊的代價很實在:少加,你可能存了一份漏掉程式剛改的值的文件;多加,則是憑直覺亂下。這篇把 getDocument() 與 getDocument(true) 的差別講清楚:true 是把 data source 的待套改動(控制項輸入 + 程式 setValue)flush 進 backend 文件;一般送出事件裡 Update Model Values 早就把畫面值同步進去了、多半不用加;真正需要 true 的是你做了程式改動、或要直接對 backend 文件動作時。附上 save() 與 getComponent().getValue() 的分工。
2026.10.11 - XPages 呼叫 runOnServer 後文件還是舊值?in-memory 文件是快照——解法與用 contextDocument 省掉暫存文件
XPages SSJS 常見模式:建一個暫存文件、填參數、save、呼叫 agent.runOnServer(noteid),agent 在伺服器端把結果回寫進那份文件。然後你讀回來——卻是 agent 處理前的舊值。這不是 bug:你手上那個文件物件是載入當下的 in-memory 快照,agent 在另一條執行把磁碟上的 note 存檔了,你的物件不會自動同步。解法是 recycle 掉舊的、再 getDocumentByID 重抓一份新的。這篇講清楚這個模式、為什麼會拿到舊值、標準解法,用表單的 document data source(contextDocument)取代暫存文件,以及最乾淨的 runWithDocumentContext——傳 in-memory 文件給 agent、連存檔和重抓都免(代價是 agent 要勾「以 Web 使用者身分執行」)。
2026.10.10 - 12.0.2「子分類底下的文件消失」regression 家族:四支 KB、兩個 notes.ini 參數,先分清楚你中的是哪一個
升到 12.0.2 後,多層分類的視圖只顯示最上層、子分類底下的文件不見了。你照症狀搜到一支 KB、照它加了 notes.ini 參數,卻「did not work」——因為這不是單一 bug,是一整個家族:四支官方 KB、兩個不同的參數。client 端的 @PickList 與 embedded view 用 EnableExtendedFindByKey=0(修於 FP1),XPages 用 DISABLE_REFIND_IN_READENTRIES=1(修於 FP3/14.0)。這篇把四支 KB 整理成一張對照表,教你先對到自己的介面、再下對的參數。
2026.10.07 - XPages 多欄位分類、下一欄還是分類時文件不顯示——12.0.2 的 regression 與 DISABLE_REFIND_IN_READENTRIES
一個 XPages 視圖分類在多個欄位上,你套上篩選、而下一欄還是分類時,畫面只出現分類、底下的文件卻不見了——12.0.2 才這樣,12.0.1 是正常的。這是 HCL 官方認的 regression(KB0102504 / SPR# MNIACMGKUV),是 12.0.2 修另一個 bug(SPR# PJONB7GRUL)時引入的。暫解是在伺服端 notes.ini 加 DISABLE_REFIND_IN_READENTRIES=1,正解是升到 12.0.2 FP3 或 14.0。這篇講症狀、為什麼會這樣、暫解與正解,以及 12.0.2 一整組同家族的分類視圖 regression(像官方 KB0102042 的 @PickList 變體,參數與修復版本都不同)該怎麼對症下參數。
2026.10.06 - 從 SSJS 跑 @Formula:session.evaluate 的回傳、限制,與「不能改文件」這件事
你已經有一段 Formula 邏輯——一個 @DbLookup、一段 @Name 格式化——不想在 SSJS 裡重寫一遍。session.evaluate() 讓你直接從 SSJS 跑一段 Formula 字串、把結果拿回來。但它有幾個利角:回傳的是 java.util.Vector(不是純量),公式引用到欄位時要用兩參數版把 document 傳進去,UI 類的 @functions(@Command/@Prompt/@PickList…)在裡面不能用,而且它不能改文件、只能算出結果。這篇整理 session.evaluate 的兩種寫法、回傳與限制,以及要改文件時該怎麼把結果寫回去。
2026.10.05 - XPages managed bean:給 SSJS 一個真正的 Java 物件,像 database 一樣直接用
SSJS 寫在 script library 裡當膠水很方便,但邏輯一多就難維護——沒有真正的型別、難測試、塞進 scope 還有序列化問題。managed bean 讓你在 faces-config.xml 宣告一個 Java class,它就變成 SSJS 與 EL 裡的一個頂層變數,用起來跟 database、session 一樣——bean.method()、#{bean.prop}。這篇講 managed bean 怎麼宣告(name/class/scope 三元素)、class 的三個要件(no-arg 建構子、get/set、Serializable)、scope 的生命週期,以及邏輯什麼時候該從 SSJS 搬進 bean。
2026.10.03 - partial refresh vs partial execution:XPages 的 JSF 六階段,為什麼只刷一塊卻整頁重算
你在 XPages 按一個按鈕,結果一個八竿子打不著的欄位驗證器跳出來擋你——因為預設情況下,整頁都跑了一輪 JSF 生命週期,不只你按的那塊。XPages 有兩個各自獨立的「partial」旋鈕:partial refresh(refreshMode/refreshId)管的是 client 端回傳哪塊 HTML,partial execution(execMode/execId)管的才是 server 端跑哪些元件的生命週期。這篇用 JSF 六階段講清楚兩者差別、為什麼只做 partial refresh 整頁還是在 server 重算,以及 partial execution 怎麼把 server 工作縮到一塊。
2026.10.01 - sessionAsSigner:XPages 用簽章者身分提權,簽章算誰、會踩什麼雷
XPages 給你三個全域 session:session 是當前使用者、sessionAsSigner 是 XPage 的簽章者、sessionAsSignerWithFullAccess 是簽章者再加 full access。用它讓使用者做他 ACL 上做不到的事(寫受限 DB、繞 Readers)很方便,但「簽章者到底算誰」是逐個 design element 算的——script library 用它自己的簽章者,不是 XPage 的,混簽就提權不一致。這篇講三個 session 的身分差別、簽章者怎麼認定,以及 setConvertMime、full access 那幾個會咬人的雷。
2026.09.28 - XPages 四個 scope:各活多久、該放什麼、什麼會爆
XPages 有 requestScope/viewScope/sessionScope/applicationScope 四個 scope,壽命從「一個請求」到「整個應用」差很多。挑錯 scope,值會莫名消失或跨使用者互相汙染;而最會咬人的是——scope 會被序列化寫到磁碟,把 NotesDocument、NotesView 或 SSJS function 塞進去,遲早噴 NotSerializableException。這篇講清楚四個 scope 各活多久、名稱怎麼由窄到寬解析、什麼能放什麼不能放,以及該存 UNID/view 名而不是物件本身。
2026.09.27 - XPages 存檔衝突:為什麼「只有你一個人」還會跳存檔衝突
「Document has been saved by another user」——奇怪的是根本沒別人在動這份文件,存檔衝突卻偶爾自己冒出來。這篇講一個 XPages 老坑:在同一份文件上混用 dominoDocument 資料來源的存檔與後端 Document 的存檔,會讓 Domino 的衝突判定誤判、生出一份 conflict 文件。從官方的衝突機制($Revisions)講起、拆解 assono 那個經典重現,並在 Domino 12.0.2 與 14.5.1 各自實測看這個 2013 年的坑現在還在不在。
2026.09.16 - XPages 附件多選批次刪除:官方只能一次刪一個,自己補上「勾選多個、存檔一次刪」
XPages 的 File Download 控制項只給你一列一個、一次刪一個附件,沒有「勾選多個、一次刪」的原生做法——連做得很完整的生產表單也缺這塊。這篇先實測澄清一件事:原生刪除其實是「存檔才生效」、很守規矩;再用同樣 save-bounded 的官方 API(NotesXspDocument.removeAttachment)自己補上多選批次刪,在測試環境(Domino 12.0.2)做出一個可勾選、可反悔、存檔一次落地的實作。
2026.09.13