Download Creating a New Confluence Macro

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Creating a New Confluence Macro
Redirection Notice
This page will redirect to DOCS:Create a Confluence 'Hello World' Macro.
Level of experience
Time estimate
Atlassian application
BEGINNER
1:00
CONFLUENCE 4.X+
On this page:
Tutorial overview
Step 1. Create the plugin project and trim the skeleton
Step 2. Create the ExampleMacro class
Step 3. Add methods and interfaces to ExampleMacro.java
Step 4. Define the execute method for ExampleMacro
Step 5. Modify the atlassian-plugin.xml plugin descriptor
Step 6. Build, install and run the plugin
Step 7. Extra credit: Add an icon in the macro browser
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:
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.10.1 and Atlassian SDK 6.2.6.
2
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
https://bitbucket.org/atlassian_tutorial/confluence-macro-plugin-tutoria
l.git
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:
atlas-create-confluence-plugin
3. When prompted, enter the following information to identify your plugin:
group-id
com.example.plugins.tutorial.confluence
artifact-id
tutorial-confluence-macro-demo
version
1.0-SNAPSHOT
package
com.example.plugins.tutorial.confluence
4. Confirm your entries when prompted with Y or y.
Your terminal notifies you of a successful build:
3
[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]
-----------------------------------------------------------------------
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
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:
4
[INFO]
----------------------------------------------------------------------[INFO] BUILD SUCCESSFUL
[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 interfa
ce. 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.
6.
5
7. Tick the checkboxes to include Constructors from superclass and Inherited abstract methods. Leave
public static void main(String[] args) unchecked.
The dialog box should resemble the following:
8. Click Finish.
Eclipse generates stub code for ExampleMacro.java.
See an example of the stub code.
6
package com.example.plugins.tutorial.confluence;
import java.util.Map;
import
com.atlassian.confluence.content.render.xhtml.ConversionContext;
import com.atlassian.confluence.macro.Macro;
import com.atlassian.confluence.macro.MacroExecutionException;
public class ExampleMacro implements Macro {
public ExampleMacro() {
// TODO Auto-generated constructor stub
}
@Override
public String execute(Map<String, String> arg0, String arg1,
ConversionContext arg2) throws MacroExecutionException {
// TODO Auto-generated method stub
return null;
}
@Override
public BodyType getBodyType() {
// TODO Auto-generated method stub
return null;
}
@Override
public OutputType getOutputType() {
// TODO Auto-generated method stub
return null;
}
}
Step 3. Add methods and interfaces to ExampleMacro.java
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 ExampleMacro.java.
2. Annotate this class with @Scanned
@Scanned
public class ExampleMacro implements Macro{
}
3. Add an import statement for XhtmlContent.
import com.atlassian.confluence.xhtml.api.XhtmlContent;
7
This API method assists with storage content in Confluence.
4. Add a constructor for ExampleMacro to take in a value of XhtmlContent.
private final XhtmlContent xhtmlUtils;
@Autowired
public ExampleMacro(@ComponentImport XhtmlContent xhtmlUtils)
{
this.xhtmlUtils = xhtmlUtils;
}
5. 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: PLA
IN_TEXT, RICH_TEXT, and NONE.
@Override
public BodyType getBodyType()
{
return BodyType.NONE;
}
6. Define the OutputType of your macro as BLOCK.
Macros in Confluence can be INLINE or BLOCK formatted.
@Override
public OutputType getOutputType()
{
return OutputType.BLOCK;
}
7. 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.
8
import java.util.ArrayList;
import java.util.List;
import
com.atlassian.confluence.content.render.xhtml.XhtmlException;
import com.atlassian.confluence.xhtml.api.MacroDefinition;
import com.atlassian.confluence.xhtml.api.MacroDefinitionHandler;
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 Strin
g, and return the storage format of the macros so that your macro can display this information.
@Override
public String execute(Map<String, String> parameters, String
bodyContent, ConversionContext conversionContext) throws
MacroExecutionException
{
String body =
conversionContext.getEntity().getBodyAsString();
}
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.
final List<MacroDefinition> macros = new
ArrayList<MacroDefinition>();
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 MacroDe
finition 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.
try
{
xhtmlUtils.handleMacroDefinitions(body,
conversionContext, new MacroDefinitionHandler()
{
public void handle(MacroDefinition macroDefinition)
{
macros.add(macroDefinition);
}
});
}
catch (XhtmlException e)
{
throw new MacroExecutionException(e);
}
5.
9
5. Finally, use Java utilities to format the data into a table.
StringBuilder builder = new StringBuilder();
builder.append("<p>");
if (!macros.isEmpty())
{
builder.append("<table width=\"50%\">");
builder.append("<tr><th>Macro Name</th><th>Has
Body?</th></tr>");
for (MacroDefinition defn : macros)
{
builder.append("<tr>");
builder.append("<td>").append(defn.getName()).append("</td><td>").a
ppend(defn.hasBody()).append("</td>");
builder.append("</tr>");
}
builder.append("</table>");
}
else
{
builder.append("You've done built yourself a macro!
Nice work.");
}
builder.append("</p>");
return builder.toString();
6. Save and close the file.
See an example of the complete class.
Here's what the finalized ExampleMacro class should resemble:
package com.example.plugins.tutorial.confluence;
import
com.atlassian.confluence.content.render.xhtml.ConversionContext;
import com.atlassian.confluence.content.render.xhtml.XhtmlException;
import com.atlassian.confluence.macro.Macro;
import com.atlassian.confluence.macro.MacroExecutionException;
import com.atlassian.confluence.xhtml.api.MacroDefinition;
import com.atlassian.confluence.xhtml.api.MacroDefinitionHandler;
import com.atlassian.confluence.xhtml.api.XhtmlContent;
import
com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import
com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImpor
t;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
10
@Scanned
public class ExampleMacro implements Macro{
private final XhtmlContent xhtmlUtils;
@Autowired
public ExampleMacro(@ComponentImport XhtmlContent xhtmlUtils) {
this.xhtmlUtils = xhtmlUtils;
}
public String execute(Map<String, String> params, String
bodyContent, ConversionContext conversionContext) throws
MacroExecutionException {
String body =
conversionContext.getEntity().getBodyAsString();
final List<MacroDefinition> macros = new
ArrayList<MacroDefinition>();
try {
xhtmlUtils.handleMacroDefinitions(body,
conversionContext, new MacroDefinitionHandler() {
public void handle(MacroDefinition macroDefinition) {
macros.add(macroDefinition);
}
});
} catch (XhtmlException e) {
throw new MacroExecutionException(e);
}
StringBuilder builder = new StringBuilder();
builder.append("<p>");
if (!macros.isEmpty()) {
builder.append("<table width=\"50%\">");
builder.append("<tr><th>Macro Name</th><th>Has
Body?</th></tr>");
for (MacroDefinition defn : macros) {
builder.append("<tr>");
builder.append("<td>").append(defn.getName()).append("</td><td>").app
end(defn.hasBody()).append("</td>");
builder.append("</tr>");
}
builder.append("</table>");
} else {
builder.append("You've done built yourself a macro! Nice
work.");
}
builder.append("</p>");
return builder.toString();
}
public BodyType getBodyType() {
return BodyType.NONE;
}
public OutputType getOutputType() {
11
return OutputType.BLOCK;
}
}
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.
<xhtml-macro name="tutorial-confluence-macro-demo"
class="com.example.plugins.tutorial.confluence.ExampleMacro"
key="my-macro">
<parameters/>
</xhtml-macro>
See an example of the complete file.
Here's what your finished atlassian-plugin.xml file should resemble:
12
<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>
<xhtml-macro name="tutorial-confluence-macro-demo"
class="com.example.plugins.tutorial.confluence.ExampleMacro"
key="my-macro">
<parameters/>
</xhtml-macro>
<!-- add our i18n resource -->
<resource type="i18n" name="i18n"
location="tutorial-confluence-macro-demo"/>
<!-- add our web resources -->
<web-resource key="tutorial-confluence-macro-demo-resources"
name="tutorial-confluence-macro-demo Web Resources">
<dependency>com.atlassian.auiplugin:ajs</dependency>
<resource type="download"
name="tutorial-confluence-macro-demo.css"
location="/css/tutorial-confluence-macro-demo.css"/>
<resource type="download"
name="tutorial-confluence-macro-demo.js"
location="/js/tutorial-confluence-macro-demo.js"/>
<resource type="download" name="images/"
location="/images"/>
<context>tutorial-confluence-macro-demo</context>
</web-resource>
</atlassian-plugin>
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
13
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.
atlas-run
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:1
990/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 admin / admin.
6. Click Create and follow the prompts to create a new page.
7. 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 Insert > Other Macros to open the macro browser.
8. Next, go to Insert > Other Macros and add your Tutorial confluence macro demo macro.
9. Save the page.
10. Confirm your macro displays the names and body statuses of the other macros used on the page.
You can experiment – add, remove, modify your macros, and re-save the page. Confirm your macro stays
up to date.
14
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: plugi
nIcon.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:
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="".
<xhtml-macro name="tutorial-confluence-macro-demo"
class="com.example.plugins.tutorial.confluence.ExampleMacro"
icon="/download/resources/${project.groupId}.${project.artifactId}/
images/browserLogo.png" key="my-macro">
<parameters/>
</xhtml-macro>
5. Relocate the resource for /images from <web-resource> to directly below the i18n resources.
Your resources should appear as following:
15
<resource type="i18n" name="i18n"
location="tutorial-confluence-macro-demo"/>
<resource type="download" name="images/" location="/images"/>
<!-- add our web resources -->
<web-resource key="tutorial-confluence-macro-demo-resources"
name="tutorial-confluence-macro-demo Web Resources">
<dependency>com.atlassian.auiplugin:ajs</dependency>
<resource type="download"
name="tutorial-confluence-macro-demo.css"
location="/css/tutorial-confluence-macro-demo.css"/>
<resource type="download"
name="tutorial-confluence-macro-demo.js"
location="/js/tutorial-confluence-macro-demo.js"/>
<context>tutorial-confluence-macro-demo</context>
</web-resource>
6. Save and close the file.
7. Rebuild your plugin - QuickReload will automatically reinstall your plugin into the running instance.
8. Search for your macro in the macro browser while editing a page.
Check out your awesome icon!
See the entire atlassian-plugin.xml file.
16
<atlassian-plugin key="${project.groupId}.${project.artifactId}"
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>
<!-- add our i18n resource -->
<resource type="i18n" name="i18n"
location="tutorial-confluence-macro-demo"/>
<resource type="download" name="images/" location="/images"/>
<!-- add our web resources -->
<web-resource key="tutorial-confluence-macro-demo-resources"
name="tutorial-confluence-macro-demo Web Resources">
<dependency>com.atlassian.auiplugin:ajs</dependency>
<resource type="download"
name="tutorial-confluence-macro-demo.css"
location="/css/tutorial-confluence-macro-demo.css"/>
<resource type="download"
name="tutorial-confluence-macro-demo.js"
location="/js/tutorial-confluence-macro-demo.js"/>
<context>tutorial-confluence-macro-demo</context>
</web-resource>
<xhtml-macro name="tutorial-confluence-macro-demo"
class="com.example.plugins.tutorial.confluence.ExampleMacro"
icon="/download/resources/${project.groupId}.${project.artifactId}/im
ages/browserLogo.png" key="my-macro">
<parameters/>
</xhtml-macro>
<!-- import from the product container -->
<component-import key="applicationProperties"
interface="com.atlassian.sal.api.ApplicationProperties" />
</atlassian-plugin>