Hi all,
is there a built-in REST method that exposes the functionality of “Manage: Move/Rename” web gui element to allow the programmatic renaming of a page and its children? (At least according to https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiRESTfulAPI there isn’t, but on the other hand that document is almost one year old) Or perhaps an extension that offers this as REST functionality?
to my knowledge there’s no such thing. One of the reason is that the move/rename operation is generally not a unique operation: when you do that from the UI you also perform several refactoring checks and operations, such as renaming links. It could also trigger questions, like when you try to move a space containing some extension pages.
It’s not always easy to generate the right request body unless you are in Java, in which case you can reuse the org.xwiki.rest.internal.ModelFactory component and its #toRestJobRequest which makes things easier. Unfortunately it’s internal so not recommended to count on it on the long run but there will always be a helper like this in a form or another since we need it.
Thanks for your your replies guys, I’m trying to go with tmortagne’s pointer for now; I don’t really mind using internal APIs here, since I’m planning to just learn the form of the xml document and use it as a text template later, swapping out parameter values as needed. However, trying to generate the request body via this code
// JAVA START
RenameRequest request = new RenameRequest();
// RenameRequest class definition taken from here:
// https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/Tutorials/PerformingAsynchronousTasks/
var xwiki = new WikiReference(“xwiki”);
request.setId(UUID.randomUUID().toString());
request.setSpaceReference(new SpaceReference(“TestPage1”, xwiki));
request.setNewSpaceName(“TestPage2”);
request.setCheckRights(false);
request.setInteractive(false);
request.setUserReference(new DocumentReference(new LocalDocumentReference(“Home”, “myuser”), xwiki));
ModelFactory mf = new ModelFactory();
JobRequest rjr = mf.toRestJobRequest(request); // NullPointerException is thrown here
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(JobRequest.class);
Marshaller m = context.createMarshaller();
m.marshal(rjr, writer);
// JAVA END
results in
// STACK TRACE START
Exception in thread “main” java.lang.NullPointerException: Cannot invoke “org.xwiki.rest.internal.JAXBConverter.serializeAny(Object)” because “this.jaxbConverter” is null
at org.xwiki.rest.internal.ModelFactory.toRestMapEntry(ModelFactory.java:1095)
at org.xwiki.rest.internal.ModelFactory.toRestJobRequest(ModelFactory.java:1070)
at xwikitest.XwikiTest.main(XwikiTest.java:81)
// STACK TRACE END
Complete nonsense request parameters aside, this supposedly happens because I’m executing that piece of code standalone outside of a full xwiki instance, and ModelFactory.jaxbConverter isn’t properly injected (the field carries the @inject annotation). Is there a quick-and-easy way to fix this, or is there a factory of factories that I need to use instead of ModelFactory’s constructor?
Indeed, ModelFactory is designed to be used inside an XWiki instance.
The simplest would probably be to move your code to a {{groovy}} macro (if you don’t know Groovy it’s OK as the Java syntax mostly works in it, it just adds some shortcuts) in a page of an XWiki instance.
In the Groovy script, you can get the ModelFactory component with services.component.getInstance(org.xwiki.rest.internal.ModelFactory.class).
Thanks again for your help, finally got the XML job request generation to work. However, the result of the HTTP PUT to “https://xwiki.myserver.local/xwiki/rest/jobs” is a code 500 (internal server error) and the helpful error message “Failed to start job” (nothing more).
The job request XML chunk contains verbose=true, remote=true, interactive=false, the job id is randomly generated. I know that it is not an auth problem (in that case the error code is 401). The source space of the renaming operation exists, the target space doesn’t, and the user has all permissions for the parent and its descendants.
Is the REST endpoint URL the right one? Is there a way to get more debug info in the reply?
P. S.: It just hit me that nowhere in my jobRequest xml chunk I state what kind of job I would like performed. How do I get this across? Is it a REST endpoint other than /xwiki/rest/jobs, or an additional property or element in the XML?