Contents
This page documents how to create an XWiki Script Service in Groovy. The general recommended approach for creating components in Groovy is actually to write a wiki component using the dedicated API. However, at the moment of writing, this API does not allow the creation of component methods dynamically, i.e. methods that are not already present in the interfaces declared by the wiki component (see XWIKI-16117). This tutorial proposes a workaround until XWIKI-16117 is resolved.
The approach is threefold:
- Create an event listener as a wiki component
- Let the created component declare the interface org.xwiki.component.phase.Initializable
- Add the required methods to the component
Create an event listener as a wiki component
- Create a wiki page, e.g. HelloWorldGroovyScriptService
- Add an object of class XWiki.ComponentClass to it, with the following properties:
- Role type: org.xwiki.observation.EventListener
- Role hint: helloWorldGroovyScriptService
- Scope: current wiki
More info about writing event listeners.
Turn the component into an Initializable
- Add an object of class XWiki.ComponentInterfaceClass to the page, with the following property:
- Interface qualified name: org.xwiki.component.phase.Initializable
Add methods to the component
- Add an object of class XWiki.ComponentMethodClass to the page, with the following properties:
- Name: initialize
- Body code:{{groovy}}
import javax.inject.Named
import javax.inject.Singleton
import org.xwiki.component.annotation.Component
import org.xwiki.component.annotation.ComponentAnnotationLoader
import org.xwiki.script.service.ScriptService
@Component
@Named("helloWorld")
@Singleton
public class HelloWorldGroovyScriptService implements ScriptService
{
public String execute()
{
return "Hello world from Groovy script service"
}
}
def componentManager = services.component.getComponentManager('wiki:' + services.wiki.currentWikiId)
def loader = new ComponentAnnotationLoader()
// Register service
// Parse annotation of the class to generate a descriptor in order to register the class as a component in the component manager
def descriptors = loader.getComponentsDescriptors(HelloWorldGroovyScriptService.class)
for (descriptor in descriptors) {
componentManager.registerComponent(descriptor)
}
{{/groovy}}
- Add the following method to the component, so as to make sure the component has a unique name, e.g. the current page reference converted to a string:
- Name: getName
- Body code:{{groovy}}
xcontext.method.output.value = doc.documentReference.toString()
{{/groovy}}
- Add the method below to the component. The goal here is to trigger an initialization, not to listen to real events. Since registered listeners are automatically initialized as soon as they are registered, an empty event array is ok (even though this may be considered as a trick).
- Name: getEvents
- Body code:{{groovy}}
xcontext.method.output.value = []
{{/groovy}}
Test the script service
In a distinct page, enter the code below and make sure that you get the hello world output.
{{velocity}}
$services.helloWorld.execute()
{{/velocity}}
$services.helloWorld.execute()
{{/velocity}}