Creating a Template Bundle

Applicable:

This tutorial applies to Confluence 3.2 - Confluence 4.3

(As of Confluence 5.0 plugin developers can bundle templates as part of their add-ons. See Preparing for Confluence 5.0 for details)

Level of experience:

Intermediate. Our tutorials are classified as 'beginner', 'intermediate' and 'advanced'. This one is at 'intermediate' level. If you have never developed a plugin before, you may find this one a bit difficult.

Status: LEGACY This tutorial applies to Confluence versions that have reached end of life.

A template is a pre-defined page that can be used as a prototype when creating new pages. Templates are useful for giving pages a common style or format. Templates are written in regular Confluence wiki markup, using special markup to define form fields that need to be filled in. A template bundle is essentially a collection of templates packaged up into a plugin.

The templates framework plugin bundled with Confluence 3.2 allows custom template bundles to be deployed to a Confluence instance by creating a standard Atlassian Plugin that depends on the templates framework. Once you have created and deployed a custom template bundle to a Confluence instance, you will be able to import the templates to use globally or within specific spaces.

On this page:

Required Knowledge

If you are unfamiliar with plugin development, we recommend that you read the guide to developing with the Atlassian Plugin SDK before you read this document. You may also want to read Common Coding Tasks for an overview of the plugin framework. Some experience with Maven is assumed for plugin development. If you haven't used Maven before, you may want to read the Maven documentation to familiarise yourself with it.

Creating a Template Bundle

1. Archetype Your Plugin

Create a new plugin confluence plugin with the atlas-create-confluence-plugin command. We will define this plugin as a dependency of the templates framework. The functionality it will provide is an implementation of the TemplatePackage interface which provides a java.util.List<PageTemplate> to the framework.

Incorrect Confluence version in plugin archetype

If you are not using the latest Atlassian Plugin Development Kit, your plugin archetype may be created with an incorrect Confluence version. Please check your pom.xml and update the product (Confluence) version to 3.2 or later, or update your PDK to the latest version and create a new plugin archetype.

The implementation of how your plugins are stored are completely up to you, the example at the end of this page uses an XML file and JAXB.

2. Define The Dependencies

We have to add both the maven dependency to your pom.xml and a component in the atlassian-plugin.xml file.

  • Add this dependency to your pom.xmlfile for the plugin:

    <dependency>
        <groupId>com.atlassian.confluence.plugins</groupId>
        <artifactId>templates-framework</artifactId>
        <version>0.4</version>
        <scope>provided</scope>
    </dependency>
    
  • Define this component in your atlassian-plugins.xmlfile:

    <component name="Templates: Default Package" key="templates" public="true"
            class="com.atlassian.confluence.plugin.templates.packages.DefaultTemplatesPackage">
        <interface>com.atlassian.confluence.plugin.templates.export.TemplatePackage</interface>
    </component>
    

In this example the com.atlassian.confluence.plugin.templates.packages.DefaultTemplatesPackage class is our plugin implementation, change this to your plugin class. The <interface>com.atlassian.confluence.plugin.templates.export.TemplatePackage</interface> line should not be changed as this is the dependency the Atlassian Plugins Framework uses to register your plugin with the templates framework.

3. Implement The Interface

For the plugin to function as a templates bundle, we must implement the TemplatePackage interface that is exported by the templates framework. This allows the plugin to provide a list of templates to the framework.

The interface defines two methods:

List<PageTemplate> getAvailableTemplates() throws TemplatePackageException;

and

String getPackageName();

The getAvailableTemplates() method will provide the template data to the framework in the form of PageTemplate instances. When you instantiate these instances you should set the following members of the instance with your template data:

  • name - not null
  • content - not null
  • description
  • labels

The order of the returned list is not important, as this list will be sorted by the template name before it is rendered.

4. Install The Template Bundle

The template bundle should be installed as a normal plugin, the Atlassian Plugins Framework will take care of registering it with the templates framework. After it is installed, the template bundle will be available under the Import Templates administration menu item (see Importing Templates).

Example Code

The example provided here is only applicable to the DefaultTemplatesPackage that is bundled with Confluence 3.2. This plugin stores the templates as an XML file and uses JAXB to load in the file.

The code samples below are intended to be used as references only, as there are a number of ways that template bundles can be built.

Screenshot: Example directory structure for template bundle

(tick) Click to expand any code sample below.

Framework Interface - TemplatePackage.java
package com.atlassian.confluence.plugin.templates.export;

import com.atlassian.confluence.pages.templates.PageTemplate;

import java.util.List;

public interface TemplatePackage {
    /**
     * Return a collection of the available templates offered by this plugin.
     * @return A {@link java.util.List} of {@link com.atlassian.confluence.pages.templates.PageTemplate}s.
     * @throws TemplatePackageException If an exception occurs.
     */
    List<PageTemplate> getAvailableTemplates() throws TemplatePackageException;

    /**
     * Returns the name for this template package
     *
     * @return The name of this package.
     */
    String getPackageName();
}
Example Implementation - DefaultTemplatesPackage.java
package com.atlassian.confluence.plugin.templates.packages;

