Awesome ways to use add-ons to build better add-ons

January 12th 2015 Nick Wade in Education, Add-ons

Have you ever considered that the same awesome Atlassian products or applications that allow you to track, build and collaborate can help you as you're developing an add-on?

For example, you have an idea of something that would be useful for either yourself, your users or the community as a whole and, after fleshing it out, you start coding. As you're coding and you start to integrate with the UI, you hit roadblocks figuring out various web-item and web-panel locations. You know you can add a link into a particular place but, for the life of you, you can't figure out the exact code needed.

It used to be that the only way to uncover the locations was to sift through all the documentation. After that, you needed to download the source code of the product and start digging. Note: If you're an add-on developer building for Atlassian Stash then you’ve never felt this pain. That’s because the awesome Stash developers built a way to find the web fragments into the application!

It was during one of these "search party" sessions that I realized that the product itself, via the plugin system, had all of the information I was looking for. Fortunately, I like to write add-ons! So, I wrote an add-on for myself called Web Fragment Finder. The main part of Web Fragment Finder is 3 lines of code:

for (WebItemModuleDescriptor w: this.pluginAccessor.getEnabledModuleDescriptorsByClass(
com.atlassian.plugin.web.descriptors.WebItemModuleDescriptor.class))
{
    ...
}

Using this code we can easily pull out the web-item locations that are used by other add-ons and then do stuff with it. In the case of Web Fragment Finder, we turn around and generate a new add-on that places a web-item in each location and then uploads it back to the host application. Rinse and repeat for web-panels and web-sections.

Web Items and Web Panel locations

The end result? Adding a simple url parameter ?web.items&web.panels&web.sections to the URL shows all of the locations. Rejoice! You no longer have to comb through copious code and documentation to find just what you need.

What else can we get the product to tell us?

Even after I had done this, I found myself heading into the source code to figure out what context I had to hook my CSS and JS to in order to get things rendering properly in a P2 plugin environment. It looked like the cycle was going to start all over again. Then I realized that the plugin system has the info as well. So, back in to the "add-on generating add-on" world of Web Fragment Finder I went. A very similar line of code did the job:

for( WebResourceModuleDescriptor w: this.pluginAccessor.getEnabledModuleDescriptorsByClass(
WebResourceModuleDescriptor.class)) {...}

This time I wasn't quite sure how to display this. I decided that since we already generate a zip file with the atlassian-plugin.xml, we would generate a bunch of JS snippets and add them in there. After that, we just declare them all in the atlassian-plugin.xml attached to the context.

Web resources

What about events? The atlassian-events library is core to most products nowadays with events flying about within the various systems. At some point you'll want to be able see when an event was triggered and the data it contains. By registering a plain object to the event system, you'll actually get all of the events. Using java reflection, we can review all of the attributes of the objects flying about in the event system.

Events triggered in the system

The list of ways you can make the system work for you can go on and on. In some cases you can even find information that you might not have thought of that can make your life easier.

Atlassian Connect Tips

Once I had all of this under my belt, I started to get into more Atlassian Connect development. Finding the right web-item location for the atlassian-connect.json was always easy. However, getting the syntax right was sometimes challenging... especially when I only wanted to write a quick add-on to add a web-panel to a JIRA issue page. We solved this by creating an Atlassian Connect add-on named Customizer for JIRA. It generates static Atlassian Connect add-ons that get installed in your instance. It has an editor interface that allows you to easily reference various attributes available in a web-panel or web-item. It makes for rapid prototyping of Atlassian Connect add-ons possible and helps speed up your time to market for your customers. You can be a connect add-on developer without touching a single line of code!

At first I found debugging rest API calls over HTTPS challenging. I used to spin up WireShark and trace the communication that way. It worked but was slow and cumbersome. So, I took a step back and realized that a servlet-filter could track this information by just grabbing the data and storing in a singleton before it gets harvested into the database. All of a sudden development gets really simple and I'm left with my IDE and the product I'm working on.

HTTP triggered in the system

Giving back to the ecosystem

We add new capabilities to Web Fragment Finder as we discover new needs. And we've made Web Fragment Finder available for free on the Atlassian Marketplace as our way of giving back to the ecosystem. Are there tools you’ve developed in order to make your job easier? Have you poked around on docs.atlassian.com in some of the underlaying libraries (SAL, ActiveObjects, Plugin system etc)?

Explore the APIs of the add-ons and I think you might be surprised at how much information is available to help you. Once you've solved your problem, you might also consider giving back to the ecosystem so we can all write better add-ons.

Happy coding! -Daniel Wester

--