Skip to end of metadata
Go to start of metadata
Level of experienceBEGINNER
Time estimate1:00
Atlassian applicationCONFLUENCE 4.X+

On this page:

Tutorial overview

This tutorial will show you how to create a macro for Confluence. Macros are treated as plugins in Confluence and other Atlassian applications. The macro you'll build for Confluence generates a list of macros used on a page, and outputs them in a table format. This is a good tutorial if you've never developed an add-on before.

Here's an example how your macro might appear when you're finished:

Macro example table

The following concepts will be covered:

  • The Macro interface.
  • Using the provided API to interact with storage format.
  • The xhtml-macro module descriptor.

About these Instructions


You can use any supported combination of OS and IDE to create this plugin. These instructions were written using Eclipse Indigo on Mac OS X. If you are using another OS or IDE combination, you should use the equivalent operations for your specific environment.

This tutorial was last tested with Confluence 5.2.3. 

Prerequisite knowledge

You should complete the beginner tutorial, Set up the Atlassian Plugin SDK and Build a Project, before starting this tutorial. You should also already understand basic Java development – classes, interfaces, methods, and how to use the compiler.

Plugin source

We encourage you to work through this tutorial. If you want to skip ahead or check your work when you're done, you can find the plugin source code on Atlassian Bitbucket. Bitbucket serves a public Git repository containing the tutorial's code. To clone the repository, issue the following command:

$ git clone

Alternatively, you can download the source code for this plugin project. 

Step 1. Create the plugin project and trim the skeleton

