Developing your first plugin - Generate a new plugin from a Maven archetype template

This guide shows you how to generate a new plugin from a Maven archetype template.

A Maven archetype is used to define the structure of a Funnelback plugin and provides both the file structure and a set of template files required by a plugin.

Using a Maven archetype is the easiest way to setup a new plugin as this will create a new plugin by automatically fetching the current version of the template and running through a setup process that configures all the required options.

Prerequisites

Before using this guide ensure that you have installed Java, Apache Maven and IntelliJ on your computer as outlined in part 1: setting up your development environment.

Interactive setup

When the Maven command is run it will prompt for a number of required fields.

  1. Open up a terminal and change to the folder that houses all of your plugins. If this is the first time creating a plugin then create a new folder to use for your plugin development. Each plugin that you develop will be in a sub-folder of this.

    cd my-plugins-directory
  2. Run the maven command.

    mvn archetype:generate -DarchetypeGroupId=com.funnelback -DarchetypeArtifactId=plugin-archetypes -DarchetypeVersion=LATEST
  3. Supply a group ID when prompted.

    A groupId defines your organisation/subgroup. This should be based on your organisation’s domain name. e.g. If your organisation is Funnelback and it has a domain name of 'funnelback.com' then you should use com.funnelback.plugin. For this exercise a fictitious organisation Example Pty. Ltd. with domain of example.com will be used.

    The should match expression note in the prompt tells you that the ID can only be made up of lowercase or uppercase alphabetic characters, numbers, periods and dashes.

    Define value for property 'groupId' (should match expression '^[a-zA-Z0-9\.\-]+$'): com.example.plugin
  4. Supply an artifact ID when prompted.

    The artifactId defines the name of the plugin. The title should be conscise but describe the function of the plugin. In this tutorial a plugin that modifies the prefix of a title in search results will be written. For this we will use title-prefix-plugin as the artifact ID.

    Define value for property 'artifactId' (should match expression '^[a-zA-Z0-9\.\-]+$'): title-prefix-plugin
  5. Supply a version for the plugin

    Plugins support versioning allowing a user to specify which version of a plugin will be used when enabling it on a data source or results page. The plugin version needs to be a valid semver version (hence the long regex below). For a new plugin set this to 1.0.0.

    Define value for property 'version' (should match expression '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$') : : 1.0.0
  6. Supply a package name for the plugin

    The package ID is used by Java to identify the plugin. It should be entered following the format <groupId>.<artifactId>, without hyphens. A unique package name is recommended to avoid conflicts with other plugins.

    Define value for property 'package' com.example.plugin: : com.example.plugin.titleprefixplugin
  7. Supply a plugin name for the plugin

    The plugin name is the human readable name for the plugin, for display in the plugin administration pages in Funnelback.

    Define value for property 'plugin-name' (should match expression '^[a-zA-Z0-9\.\- ]+$'): Example Plugin
  8. Supply a description for the plugin

    A short description of the plugin, also be shown in the plugin administration pages.

    Define value for property 'plugin-description': An example description
  9. Define where the plugin will run

    A plugin can run on a data source and/or a results page. So Funnelback knows where to install the plugin, we need to set the runs-on-datasource and runs-on-result-page properties. The title-prefix-plugin will run in a results page, which we indicate like so:

    Define value for property 'runs-on-datasource' (should match expression '^(?i)(true|false)$'): false
    Define value for property 'runs-on-result-page' (should match expression '^(?i)(true|false)$'): true
  10. Define which plugin templates to include

    At this point Maven will provide a prompt asking if the plugin should be created.

    By default (if you press y) Maven will create the new plugin with all the available interface templates.

    If you wish to define which interface templates are included then you can press n and Maven will then confirm which interface templates to include.

    Plugins can implement a number of different interfaces, which provide different types of functionality within the plugin. Most plugins will only need to implement a subset of these functions and you can define which things are required before the new plugin is generated.

    Interface flag Description

    gatherer

    Only works for a custom data source. Lets you create a custom gatherer, which will get documents in unique ways.

    filtering

    Lets you create a document filter for modifying documents before they are indexed.

    jsoup-filtering

    Lets you create a html jsoup filter for processing html documents before they are indexed.

    indexing

    Lets you hook into different parts of the indexing process; providing metadata mappings, external metadata mappings, gscopes or to kill documents

    facets

    Lets you provide faceted navigation configuration.

    search-servlet-filtering

    Lets you hook into the servlet request and response lifecycle by implementing the SearchServletFilterHook interface

    searchLifeCycle

    Lets you provide scripts that hook into the query processing and search results

    If you are not sure which interfaces you will need create the plugin with all interface templates and cleanup any unused ones later.

    For this plugin we only want to change the title of every search result. To achieve this only requires the searchLifeCycle interface so we can say n at the prompt to specify which interfaces should be included in the new plugin.

     Y: : n
    Define value for property 'groupId' (should match expression '^[a-z0-9\.]+$'): com.example.plugin
    [INFO] Using property: groupId = com.example.plugin
    Define value for property 'artifactId' (should match expression '^[a-z0-9\.\-]+$'): title-prefix-plugin
    [INFO] Using property: artifactId = title-prefix-plugin
    Define value for property 'version' (should match expression '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$') : : 1.0.0
    Define value for property 'package' com.example.plugin.title-prefix-plugin: : com.example.plugin.titleprefixplugin
    [INFO] Using property: archetypeVersion = LATEST
    Define value for property 'facets' (should match expression '^(?i)(true|false)$'): false
    Define value for property 'filtering' (should match expression '^(?i)(true|false)$'): false
    Define value for property 'gatherer' (should match expression '^(?i)(true|false)$'): false
    Define value for property 'indexing' (should match expression '^(?i)(true|false)$'): false
    Define value for property 'jsoup-filtering' (should match expression '^(?i)(true|false)$'): false
    Define value for property 'plugin-description': Adds a prefix to search result titles
    Define value for property 'plugin-name' (should match expression '^[a-zA-Z0-9\.\- ]+$'): Title Prefix Plugin
    Define value for property 'runs-on-datasource' (should match expression '^(?i)(true|false)$'): false
    Define value for property 'runs-on-result-page' (should match expression '^(?i)(true|false)$'): true
    Define value for property 'search-servlet-filtering' (should match expression '^(?i)(true|false)$'): true
    Define value for property 'searchLifeCycle' (should match expression '^(?i)(true|false)$'): true
    Confirm properties configuration:
    groupId: com.example.plugin
    artifactId: title-prefix-plugin
    version: 1.0.0
    package: com.example.plugin.titleprefixplugin
    archetypeVersion: LATEST
    facets: false
    filtering: false
    gatherer: false
    indexing: false
    jsoup-filtering: false
    plugin-description: Adds a prefix to search result titles
    plugin-name: Title Prefix Plugin
    runs-on-datasource: false
    runs-on-result-page: true
    search-servlet-filtering: true
    searchLifeCycle: true
     Y: :

    Maven will generate a new folder generated called title-prefix-plugin, as a sub-folder to your my-plugins-directory. This folder contains all the files required to develop and package your plugin.

