Last updatedMay 12, 2019

Adding licensing support to server apps

Level of experienceBEGINNER
Time estimate0:20
Applicability

Licensing apps for the Marketplace

For demonstration, this tutorial uses Jira Server 7.2.4 but it applies to:

  • Confluence Server 4.1.7+
  • Jira Server 5.0.1+
  • Bamboo 4.0.1+
  • Bitbucket Server 1.1.2+
  • Fisheye/Crucible 2.8+
Ecosystem compatibilityThis tutorial was tested on AMPS 6.2.11 and Atlassian SDK 6.2.14

Tutorial overview

You'll learn how app licensing works in the Universal Plugin Manager (UPM). Without licensing, UPM treats your app as a free app users aren't prompted to purchase or obtain licenses in order to use your app. In order for your app to be profitable, it needs to be licensable. In this tutorial, you'll create a simple app without licensing, and then add a license via the UPM. This tutorial uses Jira to illustrate how licensing works, but the concepts presented are identical across server products.

Concepts covered

  • The Licensing API
  • App licensing for UPM 2.0+

Prerequisite knowledge

Complete the beginner tutorial, Set up the Atlassian Plugin SDK and Build a Project, before starting this one. Specific to this tutorial, we recommend reading through metadata files used by UPM and Marketplace

Step 1. Create the app project

In this step you'll generate stub code for your app. You can ensure you have the latest version of the SDK installed by issuing the command atlas-update and following the installation prompts. 

  1. Open a terminal and navigate to a directory to create an app. 

    1
    cd atlastutorial/
  2. Enter the following command to create a Jira app skeleton:

    1
    atlas-create-jira-plugin
  3. When prompted, enter the following information to identify your app:

    ItemDetails

    group-id

    com.atlassian.tutorial

    artifact-id

    jiraLicensedPlugin

    version

    1.0.0-SNAPSHOT

    package

    com.atlassian.tutorial

  4. Confirm your entries when prompted with Y or y. Your terminal notifies you of a successful build:
    1
    2
    3
    4
    5
    6
    7
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 21.863 s
    [INFO] Finished at: 2016-11-17T15:18:35+10:00
    [INFO] Final Memory: 22M/314M
    [INFO] ------------------------------------------------------------------------
  5. Change to the jiraLicensedPlugin directory created by the previous step.

    1
    cd jiraLicensedPlugin/

Step 2. Start up your host product

In this step, you'll start up a product instance to see your app in the UPM. Since you haven't added any licensing capabilities, UPM treats your app as a free extension customers can use it, but aren't prompted to purchase a license. In these steps, we use Jira 6.0 here, but you can use any product that supports UPM 2.0+. 

  1. Ensure you're in your app directory. If you followed the steps above exactly, your directory should be jiraLicensedPlugin.
  2. Run the following command to start up Jira with the app installed:

    1
    2
    3
    ``` bash
    atlas-run
    ```

    In your terminal, Jira's URL will be shown when it has finished starting up the first time this may take a few minutes as all the files need to be downloaded.

    1
    2
    3
    4
    5
    ``` bash
    [INFO] jira started successfully in 82s at http://localhost:2990/jira
    [INFO] Type Ctrl-D to shutdown gracefully
    [INFO] Type Ctrl-C to exit
    ```    

    Keep this Jira instance running for the rest of this tutorial.

  3. In your web browser, navigate to your Jira instance, usually at http://localhost:2990/jira.

  4. Log in with the credentials admin/admin.
  5. Navigate to the Universal Plugin Manager page where you can manage your apps: http://localhost:2990/jira/plugins/servlet/upm.
  6. Verify you can see your app listed in UPM. There's no label for Licensing because you have only created an unlicensed app so far. You'll add licensing in the next step.

Step 3. Make your app licensable

