Script Module

Version 10.1 by Thomas Mortagne on 2016/08/19 17:52

cogScripting APIs, on top of JSR-223
TypeJAR
Category
Developed by

XWiki Development Team

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Enterprise, XWiki Enterprise Manager

Compatibility

XWiki > 2.3

Description

XWiki's scripting features are built on top of JSR-223.

The Script Module offers the following:

  • Defines ScriptEvaluatedEvent and ScriptEvaluatingEvent events (see Observation Module) for being called before a script macro executes or just after it's been executed. The ScriptEvaluatedEvent  event even allow to cancel the execution of the script macro.
  • Provides a ScriptService component role allowing to expose APIs to script macros (see below)
  • Allow setting and accessing script binding trough ScriptContext

Setting binding

@Inject
private ScriptContextManager manager;

public void setMyVarForNextScript()
{
  
// Best practice since 8.3 to access the current ScriptContext
  
ScriptContext scriptContext = this.manager.getCurrentScriptContext();
  
// #getCurrentScriptContext does not exist before 8.3
  
// ScriptContext scriptContext = this.manager.getScriptContext();

  
scriptContext.setAttribute("myvar", "my value", ScriptContext.ENGINE_SCOPE);
}

Script Services

To expose an API to a script macro you simply need to implement the org.xwiki.script.service.ScriptService component role (see Component Module to know more about components). 

For example:

@Component
@Named("my")
@Singleton
public class MyScriptService implements ScriptService
{
   // Declare all java methods you wish to expose here. For example:
   public void doSomething(String whatever)
    {
        ...
    }
}

Of course, make sure to register your component in components.txt and to deploy your component JAR in WEB-INF/lib.

Then to use this in a Velocity script macro for example you'll write:

{{velocity}}
$services.my.doSomething("something here")
{{/velocity}}

Best Practices

  • Script Service methods should not throw Exceptions. This rule is there so that it's easy to write scripts in Velocity. Instead they should return null in case of an error and the Script Service should provide a public Exception getLastError() method to get the last exception thrown. For example:
    public class ComponentScriptService implements ScriptService
    {
       /**
         * The key under which the last encountered error is stored in the current execution context.
         */

       private static final String ERROR_KEY = "scriptservice.component.error";
    ...
       /**
         * Provides access to the current context.
         */

       @Inject
       private Execution execution;
    ...
       /**
         * Get the error generated while performing the previously called action.
         *
         * @return the last exception or {@code null} if no exception was thrown
         * @since 6.1M2
         */

       public Exception getLastError()
       {
           return (Exception) this.execution.getContext().getProperty(ERROR_KEY);
       }

       /**
         * Store a caught exception in the context, so that it can be later retrieved using {@link #getLastError()}.
         *
         * @param exception the exception to store, can be {@code null} to clear the previously stored exception
         * @see #getLastError()
         * @since 6.1M2
         */

       private void setError(Exception exception)
       {
           this.execution.getContext().setProperty(ERROR_KEY, exception);
       }
    ... Example of setting an exception...
       public <T> T getInstance(Type roleType, String roleHint)
       {
           ...
           try {
                result = cm.getInstance(roleType, roleHint);
           } catch (ComponentLookupException e) {
                setError(e);
           }
           ...
       }
Tags:
    

Get Connected