Groovy Script Service Tutorial

Version 8.1 by slauriere on 2019/02/08 17:58

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 a wiki component
  • Let the created component declare the interface org.xwiki.component.phase.Initializable
  • Add the required methods to the component

Caveat: the proposed approach will work only in the current wiki.

Create 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

When a component implements the interface Initializable, their method initialize gets executed when the component is created. Turning our component into an Initializable will allow us to add some code to that method that will register the script service. In order to do so:

  • 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}}
Tags:
    

Get Connected