Your app hasn't conveyed to the product that it should have a license, let alone provided an ability to accept licenses. Here, we'll add a dependency in your pom.xml file to both the UPM API and the licensing API. Then, you'll declare your app as licensable in your descriptor file.

  1. Add the following dependencies to the dependencies element inside pom.xml:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <dependency>
        <groupId>com.atlassian.upm</groupId>
        <artifactId>licensing-api</artifactId>
        <version>2.21.4</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.atlassian.upm</groupId>
        <artifactId>upm-api</artifactId>
        <version>2.21</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>provided</scope>
    </dependency>
  2. Add the following parameter to the plugin-info element in /src/main/resources/atlassian-plugin.xml:

    1
    <param name="atlassian-licensing-enabled">true</param>
  3. Run atlas-mvn package in the project home directory to repackage the app. QuickReload will then reload the app.

  4. Refresh the UPM page. Verify you see two big changes: a License details field, and a License key input box.

Step 4. Use PluginLicenseManager to access licensing information

You can use PluginLicenseManager to access licensing information within your plugin. In the following, we create a servlet that replies with the currently registered license (if there is one).

  1. In atlassian-plugin.xml, add the following servlet declaration:

    1
    2
    3
    4
    <servlet name="License Servlet" class="com.atlassian.tutorial.LicenseServlet" key="license-servlet">
        <description>Servlet which serves the raw license string</description>
        <url-pattern>/my/license</url-pattern>
    </servlet>
  2. Add the class com.atlassian.tutorial.LicenseServlet and put the following code in it:

    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
    ``` java
    package com.atlassian.tutorial;
    
    import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
    import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
    import com.atlassian.upm.api.license.PluginLicenseManager;
    
    import javax.inject.Inject;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    @Scanned
    public class LicenseServlet extends HttpServlet {
        @ComponentImport
        private final PluginLicenseManager pluginLicenseManager;
    
        @Inject
        public LicenseServlet(PluginLicenseManager pluginLicenseManager) {
            this.pluginLicenseManager = pluginLicenseManager;
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            PrintWriter w = resp.getWriter();
            if (pluginLicenseManager.getLicense().isDefined()) {
                w.println(pluginLicenseManager.getLicense().get().getRawLicense());
            } else {
                w.println("License missing!");
            }
            w.close();
        }
    }
    ```

    We constructor-inject an instance of PluginLicenseManager into the servlet and use it to return the license string in response to GET requests.

  3. Run atlas-mvn package to reload the app.

For further details about the PluginLicenseManager, see License API for server apps.

Step 5. Add a license key and verify it all works

Here you'll verify that everything is wired properly. You'll input a test license to check that UPM responds the way it should to your app.

  1. Issue a GET request to our servlet with URL http://localhost:2990/jira/plugins/servlet/my/license. It should say "License missing!" since we haven't entered a license yet.
  2. Enter the following into the License key field for our app on the UPM page:

    1
    2
    3
    4
    5
    6
    AAABEA0ODAoPeNp9UE1Pg0AUvO+v2MSbCc0uQZOS7KEIUWMtpNJqGi9bfKUb4S3ZD7T/XgrqwYPv9
    mbezGTeRXn0NK8cZRHlPGZRHEW0SEsaMh6SFGxlVOeURlGCdbRRFaAFetCGdo2vFdI36KHRHRhLV
    r7dg8kPGztsgjNyY0Cexal0IELOw4DNA85J1svGj4xwxgOZrOzsciYrp3qY0Eep0AFKrCD77JQ5j
    TapN6PyNb5mw5Dc1BKVndwWrpHWKonkCUwP5j4Vye28DF422yh42O3ugoTxZ7KcagzsBt9Rf+AP8
    k/O90V56mAl24HPttkyL7L1b+1Etnut19BqB4sa0FkRXpHCm+ooLfz9wRfgrX9WMCwCFAkWHvhJC
    dutS3LcZ46iYgICDPQqAhQL76vdT4AYTQXBwl/wbw/MtQrP4w==X02dt

    This is a 60-second license key.

  3. Click Update. If accepted, you should see a lozenge and a banner appear to notify you that your app license expires soon.

  4. Issue another GET request to our sevlet, http://localhost:2990/jira/plugins/servlet/my/license, and you should see the license we entered.
  5. Test other license states using Timebomb licenses for testing

If you run out of licenses, you can shut down your Jira instance using CTRL+D in your terminal; and then running atlas-mvn clean to remove your target staging directory.