Non-interactive setup

The interactive setup instructions prompt (interactively) for a number of required parameters. It is also possible to run the maven command and supply all the required options directly as parameters to the command. This allows creation of the new plugin to be scripted.

The following command is equivalent to the command that ran in interactive mode after all the options were input.

mvn archetype:generate -DarchetypeGroupId=com.funnelback          \
    -DarchetypeArtifactId=plugin-archetypes                       \
    -DarchetypeVersion=15.25.2030-SNAPSHOT                        \
    -DgroupId=com.example.plugin                                  \
    -DartifactId=title-prefix-plugin                              \
    -Dpackage=com.example.plugin.titleprefixplugin                \
    -Dversion=1.0.0                                               \
    -Dfacets=false                                                \
    -Dplugin-description="Adds a prefix to search result titles"  \
    -Dplugin-name="Title Prefix Plugin"                           \
    -Dfiltering=false                                             \
    -Dgatherer=false                                              \
    -Dindexing=false                                              \
    -Djsoup-filtering=false                                       \
    -Druns-on-datasource=false                                    \
    -Druns-on-result-page=true                                    \
    -Dsearch-servlet-filtering=true                               \
    -DsearchLifeCycle=true

Next steps

The next tutorial shows how to import this project into IntelliJ and covers the anatomy of a plugin.

© 2015- Squiz Pty Ltd