Applicable: | This tutorial applies to Confluence 5.9.1 and higher. |
Level of experience: | Beginner. |
Time estimate: | It should take you less than 30 minutes to complete this tutorial. |
This tutorial shows you how to create a plugin to add a custom action to Confluence. The custom action adds a "draft" label to a Confluence page accessible from the Tools drop-down menu.
Concepts covered in this tutorial:
Web Item
and Struts
module to your plugin.PageAware, Label, Labelable
, and LabelManger
interfaces.About these instructions
You can use any supported combination of operating system and IDE to create this plugin. These instructions were written using Intellij IDEA 2017.2 on macOS Sierra. If you are using another operating system or IDE combination, you should use the equivalent operations for your specific environment.
This tutorial was last tested with Confluence 6.7.1 using Atlassian SDK 6.3.10.
To complete this tutorial, you should:
We encourage you to work through this tutorial. If you want to skip ahead or check your work when you are done, you can find the plugin source code on Atlassian Bitbucket. To clone the repository, run the following command:
1 2git clone git@bitbucket.org:atlassian_tutorial/confluence-custom-action-tutorial.git
Alternatively, you can download the source as a ZIP archive.
In this step, you'll create a plugin skeleton using atlas-
commands. Since you won't need some of the files created in the skeleton, you'll also delete them in this step.
Open Terminal and navigate to your workspace directory.
To create a Confluence plugin skeleton, run the following command :
1 2atlas-create-confluence-plugin
To identify your plugin, enter the following information:
group-id | com.atlassian.plugins.tutorial |
artifact-id | AddDraftLabelAction |
version | 1.0-SNAPSHOT |
package | com.atlassian.plugins.tutorial |
When prompted, confirm your entries with Y
or y
.
Your terminal notifies you of a successful build:
1 2[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1 minute 11 seconds [INFO] Finished at: Thu Jul 18 11:30:23 PDT 2013 [INFO] Final Memory: 82M/217M [INFO] ------------------------------------------------------------------------
Navigate to the project directory created in the previous step.
1 2cd AddDraftLabelAction/
Delete the test directories.
Setting up testing for your macro isn't part of this tutorial. Run the following commands to delete the generated test skeleton:
1 2rm -rf ./src/test/java rm -rf ./src/test/resources/
Delete the unneeded Java class files.
You'll build a single class for your custom action in further steps.
1 2rm -rf ./src/main/java/com/atlassian/plugins/tutorial/*
Import project into your favorite IDE.
AddDraftLabelAction
stub class You've created the plugin skeleton. Here, you'll create a stub class in Java called AddDraftLabelAction
.
This class uses the existing class, ConfluenceActionSupport
, to leverage existing methods for managing page labels like LabelManager
.
This class also implements PageAware
interface methods to ensure your custom action only engages with current, valid pages.
src/main/java/com/atlassian/plugins/tutorial
, create a new file AddDraftLabelAction.java
.1 2package com.atlassian.plugins.tutorial; import com.atlassian.confluence.core.ConfluenceActionSupport; import com.atlassian.confluence.pages.AbstractPage; import com.atlassian.confluence.pages.actions.PageAware; public class AddDraftLabelAction extends ConfluenceActionSupport implements PageAware { @Override public AbstractPage getPage() { return null; } @Override public void setPage(AbstractPage page) { } @Override public boolean isPageRequired() { return false; } @Override public boolean isLatestVersionRequired() { return false; } @Override public boolean isViewPermissionRequired() { return false; } @Override public boolean isEditPermissionRequired() { return false; } }
execute
methodYou've built the foundation for your class, now you'll flesh out the stub code. Your class foundation is built from ConfluenceActionSupport
and PageAware
.
It inherits methods that deal with validating or identifying a specific Confluence page. Here, you'll add additional
interfaces—Label
, Labelable
, and LabelManager
—so that your custom action can add a label to a page.
Add the Label
, Labelable
, and LabelManager
interfaces to your class.
These interfaces provide access to methods and fields for managing and creating labels in Confluence.
1 2import com.atlassian.confluence.labels.Label; import com.atlassian.confluence.labels.LabelManager; import com.atlassian.confluence.labels.Labelable;
Add page
and labelManager
as instance variables.
1 2private AbstractPage page; private LabelManager labelManager;
Complete the stub code for getPage()
and setPage()
.
getPage()
obtains the current Confluence page and sets the return
to page
. With page
defined, setPage()
defines which page your custom action should interact with.
1 2@Override public AbstractPage getPage() { return page; } public void setPage(AbstractPage page) { this.page = page; }
Modify the stub code to return true
for methods with a boolean return
.
These methods are all inherited from the PageAware
interface. Now, your custom action will only execute if the Confluence page is
within the scope of user permissions, is defined as a page, and is the most recent version.
1 2@Override public boolean isLatestVersionRequired() { return true; } @Override public boolean isPageRequired() { return true; } @Override public boolean isViewPermissionRequired() { return true; }
Invoke the setLabelManager
method.
1 2public void setLabelManager(LabelManager labelManager) { this.labelManager = labelManager; }
Add the execute
method to instantiate a new draft label.
Your execute
method returns the "success" message as a String
, which your struts
module in the atlassian-plugin.xml
file uses to trigger a page refresh.
1 2public String execute() { Label label = new Label("draft"); labelManager.addLabel((Labelable) page, label); return "success"; }
Save your changes.
Here's what your finalized AddDraftLabelAction.java
file should look like:
1 2package com.atlassian.plugins.tutorial; import com.atlassian.confluence.core.ConfluenceActionSupport; import com.atlassian.confluence.pages.AbstractPage; import com.atlassian.confluence.pages.actions.PageAware; import com.atlassian.confluence.labels.Label; import com.atlassian.confluence.labels.LabelManager; import com.atlassian.confluence.labels.Labelable; public class AddDraftLabelAction extends ConfluenceActionSupport implements PageAware { private AbstractPage page; private LabelManager labelManager; @Override public AbstractPage getPage() { return page; } public void setPage(AbstractPage page) { this.page = page; } @Override public boolean isLatestVersionRequired() { return true; } @Override public boolean isPageRequired() { return true; } @Override public boolean isViewPermissionRequired() { return true; } @Override public boolean isEditPermissionRequired() { return false; } public void setLabelManager(LabelManager labelManager) { this.labelManager = labelManager; } public String execute() { Label label = new Label("draft"); labelManager.addLabel((Labelable) page, label); return "success"; } }
web-item
module to the atlassian-plugin.xml
plugin descriptorYou've built the skeleton for your plugin and finalized a Java class. To describe how Confluence should interact with your code,
you'll modify the atlassian-plugin.xml
file. This file bases these dependencies on your pom.xml
. The atlassian-plugin.xml
file was generated
when you created your plugin skeleton.
In this step you'll add a Web Item
module to your plugin. This module type allows you to customize application menus in Confluence
with links to your custom action. You can add modules to Confluence with the command atlas-create-confluence-module
,
but in this particular case it's more convenient to simply modify the atlassian-plugin.xml
file directly.
In your IDE, open atlassian-plugin.xml
.
This file is located under src/main/resources
.
Find the closing </plugin-info>
tag.
Directly after the closing </plugin-info>
tag, add the following.
This section defines the <label>
users will see in the Tools menu, and when the custom action is accessible ( system.content.action/primary
). There are four sections in the Tools menu: primary, marker, secondary, and modify. Designating your plugin's location as primary will place it at the top of the menu.
1 2<web-item name="add-draft-label-action-web-ui" key="add-draft-label-action-web-ui" section="system.content.action/primary" weight="10"> <description key="item.add-draft-label-action-web-ui.link.desc">Adds the "Add 'draft' label" action into the Tools menu.</description> <label key="Add ''draft'' label"/> <link linkId="add-draft-label-action">/plugins/add-draft-label/add-label.action?pageId=$page.id</link> </web-item>
Save your changes.
struts
module to atlassian-plugin.xml
Now, you'll add a Struts module. Your Web Item
component module defines the label and placement of the custom action. In this step,
you'll define what the custom action should do within Confluence using an struts
module. The struts
module will rely on your Java class,
AddDraftLabelAction
. This module informs Confluence to reference your Java class to execute on the page. After the draft label is applied,
AddDraftLabelAction.java
returns a String literal value of "success". This module then uses that message to trigger a "redirect" to the current page.
It is the same as a refresh.
In atlassian-plugin.xml
, find the closing tag for your newly-added </web-item>
.
Add the following on the line after </web-item>
.
1 2<struts name="add-draft-label-action-struts" key="add-draft-label-action-struts"> <description key="item.add-draft-label-action-struts.link.desc">Defines what the "Add 'draft' label" action does.</description> <package name="add-draft-label" extends="default" namespace="/plugins/add-draft-label"> <default-interceptor-ref name="defaultStack"/> <action name="add-label" class="com.atlassian.plugins.tutorial.AddDraftLabelAction"> <result name="success" type="redirect">${page.urlPath}</result> </action> </package> </struts>
Save your changes and close the file.
Here's an example of the complete atlassian-plugin.xml
:
1 2<atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2"> <plugin-info> <description>${project.description}</description> <version>${project.version}</version> <vendor name="${project.organization.name}" url="${project.organization.url}" /> <param name="plugin-icon">images/pluginIcon.png</param> <param name="plugin-logo">images/pluginLogo.png</param> </plugin-info> <web-item name="add-draft-label-action-web-ui" key="add-draft-label-action-web-ui" section="system.content.action/primary" weight="10"> <description key="item.add-draft-label-action-web-ui.link.desc">Adds the "Add 'draft' label" action into the Tools menu.</description> <label key="Add ''draft'' label"/> <link linkId="add-draft-label-action">/plugins/add-draft-label/add-label.action?pageId=$page.id</link> </web-item> <struts name="add-draft-label-action-struts" key="add-draft-label-action-xwork"> <description key="item.add-draft-label-action-struts.link.desc">Defines what the "Add 'draft' label" action does.</description> <package name="add-draft-label" extends="default" namespace="/plugins/add-draft-label"> <default-interceptor-ref name="defaultStack"/> <action name="add-label" class="com.atlassian.plugins.tutorial.AddDraftLabelAction"> <result name="success" type="redirect">${page.urlPath}</result> </action> </package> </struts> <!-- add our i18n resource --> <resource type="i18n" name="i18n" location="AddDraftLabelAction"/> <!-- add our web resources --> <web-resource key="AddDraftLabelAction-resources" name="AddDraftLabelAction Web Resources"> <dependency>com.atlassian.auiplugin:ajs</dependency> <resource type="download" name="AddDraftLabelAction.css" location="/css/AddDraftLabelAction.css"/> <resource type="download" name="AddDraftLabelAction.js" location="/js/AddDraftLabelAction.js"/> <resource type="download" name="images/" location="/images"/> <context>AddDraftLabelAction</context> </web-resource> </atlassian-plugin>
In this step, you'll install your plugin and run Confluence. Then, to test your custom action, you'll add a page and add a "draft" label to the page from the Tools menu.
Open Terminal window and navigate to the plugin root folder.
1 2cd AddDraftLabelAction
To start up Confluence from your project root, run the atlas-run
command.
1 2atlas-run
This command builds your plugin code, starts a Confluence instance, and installs your plugin. This may take a few minutes.
Find the URL for Confluence.
Your terminal outputs the location of your local Confluence instance, defaulted to http://localhost:1990/confluence.
1 2[INFO] confluence started successfully in 71s at http://localhost:1990/confluence [INFO] Type CTRL-D to shutdown gracefully [INFO] Type CTRL-C to exit
In your browser, open your local Confluence instance and log in with admin
/ admin
.
Click Create.
In the dialog box, choose Blank Page, and then click Create.
Add some content, and then click Save.
Click Tools > Add 'draft' label.
Verify that the 'draft' label is applied.
Rate this page: