So you have a cool idea for an Atlassian Connect add-on and, like me, you are still in love with Java. You start looking around to see how you can build one, and you end up landing on the Spring Boot starter app.
It's cool, you can get started developing an add-on in minutes, only by running a single command like this:
mvn archetype:generate -DarchetypeGroupId=com.atlassian.connect -DarchetypeArtifactId=atlassian-connect-spring-boot-archetype -DarchetypeVersion=1.3.0
It gives you a simple project in Spring Boot, which will start in a container and can be installed in Atlassian products. It is perfect, except it makes a big assumption. It assumes that you are going to start from scratch and build your product around the connect framework. Chances are you have a starter application which wires in all the things you decided to have in your stack. I have one of those here.
This project is based on Spring Boot and React.js, has tests in different layers, uses isomorphic views, and uses Bootstrap and LESS for views, so I'm very unlikely to start from scratch. Fortunately, there is a section that talks about modifying an existing project, but since Spring Boot is a little magical, you won't know which bits and pieces you will need to modify in order to "Connectify" your existing application. In this post, I will walk you through some changes I had to apply to my application in order to add Connect capabilities to it.
What Does the Code Look Like?
Here are the changes I had to make, all in one place. Let me walk you through what I had to do.
- Add some dependencies to the Connect library:
- Add Liquibase configuration of Connect library to your existing configuration: Spring Boot starter app for Connect exports the changelog file in a specific path and uses a properties file to configure the path, overriding the default path that Spring Boot uses to locate the .yaml file. You might not need this, but I learned that I had to do this so that Spring Boot can load both my own and Connect's configuration. If you don't use Liquibase, you can exclude it when you are defining the JPA dependency. Otherwise, your tests might fail for not being able to find the schema definition. The Connect library exports the schema definition as db.changelog-master.yaml; make sure your definition file's name doesn't conflict with it.
- Add a Connect descriptor to the project resources. Please note that the 'baseUrl' is a publicly addressable HTTPS endpoint. We'll get to this later.
- Get rid of the main controller, handling root path, since it is already handled in Connect by redirecting to the descriptor.
- Ignore security for the paths that aren't directly related to the add-on, and therefore don't require a JWT token. Connect library configures your Spring Security library to expect a JWT token, which will be provided by the host application your add-on runs in.
Let's Do Something Useful
Up to this point, my add-on doesn't do anything useful. With a few changes, I could make it do something, like adding a new page to JIRA with a link in the navigation bar.
I won't go through that in details, as you can see the changes here. It is pretty much adding a module to the Connect descriptor, saving JWT token in the view, and using it to invoke REST resources.
How Do I Run This Thing?
There are complete instructions in the Connect documentation, but the highlights are as follows.
Start the Application
For my application, the instructions are here and it is as easy as this:
Once it is started, you can check it out at http://localhost:8080 and expect to get the Connect descriptor back.
Assign a Publicly Addressable Secure URL to It
In order to install the add-on on any Atlassian product, it needs to be reachable at a valid HTTPS address. Use a local tunneling tool like ngrok to map a proper URL to your application.
Once you have a proper URL, you can modify your Connect descriptor so it advertises itself properly. Complete instructions on this topic are here.
Install the Add-On
Hopefully, you are familiar with the installation of add-ons in JIRA or Confluence. Otherwise, please check the instructions here. Happy coding!