Use Refactoring Module with API REST

Hello everyone,

I hope this topic is not too similar with this one but it seems that there is not really answer in it. I’ll delete it in that case.

I saw that we can call jobs by REST API with a XML file in the HTTP request’s input. I would like to use the jobs of Refactoring Module but it is not really clear how we can get XML template for each job.

According to REST documentation :

There is JAXB objects provided for the Java side to help generate proper HTTP request but for pure HTTP use case it usually helps to ask for the status of an existing job to have an hint of how the XML/JSON should look like (see jobstatus section).

However, I don’t know how to create a refactoring job and get its ID to ask to ‘jobstatus’ endpoint its status.

If anyone performed job request with REST API, I’m curious to know the solution.
Thank you.

Depends on what kind of job you want to call, but the UI is using Refactoring jobs for things like delete and move (pretty much any modification to a wiki page which show a progress bar and/or a log at the end is generally a sign that there is a refactoring job behind). Then you just need to find its id to use it in a jobstatus request.

But honestly, what @codemonkey did (generating the required XML using a Java/Groovy script) might actually be the easiest if you are reasonably able to read Java code (but the same could be done with any other language supported by XWiki like Python 2.7 or Ruby). I just created a more documented example on Generate Refactoring Job REST request XML (Extension.Generate Refactoring Job REST request XML.WebHome) - XWiki.

Thank you so much @tmortagne for your answer !

Your script is very useful, but I have an issue when I try to start the job with curl :

curl -i --user "admin:password" -X PUT -H "Content-Type: text/xml" "http://localhost:8080/xwiki/rest/jobs?jobType=refactoring/move" --upload-file test.xml
HTTP/1.1 100 

HTTP/1.1 500 
Content-Script-Type: text/javascript
Set-Cookie: JSESSIONID=**********; Path=/xwiki; HttpOnly
Access-Control-Allow-Origin: *
Date: Tue, 09 Aug 2022 09:10:13 GMT
Server: Restlet-Framework/2.3.12
XWiki-User: xwiki:XWiki.admin
XWiki-Version: 14.2.1
Content-Type: application/json;charset=ISO-8859-1
Content-Language: en
Transfer-Encoding: chunked
Connection: close

{"code":500,"contactEmail":null,"description":"The server encountered an unexpected condition which prevented it from fulfilling the request","homeRef":"/","reasonPhrase":"Internal Server Error","uri":"http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1"}

What could cause this 500 error ? I tried to change “destination” property and “entityReferences” property in xml file to refer to a PageReference instead of a SpaceReference, but it doesn’t change anything.

I’m afraid there is nothing useful in that error message, maybe you have more details on server log side ?

Sorry, indeed with logs, it should be better :sweat_smile: :

août 09 15:03:34 ordi001 tomcat9[19114]: AVERTISSEMENT: Exception or error caught by status service
août 09 15:03:34 ordi001 tomcat9[19114]: java.lang.ClassCastException: class org.xwiki.job.DefaultRequest cannot be cast to class org.xwiki.refactoring.job.EntityRequest (org.xwiki.job.DefaultRequest and org.xwiki.refactoring.job.EntityRequest are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @4102b1b1)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.xwiki.refactoring.internal.job.AbstractEntityJob.createNewStatus(AbstractEntityJob.java:53)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.xwiki.job.AbstractJob.initialize(AbstractJob.java:171)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.xwiki.refactoring.internal.job.AbstractEntityJob.initialize(AbstractEntityJob.java:115)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.xwiki.job.internal.DefaultJobExecutor.createJob(DefaultJobExecutor.java:308)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.xwiki.job.internal.DefaultJobExecutor.execute(DefaultJobExecutor.java:316)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.xwiki.rest.internal.resources.job.JobsResourceImpl.executeJob(JobsResourceImpl.java:80)
août 09 15:03:34 ordi001 tomcat9[19114]:         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
août 09 15:03:34 ordi001 tomcat9[19114]:         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
août 09 15:03:34 ordi001 tomcat9[19114]:         at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
août 09 15:03:34 ordi001 tomcat9[19114]:         at java.base/java.lang.reflect.Method.invoke(Method.java:566)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.ext.jaxrs.internal.wrappers.AbstractMethodWrapper.internalInvoke(AbstractMethodWrapper.java:162)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.ext.jaxrs.internal.wrappers.ResourceMethod.invoke(ResourceMethod.java:281)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.ext.jaxrs.JaxRsRestlet.invokeMethod(JaxRsRestlet.java:997)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.ext.jaxrs.JaxRsRestlet.handle(JaxRsRestlet.java:746)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.doHandle(Filter.java:150)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.handle(Filter.java:197)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Router.doHandle(Router.java:422)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Router.handle(Router.java:641)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.doHandle(Filter.java:150)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.handle(Filter.java:197)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.doHandle(Filter.java:150)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.handle(Filter.java:197)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.doHandle(Filter.java:150)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.handle(Filter.java:197)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.doHandle(Filter.java:150)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.handle(Filter.java:197)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.doHandle(Filter.java:150)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:140)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.handle(Filter.java:197)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.doHandle(Filter.java:150)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.handle(Filter.java:197)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:202)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.engine.application.ApplicationHelper.handle(ApplicationHelper.java:77)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.Application.handle(Application.java:385)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.doHandle(Filter.java:150)
août 09 15:03:34 ordi001 tomcat9[19114]:         at org.restlet.routing.Filter.handle(Filter.java:197)
...

Hmm, I’m afraid this is a bug of this specific type of job (and from what I see it seems to be a common mistake among the refactoring/* jobs…). Would be great if you could create a BUG issue about that on https://jira.xwiki.org/browse/XWIKI. Should be an easy fix but it will be only in the next release…

Unfortunately, I cannot think of any workaround other than:

  • patching your XWiki instance with the fix (when it’s fixed)
  • provide your own component which extends org.xwiki.refactoring.internal.job.MoveJob with the fix (which is to implement castRequest)