Write an Editor in Java

Last modified by superadmin on 2026/10/14 10:44

Steps

Add an editor to the registry from Java by implementing the Editor role as a component, so that the resolution chain can offer it for a data type.

An editor written this way is compiled with a module and ships with it. To add one without recompiling, write it as a wiki page instead. The code below is the text editor that the Edit API itself ships, taken step by step.

  1. Create the component class. AbstractTemplateEditor<D> is the base class to extend when the editor's HTML comes from a template, D being the data type it edits. The @Named hint becomes the editor's identifier, so declare it as a constant: the descriptor needs it too.
    @Component
    @Singleton
    @Named(TextXDOMEditor.ROLE_HINT)
    public class TextXDOMEditor extends AbstractTemplateEditor<XDOM> implements Initializable
    {
        public static final String ROLE_HINT = "text";
    }

    Two other starting points exist for an editor that does not render a template: AbstractEditor<D>, which handles the script binding of the next steps and leaves render() to you, and the Editor<D> role itself, whose two methods are getDescriptor() and render(D data, Map<String, Object> parameters). Both render methods may throw EditException.

  2. Describe the editor. Inject an EditorDescriptorBuilder, configure it once in initialize() with at least the id and the category, and return build() from getDescriptor():
    @Inject
    private EditorDescriptorBuilder editorDescriptorBuilder;
    
    @Override
    public void initialize() throws InitializationException
    {
        this.editorDescriptorBuilder.setId(ROLE_HINT).setCategory(ROLE_HINT);
    }
    
    @Override
    public EditorDescriptor getDescriptor()
    {
        // Re-build the descriptor for the current localization context.
        return this.editorDescriptorBuilder.build();
    }

    Build the descriptor on every call and never store the result. The builder is stateful and resolves the descriptor's name and description from the translations edit.editor.<id>.name and edit.editor.<id>.description when they were not set explicitly, falling back to the id for the name. No module in the platform ships those keys today, so an editor that wants a readable name has to ship them itself. The other properties a descriptor carries are icon and, alongside the id, the category.

  3. Return the name of the template that produces the editor's HTML:
    @Override
    public String getTemplateName()
    {
        return "editors/xdomText.vm";
    }
  4. Write that template. Before it is rendered, the data being edited and the parameters the caller passed are bound to the script context under the name edit, and any previous value of that binding is restored afterwards, so a template reads $edit.data and $edit.parameters:
    <textarea name="content" cols="$!edit.parameters.cols" rows="$!edit.parameters.rows">
    $escapetool.xml($edit.data.content)
    </textarea>
  5. Declare the component in the module's META-INF/components.txt, one fully qualified class name per line, or it is never registered:
    org.xwiki.edit.internal.TextXDOMEditor
  6. Confirm the editor is registered, from any wiki page, by listing the editors of its data type:
    {{velocity}}
    #foreach ($editor in $services.edit.xdom.getEditors())
    * $editor.descriptor.id in category $editor.descriptor.category
    #end
    {{/velocity}}

    The new identifier appears in that list, and from then on the resolution chain can select it.

Related

Get Connected