In this step you'll generate stub code for your plugin, and setup the stub code as an Eclipse project. You'll use atlas- commands to automate the plugin creation.  

  1. Open a terminal and navigate to your Eclipse (or equivalent IDE) workspace directory.

  2. Enter the following command to create a Confluence plugin skeleton:

  3. When prompted, enter the following information to identify your plugin:









  4. Confirm your entries when prompted with Y or y.

    Your terminal notifies you of a successful build:

    [INFO] ------------------------------------------------------------------------
    [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] ------------------------------------------------------------------------
  5. Change to the tutorial-confluence-macro-demo directory created by the previous step. 

    $ cd tutorial-confluence-macro-demo
  6. Delete the test directories.

    Setting up testing for your macro isn't part of this tutorial. Use the following commands to delete the generated test skeleton:

    $ rm -rf ./src/test/java
    $ rm -rf ./src/test/resources/
  7. Delete the unneeded Java class files.

    You'll build a single class for your macro in later steps.

    $ rm ./src/main/java/com/example/plugins/tutorial/confluence/*.java
  8. Edit the src/main/resources/atlassian-plugin.xml file.

  9. Remove the generated myPluginComponent component declaration.

     Click here to see how the file should look when you are done.

    Here's what your atlassian-plugin.xml should look like after the deletion:

  10. Save and close atlassian-plugin.xml.

Import your project into your IDE

 Click here to see instructions for importing into Eclipse


  1.  Make your project available to Eclipse.

    atlas-mvn eclipse:eclipse

    You'll see a successful build message: 

    [INFO] ------------------------------------------------------------------------
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 54 seconds
    [INFO] Finished at: Tue Jul 16 11:03:59 PDT 2013
    [INFO] Final Memory: 82M/224M
    [INFO] ------------------------------------------------------------------------
  2. Start Eclipse.
    You can open a new terminal window to perform this action.

    $ cd ~/eclipse
    $ ./eclipse
  3. Click File > Import
    Eclipse starts the Import wizard.

  4. Expand the General folder tree to choose Existing Projects into Workspace.

  5. Click Next. 

  6. Click Browse and enter the root directory of your workspace.
    Your Atlassian plugin folder should now appear under Projects.

  7. Ensure your plugin checkbox is ticked and click Finish
    Eclipse imports your project, and it's now visible in your Package Explorer view.


Step 2. Create the ExampleMacro class

Your macro leverages the methods and attributes of the com.atlassian.confluence.macro.Macro interface. Here, you'll build the foundation for your class by implementing Macro.

  1. Open Eclipse.

  2. Locate the com.example.plugins.tutorial.confluence package.
    This is located under src/main/java.

  3. Right-click the package and choose New > Class.

  4. Name your class ExampleMacro.

  5. Ensure the superclass is listed as java.lang.Object.

  6. Add com.atlassian.confluence.macro.Macro to import the Macro interface.
    This interface will enable your macro to examine a Confluence space and determine the qualities of other macros used.

  7. Tick the checkboxes to include Constructors from superclass and Inherited abstract methods. Leave public static void main(String[] args) unchecked.
    The dialogue box should resemble the following:
    New Java Class Eclipse dialogue
  8. Click Finish.
    Eclipse generates stub code for

     See an example of the stub code.

Step 3. Add methods and interfaces to

You've built the stub code for your ExampleMacro class using the Confluence Macro interface. In this step you'll replace some of the stub code to define attributes of your macro.

  1. Open

  2. Add an import statement for XhtmlContent.

    This API method assists with storage content in Confluence. 

  3. Add a constructor for ExampleMacro to take in a value of XhtmlContent.

  4. Modify the getBodyType method to define that your macro's body type is NONE.

    Your macro has no body, so the body type is NONE. There are three available body types for macros: PLAIN_TEXT, RICH_TEXT, and NONE.  

  5. Define the OutputType of your macro as BLOCK.

    Macros in Confluence can be INLINE or BLOCK -formatted. 

  6. Save your changes.

Step 4. Define the execute method for ExampleMacro

The execute method is where the meat of your macro is – it controls what your macro actually does. In this step you'll add more interfaces to your ExampleMacro class, and define the execute method in several steps. Your macro will use MacroDefinition and MacroDefinitionHandler to retrieve and parse the bodies of other macros on a given Confluence page. You'll also add the XhtmlException interface to handle cases when your macro is unable to parse XHTML definitions of other macros. 

The final step for ExampleMacro's execution method is to use Java utilities to assemble the information in a table.

  1. Add the following interfaces to ExampleMacro as import statements. 

  2. Modify the args for the execute method and define how execute() defines a macro body.

    This enables your macro to examine the body of a given Confluence page, convert the data into a String, and return the storage format of the macros so that your macro can display this information.

  3. Define your List of macros as an instantiation of a new ArrayList<MacroDefinition>()

    From this step through step 4.5, place your code inside the closing } bracket for the execute() method.

  4. Add a call to the handleMacroDefinitions method to take body, conversionContext and a new instance of MacroDefinitionHandler, formatted as a try block.  

    This section of your code will use the XhtmlContent utility to parse the XHTML and add each MacroDefinition to a list. Formatting this code in a try/catch block will account for circumstances when your macro encounters a MacroDefinition it isn't able to parse.

  5. Finally, use Java utilities to format the data into a table.

  6. Save and close the file.



 See an example of the complete class.

Here's what the finalized ExampleMacro class should resemble:

Step 5. Modify the atlassian-plugin.xml plugin descriptor

atlassian-plugin.xml describes modules and components to the Atlassian applications – in this case, Confluence. This file bases these dependencies on your pom.xml. The atlassian-plugin.xml file was also generated when you created your plugin skeleton. Here, you'll add an element to reference the ExampleMacro class you built.

  1. Open atlassian-plugin.xml.
    This file should be located under src/main/resources in the Package Explorer view.

  2. Locate the closing tag for </plugin-info>

  3. Add the following code in the line after </plugin-info>. This is a plugin module type. 

    Note that <parameters/> is a blank field. This is because your particular macro doesn't accept input.

     See an example of the complete file.

    Here's what your finished atlassian-plugin.xml file should resemble:


  4. Save and close the file.

  5. From your project root in terminal, tutorial-confluence-macro-demo, update the Eclipse changes to your project. 

    $ atlas-mvn eclipse:eclipse
  6. Refresh your project in Eclipse.

Step 6. Build, install and run the plugin

You've built your macro, but you haven't yet had a chance to interact with it. Now you'll install your plugin and run Confluence, and put your macro to the test.

  1. Open a terminal window and navigate to the plugin root folder. 

    $ cd tutorial-confluence-macro-demo

  2. Start up Confluence from your project root using the atlas-run command.


    This command builds your plugin code, starts a Confluence instance, and installs your plugin. This may take a few minutes.


  3. Locate the URL for Confluence.
    Your terminal outputs the location of your local Confluence instance, usually defaulted to http://localhost:1990/confluence.

    [INFO] confluence started successfully in 71s at http://localhost:1990/confluence
    [INFO] Type CTRL-D to shutdown gracefully
    [INFO] Type CTRL-C to exit
  4. Open your browser and navigate to your local Confluence instance.

  5. Login with adminadmin.

  6. Click Add Page.
    Click Add Page
  7. Choose Demonstration Space and Start with a blank page.

  8. Click Next.
    A blank Confluence page loads. 

  9. Add at least 2 macros to your page. 
    You can add macros by typing a single curly brace ({) and choosing from the suggested list. 
    Alternatively you can click InsertOther Macros to open the macro browser.

  10. Using the macro browser, add your macro titled Tutorial confluence macro demo.
    Insert your macro from the Macro Browser
  11. Save the page.

  12. Confirm your macro displays the names and body statuses of the macros used on the page.
    Finished product
    You can experiment – add, remove, modify your macros, and re-save the page. Confirm your macro stays up to date.


Step 7. Extra credit: Add an icon in the macro browser

When you created the project, two images were automatically downloaded to serve as the logo and icon: pluginIcon.png and pluginLogo.png. These files are located under src/main/resources/images for your project. In this step, you'll add your own custom images to your macro. This image will be shown in the Confluence macro browser:

Macro browser with icon

  1. Locate an image of your liking.

  2. Resize the image to 80 x 80 pixels.

  3. Save the image under src/main/resources/images in a png format.

  4. In atlassian-plugin.xml, add a parameter to specify the location of the icon image using icon="".

  5. Relocate the resource for /images from <web-resource> to directly below the i18n resources.
    Your resources should appear as following:

  6. Save and close the file.

  7. Press Shift + Reload in your running version of Confluence.
    FastDev reloads the changes.

  8. Search for your macro in the macro browser while editing a page.
    Check out your awesome icon!
    Close-up of macro browser icon
 See the entire atlassian-plugin.xml file.




See Preventing XSS issues with macros in Confluence 4.0 for information on how to prevent XSS issues with your macro.

See Making your macro render in Confluence mobile for making your macro compatible with Confluence Mobile.


  1. It's great to see some early info on C4 macros. I understand the focus here is on the new API, but the HTML mixed in with the java still makes me queasy.

    Will there still be a default Velocity context available for creating the output?
    What will be the migration process for current macros that produce wiki markup (including embedding other macros) and simply have that rendered to HTML?


    1. Hi Tim,

      We currently haven't exposed a method for getting a velocity context, however this is on our cards to do so you should be able to use a template rather than mixing html and java (smile)

      As for macros that output wiki-markup, we provide a bunch of commonly used functionality in an interface called XhtmlContent, there is an implementation of this exposed to the plugin system so you should be able to have it autowired into your macro.

      At the moment there is no single call to mirate wiki-markup to a format suitable for rendering in the browser, though you can do the following: convert the wiki-markup to storage format with convertWikiToStorage and then convert that storage format to html output with convertStorageToView.

      Hope this answers your questions.



  2. Anonymous

    Has this been addressed?  Our velocity templates are currently being output with escaped HTML. (sad)

    1. You're probably running into the Anti-XSS features in Confluence. You can read about it here:

      Anti-XSS documentation

      An easy fix is to use a variable ending in HTML in your template. For example, replace:



      #set ($spiffyHTML = $spiffy)


      and it shouldn't have the HTML escaped.

  3. Hi there,

    It looks like the error you're getting is specific to the pi command. Here are a couple suggestions:

    • Restart Confluence and run it with the atlas-run command from your project root
    • Check the UPM (Cog icon > Add-ons > User-installed) and verify your macro plugin appears as enabled and installed. You should see something like this:
      Macro plugin installed in UPM

    If you still have trouble running the plugin, let us know!

  4. Anonymous

    When I try git clone 
    This happens:

    Cloning into 'confluence-macro-tutorial'...
    Permission denied (publickey).
    fatal: Could not read from remote repository.

    Please make sure you have the correct access rights
    and the repository exists.

    And when I download the source code and try to unzip it, it says the zip is corrupted.

    Also when I do the tutorial and copy the example of the complete class to save some time Confluence doesn't want to load it because it has errors o_O.

  5. Hi there,

    I'm sorry to see you're running into issues! The error you're getting looks like an issue with your SSH public key. Are you able to clone any other repositories from Bitbucket? Here's another example to try:

    $ git clone

    If not, it seems that you'll want to resolve the issue with your SSH key first. 

    Good catch on the zipped file! I had accidentally included my target staging directory. I've corrected this issue. You should be able to unzip this file without any errors:

    For your third issue regarding the Java class, could you describe the error Confluence is generating? 

    I hope this helps!




  6. Anonymous

    As a wiki user, Confluence is a great product; however, from a developer persepective, if you want us to develop for your platform..   the instructions are VERY frustrating..   


    Where does it say in the tutorial that we need a public key?

  7. Anonymous

    I've spent well over 2 hours just trying to get my configuration setup in eclipse.   Forget the public key..   there isn't even a mention in the tutorial that we have to install a separate 'atlassian-plugin' for eclipse...   


    VERY frustrating.

  8. Hi there, 

    I've added mention that before starting this tutorial, you should complete Set up the Atlassian Plugin SDK and Build a Project.

    Thanks for finding the bug with the format in the git command. Here's the correct command: 

    $ git clone
  9. Anonymous

    In step 4.2. you've missed the line:

     List<MacroDefinition> macros = new ArrayList<MacroDefinition>(); 

    Which shows when you click the "See an example of the full class" text. 

  10. Anonymous

    Hi there

    When I try to create a macro the module is always disabled in the upm. Do I need an further import?




  11. Hi there,

    When you view the plugin in UPM, are all modules showing as disabled, or just some? Can you clarify if the plugin is enabled, and certain modules are disabled? 

    I think your best bet is to compare the source code for your plugin with the tutorial repository: 

    git clone