import com.atlassian.confluence.pages.templates.PageTemplate;
import com.atlassian.confluence.plugin.templates.export.TemplatePackage;
import com.atlassian.confluence.plugin.templates.export.TemplatePackageException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class DefaultTemplatesPackage implements TemplatePackage {
    private static final Logger log = LoggerFactory.getLogger(DefaultTemplatesPackage.class);

    private static final String TEMPLATES_FILE = "templates.xml";
    private static final String NAME = "Default Templates Package";

    public DefaultTemplatesPackage() {}

    public List<PageTemplate> getAvailableTemplates() throws TemplatePackageException {
        Templates templatesXml;
        try {
            JAXBContext ctx = JAXBContext.newInstance("com.atlassian.confluence.plugin.templates.packages", getClass().getClassLoader());
            InputStream resourceStream = getClass().getClassLoader().getResourceAsStream(TEMPLATES_FILE);
            templatesXml = (Templates) ctx.createUnmarshaller().unmarshal(resourceStream);
        }
        catch(JAXBException e) {
            throw new TemplatePackageException("Unable to unmarsal xml", e);
        }
        List<PageTemplate> templates = new ArrayList<PageTemplate>();
        for(Templates.Template t : templatesXml.getTemplate()) {
            PageTemplate pTemplate = new PageTemplate();
            pTemplate.setName(t.getName());
            pTemplate.setContent(t.getContent());
            pTemplate.setDescription(t.getDescription());
            pTemplate.setLabels(t.getLabels());
            if(log.isDebugEnabled()) {
                log.debug("Loading Template: " + t.getName());
            }
            templates.add(pTemplate);
        }
        return templates;
    }

    public String getPackageName() {
        return NAME;
    }
}
JAXB XSD Schema
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:annotation>
        <xsd:documentation xml:lang="en">
            Schema for the PageTemplate
        </xsd:documentation>
    </xsd:annotation>

    <xsd:element name="templates">
        <xsd:complexType>
            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
                <xsd:element name="template">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="name" type="xsd:string"/>
                            <xsd:element name="description" type="xsd:string"/>
                            <xsd:element name="content" type="xsd:string"/>
                            <xsd:element name="labels" type="xsd:string"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
Maven2 changes for XSD generation
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>xjc</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <packageName>com.atlassian.confluence.plugin.templates.packages</packageName>
    </configuration>
</plugin>
Example templates.xml data
<templates>

    <template>
        <name>Charts</name>
        <description></description>
        <content>
            <![CDATA[
{tip:title=How to use this template}
* Display tables of data as charts on Confluence pages
* Edit these charts by placing your cursor inside any of the chart macros on this page and click on the _Insert/Edit Macro_ icon in the toolbar
{tip}
h3. Pie Chart

{chart:title=Estimated Hours Per Feature|xLabel=Time (in hours)|yLabel=Feature|3D=true|width=500|dataOrientation=vertical}

|| Feature || Hours to complete ||
| autocomplete | 45 |
| bundled themes | 60 |
| JIRA Query Language | 120 |
| Cross-Browser Support | 60 |
{chart}

h3. Bar Chart

{chart:type=bar|title=Estimated Hours Per Feature|xLabel=Time (in hours)|yLabel=Feature|3D=true|width=500|dataOrientation=vertical}

|| Feature || Hours to complete ||
| autocomplete | 45 |
| bundled themes | 60 |
| JIRA Query Language | 120 |
| Cross-Browser Support | 60 |
{chart}

h3. Line Chart

{chart:type=line|title=Estimated Hours Per Feature|xLabel=Time (in hours)|yLabel=Feature|width=500|dataOrientation=vertical}

|| Feature || Hours to complete ||
| autocomplete | 45 |
| bundled themes | 60 |
| JIRA Query Language | 120 |
| Cross-Browser Support | 60 |
{chart}             
            ]]>
        </content>
        <labels></labels>
    </template>

    <template>
        <name>Document List</name>
        <description></description>
        <content>
            <![CDATA[
{tip:title=How to use this template}
* Add an attachment, such as a Word document, to this page and see it displayed below
* It's a great way to share documents and files with other users as they can view the attached files by clicking the view link.
{tip}

{panel}

h3. Documents
{attachments:upload=true}
\\
{panel}
            ]]>
        </content>
        <labels></labels>
    </template>
    
    <template>
        <name>Meeting Notes</name>
        <description></description>
        <content>
            <![CDATA[
{tip:title=Use Confluence to take notes during your meetings}
Create a new meeting notes page using this template. Keep track of who attended, what has been discussed during the meeting and what needs to be acted upon.{tip}

h2. Date: {color:#3c78b5}24.4.2009{color}

h2. Attendees

* Joe Black
* John Doe
* &nbsp;

h2. Status of Action Items from Last Week

* Scope out site for offsite (Joe)
* Get three customer testimonials (John)
* &nbsp;

h2. Meeting Agenda

* Review status last week's action items
* Set action items for next week
* &nbsp;

h2. Action Items for Next Week

{tasklist}
Prepare release blog-post
Buy cheese and wine for offsite
{tasklist} 
            ]]>
        </content>
        <labels></labels>
    </template>
</templates>
Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport