Last updatedMay 6, 2019

Write an intermediate blueprint plugin

Applicable:

This tutorial applies to Confluence Server 5.9.1 and higher.

Level of experience:

Intermediate.

In this tutorial, you'll build a plugin that can only be installed on Confluence Server. To create a blueprint for Confluence Cloud, go to Multi-page blueprints with Confluence Connect.

Overview of the tutorial

If you successfully completed Write a simple Confluence blueprint plugin you have a functional but basic blueprint plugin. In this tutorial, you create a blueprint that populates its template with data. You can populate a template by implementing a ContextProvider class in your plugin. You can also populate a template by creating an interactive wizard using JavaScript. In this tutorial, you do both.

Before you begin

Before starting this tutorial, be sure you've completed Write a simple Confluence blueprint plugin tutorial first.

Plugin source

If you want to skip ahead or check your work when you finish, you can find the plugin source code on Atlassian Bitbucket. Alternatively, you can download the source as a ZIP archive. To clone the repository, run the following command:

1
git clone https://bitbucket.org/atlassian_tutorial/confluence-populated-blueprint.git

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 the Atlassian SDK 6.3.10.

Step 1. Add a variable and some instructional text to the template 

In this step, you'll add a variable to the template you created in the Write a simple Confluence blueprint plugin.  If you don't have that code, you can can download the source as a ZIP archive of the project to use.

  1. Open Terminal and navigate to the root of the project.
  2. In the src/main/resources/templates/mytemplate.xml file replace the Enter your name here text with a variable:

    1
    <td><at:var at:name="vName"/></td>
  3. To make it instructional, add a placeholder around the Enter today's date here text.

    1
    <td><ac:placeholder>Enter today's date here</ac:placeholder></td>

    The following code snippet shows the table with the previous example added.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <table>
      <tbody>
        <tr>
          <th>Name</th>
          <th>Date</th>
        </tr>
        <tr>
          <td><at:var at:name="vName"/></td>
          <td><ac:placeholder>Enter today's date here</ac:placeholder></td>
        </tr>
      </tbody>
    </table>
  4. Save and close the file.

Confluence does not support adding <at:var> elements inside of other <at:> namespace elements. For example, an <at:var> inside a macro parameter renders correctly for the end-user creating a page, but an admin subsequently editing the template will not be able to edit the variable as the macro will not render.

 The recommended workaround is to make the entire macro element an <at:var> in the template. To correctly insert XHTML from a variable into the template, you'll need to define the variable with an extra "rawxhtml" attribute, like so:

1
<at:var at:name="myNameWithSomeXhtmlInIt" at:rawxhtml="true"/>

If the at:rawxhtml attribute is not present, the system escapes all XHTML in the attribute value when rendering.

Step 2. Add a new dependency to the pom.xml file

