I was adapting the very useful “Bulk replace content in pages” script to perform bulk changes on macro code stored in XWiki.WikiMacroClass objects.
Reading the macro code worked perfectly.
Replacing the content in memory also worked.
But every attempt to write the modified code back to the object failed ![]()
All write attempts resulted in variations of:
No signature of method: <unknown>.null() is applicable for argument types: (null)
groovy.lang.MissingMethodException
I tried all obvious approaches without success:
codeProp.setValue(newContent) // never worked
macroObj.set("code", newContent) // never worked
document.save("Bulk Replace Code.") // never worked
I also tried switching to the Core API, similar to patterns used here:
def pxwiki = xwiki.getXWiki()
def pxcontext = xcontext
def coreDoc = pxwiki.getDocument(document.getDocumentReference(), pxcontext)
def obj = coreDoc.getObject("XWiki.WikiMacroClass", macroObj.getNumber())
obj.set("code", newContent, pxcontext)
pxwiki.saveDocument(coreDoc, "Bulk Replace Code.", true, pxcontext)
This also failed, still producing the same MissingMethodException ![]()
The actual root cause
After adding more detailed logging outside the Job Macro Box, the error finally became visible to me:
No signature of method: com.xpn.xwiki.XWiki.getDocument()
is applicable for argument types:
(org.xwiki.model.reference.DocumentReference,
com.xpn.xwiki.api.Context)
So the issue was a wrong context type.
The fix
xcontext in scripts is an API context but Core APIs expect a com.xpn.xwiki.XWikiContext
The correct solution is:
def pxcontext = xcontext.context
instead of:
def pxcontext = xcontext
It took quite a while to figure this out and it ended up being a surprisingly frustrating learning experience. But it paid of finally ![]()
After switching to the proper Core context, writing to XWiki.WikiMacroClass works perfectly.
So my learning is…
If you modify objects using the Core API:
-
Reading via
xwiki.getDocument()may work -
Writing requires:
-
Core document (
XWikiDocument) -
Core context (
xcontext.context)
-
Otherwise you’ll get misleading MissingMethodException errors that look unrelated to the actual problem.
At that point I’m too happy (and tired) to continue investigating – but why is def pxcontext = xcontext working here, is it? @surli