In this step, you'll add new dependencies to your pom.xml file. The confluence-create-content-plugin provides the blueprint API. To interact with the API, you need to add a dependency in your project's pom.xml.

  1. In the pom.xml file in your project's root, add dependency element to the confluence-create-content-plugin artifact. 
    Make sure you added it in the <dependencies/> section.

    1
    2
    3
    4
    5
    6
    <dependency>
       <groupId>com.atlassian.confluence.plugins</groupId>
       <artifactId>confluence-create-content-plugin</artifactId>
       <version>${create.content.version}</version>
       <scope>provided</scope>
    </dependency>
  2. Scroll to file's end and find the <properites/> block.

  3. Add the create-content-version  element.

    1
    <create.content.version>7.0.0</create.content.version>

    Here is example of the whole pom.xml file, including the previous element.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.example.plugins.tutorial.confluence.simplebp</groupId>
        <artifactId>simplebp</artifactId>
        <version>1.0-SNAPSHOT</version>
        <organization>
            <name>Example Company</name>
            <url>http://www.example.com/</url>
        </organization>
        <name>simplebp</name>
        <description>This is the com.example.plugins.tutorial.confluence.simplebp:simplebp plugin for Atlassian Confluence.</description>
        <packaging>atlassian-plugin</packaging>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.atlassian.confluence</groupId>
                <artifactId>confluence</artifactId>
                <version>${confluence.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.atlassian.confluence.plugins</groupId>
                <artifactId>confluence-create-content-plugin</artifactId>
                <version>${create.content.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.atlassian.plugin</groupId>
                <artifactId>atlassian-spring-scanner-annotation</artifactId>
                <version>${atlassian.spring.scanner.version}</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>com.atlassian.plugin</groupId>
                <artifactId>atlassian-spring-scanner-runtime</artifactId>
                <version>${atlassian.spring.scanner.version}</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>javax.inject</groupId>
                <artifactId>javax.inject</artifactId>
                <version>1</version>
                <scope>provided</scope>
            </dependency>
            <!-- WIRED TEST RUNNER DEPENDENCIES -->
            <dependency>
                <groupId>com.atlassian.plugins</groupId>
                <artifactId>atlassian-plugins-osgi-testrunner</artifactId>
                <version>${plugin.testrunner.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>javax.ws.rs</groupId>
                <artifactId>jsr311-api</artifactId>
                <version>1.1.1</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.2.2-atlassian-1</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>com.atlassian.maven.plugins</groupId>
                    <artifactId>maven-confluence-plugin</artifactId>
                    <version>${amps.version}</version>
                    <extensions>true</extensions>
                    <configuration>
                        <productVersion>${confluence.version}</productVersion>
                        <productDataVersion>${confluence.data.version}</productDataVersion>
                        <enableQuickReload>true</enableQuickReload>
                        <enableFastdev>false</enableFastdev>
    
                        <!-- See here for an explanation of default instructions: -->
                        <!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
                        <instructions>
                            <Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>
    
                            <!-- Add package to export here -->
                            <Export-Package>
                                com.example.plugins.tutorial.confluence.simplebp.api,
                            </Export-Package>
    
                            <!-- Add package import here -->
                            <Import-Package>
                                org.springframework.osgi.*;resolution:="optional",
                                org.eclipse.gemini.blueprint.*;resolution:="optional",
                                *
                            </Import-Package>
    
                            <!-- Ensure plugin is spring powered -->
                            <Spring-Context>*</Spring-Context>
                        </instructions>
                    </configuration>
                </plugin>
    
                <plugin>
                    <groupId>com.atlassian.plugin</groupId>
                    <artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
                    <version>${atlassian.spring.scanner.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>atlassian-spring-scanner</goal>
                            </goals>
                            <phase>process-classes</phase>
                        </execution>
                    </executions>
                    <configuration>
                        <scannedDependencies>
                            <dependency>
                                <groupId>com.atlassian.plugin</groupId>
                                <artifactId>atlassian-spring-scanner-external-jar</artifactId>
                            </dependency>
                        </scannedDependencies>
                        <verbose>false</verbose>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <properties>
             <confluence.version>6.7.1</confluence.version>
             <confluence.data.version>6.7.1</confluence.data.version>
             <create.content.version>7.0.0</create.content.version>
             <amps.version>6.3.15</amps.version>
             <plugin.testrunner.version>1.2.3</plugin.testrunner.version>
             <atlassian.spring.scanner.version>1.2.13</atlassian.spring.scanner.version>
             <!-- This key is used to keep the consistency between the key in atlassian-plugin.xml and the key to generate bundle. -->
             <atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
             <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
             <maven.compiler.source>1.8</maven.compiler.source>
             <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
    </project>
  4. Save and close the pom.xml file.

Step 3. Implement a simple ContextProvider

In this step, you create a simple implementation of a com.atlassian.plugin.web.ContextProvider interface by extending the com.atlassian.confluence.plugins.createcontent.api.contextproviders.AbstractBlueprintContextProvider. You can inject any components available to the Confluence plugin system into your ContextProvider.  After you add the provider Java code, you need to specify where it is located for the plugin system. You do this in the content-template module of your atlassian-plugin.xml file.

  1. Create a MyContextProvider.java file in the src/main/java/com/example/plugins/tutorial/confluence/simplebp directory. 
  2. Your class should extend com.atlassian.confluence.plugins.createcontent.api.contextproviders.AbstractBlueprintContextProvider. The AbstractBlueprintContextProvider implements ContextProvider and provides additional Blueprint-specific behaviour.

    1
    2
    3
    4
    5
    6
    7
    8
    package com.example.plugins.tutorial.confluence.simplebp;
    
    import com.atlassian.confluence.plugins.createcontent.api.contextproviders.AbstractBlueprintContextProvider;
    import com.atlassian.confluence.plugins.createcontent.api.contextproviders.BlueprintContext;
    
    public class MyContextProvider extends AbstractBlueprintContextProvider {
    
    }
  3. Override the updateBlueprintContext() method:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package com.example.plugins.tutorial.confluence.simplebp;
    
    import com.atlassian.confluence.plugins.createcontent.api.contextproviders.AbstractBlueprintContextProvider;
    import com.atlassian.confluence.plugins.createcontent.api.contextproviders.BlueprintContext;
    
    public class MyContextProvider extends AbstractBlueprintContextProvider {
        @Override
        protected BlueprintContext updateBlueprintContext(BlueprintContext blueprintContext) {
            blueprintContext.put("vName", "Sherlock");
            return blueprintContext;
        }
    }
  4. Save and close the file.

  5. Open the atlassian-plugin.xml file and find the content-template module. Add a context-provider sub-element.

    1
    2
    3
    4
    <content-template key="simplebp-template" i18n-name-key="my.blueprint.title">
      <resource name="template" type="download" location="/templates/mytemplate.xml" />
      <context-provider class="com.example.plugins.tutorial.confluence.simplebp.MyContextProvider"/>
    </content-template>

    The following code sample shows the full file, including previous sub-element.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    <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>
        <!-- add our i18n resource -->
        <resource type="i18n" name="i18n" location="simplebp"/>
    
        <!-- add our web resources -->
        <web-resource key="simplebp-resources" name="simplebp Web Resources">
            <dependency>com.atlassian.auiplugin:ajs</dependency>
    
            <resource type="download" name="simplebp.css" location="/css/simplebp.css"/>
            <resource type="download" name="simplebp.js" location="/js/simplebp.js"/>
            <resource type="download" name="images/" location="/images"/>
            <context>simplebp</context>
        </web-resource>
    
        <!-- Blueprint -->
        <blueprint key="my-blueprint" content-template-key="simplebp-template" index-key="my-index" i18n-name-key="my.blueprint.name"/>
    
        <!-- Add to the Create Menu -->
        <web-item key="create-by-sample-template" i18n-name-key="my.create-link.title" section="system.create.dialog/content">
            <description key="my.create-link.description" />
            <resource name="icon" type="download" location="/images/myblueprint.png" />
            <param name="blueprintKey" value="my-blueprint" />
         </web-item>
    
        <!-- Template for Blueprint -->
        <content-template key="simplebp-template" i18n-name-key="my.blueprint.title">
            <resource name="template" type="download" location="/templates/mytemplate.xml" />
            <context-provider class="com.example.plugins.tutorial.confluence.simplebp.MyContextProvider"/>
        </content-template>        
    </atlassian-plugin>
  6. Save and close the file.

Step 4. Test your plugin 

At this point, you've added some instructional text, a form field, and a way to fill out the field.  Now is a good point to test your code.

  1. To start a local Confluence instance, run the following command.

    1
    atlas-run

    This command takes a minute or so to run. It builds your plugin code, starts a Confluence instance, and installs your plugin. Once the process completes, you'll see a something similar to the following message:

    1
    2
    3
    [INFO] confluence started successfully in 132s at http://localhost:1990/confluence
    [INFO] Type Ctrl-D to shutdown gracefully
    [INFO] Type Ctrl-C to exit

    You'll see the output includes a URL for the Confluence instance.

  2. Log into the instance as user admin with a password admin.
    The Confluence Dashboard appears.

  3. Click Spaces  > Demonstration Space.
    The system places you in the space home. 
  4. Click Create. The system displays the Create dialog.
  5. Select your blueprint and create a new page.
    You'll see the new page filled with the context and instructional text you defined.
  6. To rebuild your plugin, run the atlas-package command that triggers QuickReload.

Step 5. Add a Soy template and support it with JavaScript

In this example, you write a basic Soy (Closure) template file.  A Soy template file is a way of dynamically building an HTML file and UI. Atlassian Soy is Atlassian's implementation of Google Closure. You'll use the Soy template to write a wizard for your blueprint.  This tutorial doesn't really describe in depth on Soy or Closure; you can learn more about them here. After you describe your wizard in Soy, you should update atlassian-plugin.xml to reference it. Also we add some code to simplebp.js to react on wizard's events.

  1. Add a soy subdirectory to the src/main/resources directory.

  2. Create a file called simplebp.soy in this new directory.

  3. Add the following content to the simplebp.soy file and save it.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    {namespace MyPlugin.Blueprints.Simple}
    /**
    * A form that accepts a person's name
    */ 
    {template .page1Form}
        <form action="#" method="post" class="aui">
          <fieldset>
            <div class="field-group">
                <label for="vname">{getText('my.blueprint.form.label.title.vName')}</label>
                <input id="vname" class="text" type="text" name="vName">
            </div>
          </fieldset>
        </form>
    {/template}

    The template defines a single page, page1Form, that contains a one-field form. You'll reference the namespace value from your JavaScript and later from the atlassian-plugin.xml file. You'll also specify a label value that you need to add to your i18n strings.

  4. In the simplebp.properties file, add the my.blueprint.form.label.title.

    1
    2
    my.blueprint.form.label.title.vName=Name
    my.blueprint.wizard.page1.title=Simplebp WIZARD

    The following code sample shows the entire file, including previous title.

    1
    2
    3
    4
    5
    my.blueprint.title=Sample Template
    my.create-link.title=My Sample Template
    my.create-link.description=Create a new SimpleBB template
    my.blueprint.form.label.title.vName=Name
    my.blueprint.wizard.page1.title=Simplebp WIZARD
  5. Save and close the simplebp.properties file.

  6. In the top of the src/main/resources/js/simplebp.js file in your project, call the setWizard(() JavaScript API:

    1
    Confluence.Blueprint.setWizard('com.example.plugins.tutorial.confluence.simplebp.simplebp:create-by-sample-template', function(wizard) {});

    The setWizard(() method takes the fully qualified pathname to the web-item that creates the blueprint link. The fully qualified pathname uses the following this format:
    ${project.groupId}.${artifactId}:web-item-name.
    Your atlassian-plugin.xml file defines the project's groupId and artifactId values.

  7. Save and close the simplebp.js file.

Step 6. Update the atlassian-plugin.xml file and test

In the previous steps, you added some dependencies to your pom.xml file. You also used a Soy template to specify a Wizard page and wrote a JavaScript file to listen its events. In this step, you'll update the web-resource component in your atlassian-plugin.xml file to access the dependencies. Then you'll modify the content-template module to remove the context-provider element. The user fills in the Name in the wizard. You'll also add a dialog-wizard element to the <blueprint/> module. The dialog-wizard element describes each dialog-page in your wizard. A dialog-page  has three required attributes:

FieldDescription
`id`A unique identifier.
`template-key`A fully-qualified Soy template reference. The template defines the page content.
`i18n-name-key`The i18n key for the page's title.

When you are done updating your atlassian-plugin.xml file, you'll run your plugin and see the Wizard in action.

  1. In the src/main/resources/atlassian-plugin.xml file, find the <web-resource/> module.
    The SDK atlas-create-confluence-plugin command generates this module for you. 
  2. Add a <dependency> element for the confluence-create-content-plugin.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!-- add our web resources -->
    <web-resource key="simplebp-resources" name="simplebp Web Resources">
        <dependency>com.atlassian.auiplugin:ajs</dependency>
        <dependency>com.atlassian.confluence.plugins.confluence-create-content-plugin:resources</dependency>
    
        <resource type="download" name="simplebp.css" location="/css/simplebp.css" />
        <resource type="download" name="simplebp.js" location="/js/simplebp.js" />
        <resource type="download" name="images/" location="/images" />
    
        <context>simplebp</context>
    </web-resource>
  3. Add a <transformation/> module for soy.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- add our web resources -->
    <web-resource key="simplebp-resources" name="simplebp Web Resources">
        <dependency>com.atlassian.auiplugin:ajs</dependency>
        <dependency>com.atlassian.confluence.plugins.confluence-create-content-plugin:resources</dependency>
    
        <transformation extension="soy">
            <transformer key="soyTransformer">
                <functions>com.atlassian.confluence.plugins.soy:soy-core-functions
                </functions>
            </transformer>
        </transformation>
    
        <resource type="download" name="simplebp.css" location="/css/simplebp.css" />
        <resource type="download" name="simplebp.js" location="/js/simplebp.js" />
        <resource type="download" name="images/" location="/images" />
    
        <context>simplebp</context>
    </web-resource>
  4. Right before the /images entry, inside web-resource, add an entry for Soy template.
    When, specifying the name value, add .js to the template name. This notifies the plugin system that your Soy resource transforms to Javascript on the client. Make sure to append .js to the template name. For example, our simplebp.soy should look like simplebp.soy.js.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!-- add our web resources -->
    <web-resource key="simplebp-resources" name="simplebp Web Resources">
        <dependency>com.atlassian.auiplugin:ajs</dependency>
        <dependency>com.atlassian.confluence.plugins.confluence-create-content-plugin:resources</dependency>
    
        <transformation extension="soy">
            <transformer key="soyTransformer">
                <functions>com.atlassian.confluence.plugins.soy:soy-core-functions
                </functions>
            </transformer>
        </transformation>
    
        <resource type="download" name="simplebp.css" location="/css/simplebp.css" />
        <resource type="download" name="simplebp.js" location="/js/simplebp.js" />
        <resource type="download" name="simplebp.soy.js" location="/soy/simplebp.soy" />
        <resource type="download" name="images/" location="/images" />
    
        <context>simplebp</context>
    </web-resource>
  5. To include your resources in create content dialog, inside context tag replace auto generated value simplebp with create-content.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!-- add our web resources -->
    <web-resource key="simplebp-resources" name="simplebp Web Resources">
        <dependency>com.atlassian.auiplugin:ajs</dependency>
        <dependency>com.atlassian.confluence.plugins.confluence-create-content-plugin:resources</dependency>
    
        <transformation extension="soy">
            <transformer key="soyTransformer">
                <functions>com.atlassian.confluence.plugins.soy:soy-core-functions
                </functions>
            </transformer>
        </transformation>
    
        <resource type="download" name="simplebp.css" location="/css/simplebp.css" />
        <resource type="download" name="simplebp.js" location="/js/simplebp.js" />
        <resource type="download" name="simplebp.soy.js" location="/soy/simplebp.soy" />
        <resource type="download" name="images/" location="/images" />
    
        <context>create-content</context>
    </web-resource>
  6. In the <blueprint/> module, define the dialog-wizard. Make sure that template-key points to your Soy template.

    1
    2
    3
    4
    5
    6
    <!-- Blueprint -->
    <blueprint key="my-blueprint" content-template-key="simplebp-template" index-key="my-index" i18n-name-key="my.blueprint.name">
        <dialog-wizard key="simplebp-wizard">
             <dialog-page id="page1Id" template-key="MyPlugin.Blueprints.Simple.page1Form" title-key="my.blueprint.wizard.page1.title" last="true"/>
        </dialog-wizard>
    </blueprint>
  7. Comment out the context-provider where it appears in the content-template module.

    1
    2
    3
    4
    5
    <!-- Template for Blueprint -->
    <content-template key="simplebp-template" i18n-name-key="my.blueprint.title">
        <resource name="template" type="download" location="/templates/mytemplate.xml" />
    <!-- <context-provider class="com.example.plugins.tutorial.confluence.simplebp.MyContextProvider" /> -->
    </content-template>

    The following code snippet shows the full file, including the previous module.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    <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>
        <!-- add our i18n resource -->
        <resource type="i18n" name="i18n" location="simplebp" />
        <!-- add our web resources -->
        <web-resource key="simplebp-resources" name="simplebp Web Resources">
            <dependency>com.atlassian.auiplugin:ajs</dependency>
            <dependency>com.atlassian.confluence.plugins.confluence-create-content-plugin:resources</dependency>
            <transformation extension="soy">
                <transformer key="soyTransformer">
                    <functions>com.atlassian.confluence.plugins.soy:soy-core-functions
                    </functions>
                </transformer>
            </transformation>
            <resource type="download" name="simplebp.css" location="/css/simplebp.css" />
            <resource type="download" name="simplebp.js" location="/js/simplebp.js" />
            <resource type="download" name="simplebp.soy.js" location="/soy/simplebp.soy" />
            <resource type="download" name="images/" location="/images" />
            <context>create-content</context>
        </web-resource>
        <!-- Blueprint -->
        <blueprint key="my-blueprint" content-template-key="simplebp-template" index-key="my-index" i18n-name-key="my.blueprint.name">
            <dialog-wizard key="simplebp-wizard">
                <dialog-page id="page1Id" template-key="MyPlugin.Blueprints.Simple.page1Form" title-key="my.blueprint.wizard.page1.title" last="true"/>
            </dialog-wizard>
        </blueprint>
        <!-- Add to the Create Menu -->
        <web-item key="create-by-sample-template" i18n-name-key="my.create-link.title"
            section="system.create.dialog/content">
            <description key="my.create-link.description" />
            <resource name="icon" type="download" location="/images/myblueprint.png" />
            <param name="blueprintKey" value="my-blueprint" />
        </web-item>
    
        <!-- Template for Blueprint -->
        <content-template key="simplebp-template" i18n-name-key="my.blueprint.title">
            <resource name="template" type="download" location="/templates/mytemplate.xml" />
    <!--         <context-provider -->
    <!--             class="com.example.plugins.tutorial.confluence.simplebp.MyContextProvider" /> -->
        </content-template>
    </atlassian-plugin>
  8. Save and close the atlassian-plugin.xml file.

  9. To rebuild the plugin, run the following command.

    1
    atlas-package
  10. Test your blueprint in Confluence to view your wizard.
     

Step 7.  Add a description to your blueprint

Although the Wizard form is quite simple, a complex or multi-page Wizard can benefit from some explanatory text. In this step, you add description-header-key and a description-content-key to display this explanatory text. 

  1. Edit the atlassian-plugin.xml file.
  2. Add two attributes to the dialog-page element.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <blueprint key="my-blueprint" content-template-key="simplebp-template" index-key="my-index" i18n-name-key="my.blueprint.name">
      ...
      <dialog-wizard key="simplebp-wizard">
        <dialog-page id="page1Id"
                     template-key="MyPlugin.Blueprints.Simple.page1Form"
                     title-key="my.blueprint.wizard.page1.title"
                     description-header-key="my.blueprint.wizard.page1.desc.header"
                     description-content-key="my.blueprint.wizard.page1.desc.content"
                     last="true" />
      </dialog-wizard>
    </blueprint>
  3. Save and close the atlassian-plugin.xml file.

  4. In the simplebp.properties file, add an entry for the description title and content.

    1
    2
    3
    4
    5
    6
    7
    my.blueprint.title=Sample Template
    my.create-link.title=My Sample Template
    my.create-link.description=Create a new SimpleBB template
    my.blueprint.form.label.title.vName=Name
    my.blueprint.wizard.page1.title=Simplebp WIZARD
    my.blueprint.wizard.page1.desc.header=About this blueprint
    my.blueprint.wizard.page1.desc.content=Use this blueprint to create a table with your name and email.
  5. Save and close the simplebp.properties file.

  6. To rebuild your plugin, run the following command, and QuickReload will automatically reinstall it for you.
    1
    atlas-package
     

Step 8. Add validation to your template

Using the setWizard() JavaScript API you can add fuller interaction to your wizard.  For example, you can use this API to validate values entered in a wizard's forms. For validation, you use the submit hook to check the fields on a page.  The submit hook takes the id value of the dialog-page and a state object.   Values from the wizard's form are properties of the state.pageDataobject.  Do the following to validate the entry of the Name field in your wizard:

  1. In the resources/js/simplebp.js file, add the hook to the setWizard(){} body.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Confluence.Blueprint.setWizard('com.example.plugins.tutorial.confluence.simplebp.simplebp:create-by-sample-template', function(wizard) {
         wizard.on('submit.page1Id', function(e, state) {   
             var vName = state.pageData.vName;
             if (!vName){
                 alert('Please provide a name value.');
                 return false;
             }
         });
     });

    This hook checks to make sure the field is not empty.

  2. Save and close the simplebp.js file.

  3. Rebuild your plugin using the following command:
    1
    atlas-package
  4. Test your work.

Next steps

You can continue onto the next tutorial, Write an advanced blueprint plugin to learn how to construct multiple page tutorials and add event listeners.