I, the Atlassian add-on
Once upon a time, a friend of mine has told me a story of a young tester and alternative ways of viewing the problem.
A team lead has just introduced the tester to the agile terms and assigned the fellow to describe the stories for their backlog. Of course, examples of the stories have been provided: “As a system administrator, I would like to …”, “As a user, I need to …” and so forth. Imagine the surprise of the team, when they glanced at a newly described story:
Naïve, as it is, a story written thus, may not be the best description of a problem to be solved, but it makes one to think of the application as a living being and may serve as a nice introduction to its inner world.
I, the Atlassian add-on
My whole universe revolves around the Atlassian product platform:
- Confluence – the place, where ideas get discussed, insights are shared and meetings get carved into. A social network for a company.
- Jira – issue tracking, the home for developers, testers, support staff and overall for the people who create/maintain products.
- Stash – a code hub, where the program code gets stored, shared and discussed. A stand-alone code repository
- Bamboo – an automated task executing service. Designed to perform Continuous Integration.
- and many, many more: Bitbucket, Sourcetree, Hipchat, etc.
Each of those programs, are like planets: similar in the physics (some shared API’s, alike API structure, testing options), though somewhat different, when it comes to living there (class paths in the applications are different, thus supplying developers with different provided libraries, persistence library ActiveObjects in Confluence can provide read-only entities, while Jira ActiveObjects has problems with that and so on).
People need me when, for instance, one feels that ones Jira misses some convenience – one needs to store some additional information to a task, which should get presented as a chart or as a grid, one wishes to search for issues with some special content, or plainly wants some reports to be displayed, when one gets in.
I, the Atlassian add-on, am what makes a Jira issue tracker to be a time-tracking helper, a test use-case database, a living product development strategy overview. I can turn Confluence into a blog site, or an HR manager knowledge-base, with custom preset candidate review pages and LinkedIn splashes.
Earthly vs. Aerial
Most of the Atlassian products come in two distinct flavours: on-premise and on-demand (server and cloud, respectively). As far, as an add-on may be concerned, they are different.
- Server product add-ons can dwell inside the product, can alter it almost completely (via the extensive API and SPI not to mention dirty hacks such as java class-loader exploits, and private property access with reflection).
- Cloud product add-ons are separate applications. They are authorised to interact with the product realm, but they are tightly constrained by the provided API.
As I continue my story, I wish not to capture all the corners of my world. I would merely like to highlight the path of one plugin type and to warn of hardships.
How to get started
Atlassian is a company, which invests in developers: the add-on sdk (the most extensive of all, I’ve seen), own Q&A site, sample libraries as well as additional developer tools (add-ons, which allow to view the database contents, the home directory of the application; and lots of others), online documentation, design principles and user experience guidelines and, as the last resort annual events, where a developer has ability to interact with Atlassians directly.
I, the server add-on
I come into existence as a Java program. An OSGI plugin with Spring descriptor file at core.
The place of origin is the add-on sdk (although it is possible to create an add-on without it, it is very uncommon to meet such), which in a nutshell is a pre-configured maven installation with special plugins that do the most of the magic. Developer uses maven commands to run those plugin goals:
- create the add-on structure;
- create an add-on component;
- start (and debug) the product, with the add-on installed;
- run integration tests for the product with the add-on installed;
- and more.
My essence lies in plugin-modules, which are declared in the add-on descriptor file. The modules are the product extension points, being used (SPI’s and services). Basically, plugin-modules are either Java Classes or assets or plain configurations.
For a server application I may (I can have modules, that allow me to):
- declare services, available for other add-ons to use (and use the services, provided by the other add-ons)
- install web application server components (Java EE servlet context listeners, servlets, servlet filters)
- extend the user interface at provided locations (application-level menus, menu items, administrative pages, etc.)
- register REST endpoints
- state the own domain Entities to be stored via Atlassian’s ActiveObjects library
- product event listeners
- front-end assets and i18n resources
- define product Entity types:
My creator decides on the services, I will provide. It is common for a dev to try to use some libraries, not available in the Atlassian product. And it is common to see me swollen with all the tools the programmer wants me to wield.
There are times, when the product refuses me to have some lib:
- guava library has dramatical API changes between versions, and different JIRA versions have different guavas, which makes it harder for a plugin developer to support all the range
- fugue library can not be bundled with another version
- hibernate of version less than 4 is not able to live with the drivers, provided by Jira
- the wired test classpath relies on the Atlassian testrunner add-on’s classpath, thus having the hamcrest library not being able to be bumped higher than 1.1 (say “goodbye” to libraries, using the normal hamcrest)
I live, while the product application runs, and the add-on infrastructure has me enabled.
Enabling me means:
- to load my classpath:
- to load the classpath with the classes, available in my .jar file (my .jar contents)
- to load the classpath with the classes from the libraries, I bundle (the .jar’s inside my .jar)
- to load the packages, imported from the product or the other add-ons
- to instantiate my services (and to inject their dependencies)
- to run all the constructors and spring lifecycle methods
- to run the post-instantiate activities of the add-on lifecycle
When I get installed into a product, the add-on system converts my add-on descriptor file into Spring .xml configuration file (to define the services exported and imported), OSGI manifest (to define the classpath).
It is common for me to refuse starting up, just throwing a:
- for OSGI problems:
- BundleException when a package is not exported by any of add-ons (and nor the product system)
- NoClassDefFoundError, ClassNotFoundException or NoSuchMethodException when something is wrong with the OSGI manifest (the classes, available at compile time are not present at the runtime). Normally it is when my creator did not explicitly include the packages, used in my code in my add-on instructions
- LinkageError when a class is already present on the system classpath, and I bring another one with me
- for Spring troubles:
- BeanCreationException when Spring is unable to resolve dependencies for one of the add-on services
- for REST Resource problems:
- responses of 404
There are quite a lot of tools to help a developer to overcome each of them:
- for OSGI problems:
- one can view my effective OSGI configuration (as well as the packages available at the runtime) through the OSGI browser add-on
- one can remove the OSGI instructions for the add-on, and inspect the maven console output, which would log the configuration, automatically generated by the Atlassian maven plugin
- for REST resource not being accessible, one may inspect the REST API browser, which lists all the resources, the product finds at its runtime. More than that, each time one accesses the REST API browser, all the add-on REST endpoints get re-instantiated, which allows one to debug into the constructors or even to the Atlassian-rest-plugin, which performs the instantiation
As I live on, I need to evolve for people still to love me.
There are a couple of tips as to what can be done to ease the process of my maturing:
- Write as many logs, as possible at all the business-logic methods. By default, the products get the logging for the add-ons disabled. But whenever it is needed, an administrator may turn on logging for a particular package. Thus, the production would not get hurt, but the customer support team would appreciate it very much. Let me talk.
- Cover the functionality with unit tests extensively. Use integration tests: wired (or/and UI) to cover the product API / SPI usages. Do not overuse the integration tests – cover as much as possible with the unit tests.
- Support the latest and the best. As the new Atlassian product users appear, they tend to install simply what Atlassian provides by default – the latest version of the product. The more new users see your add-on compatible with their new Jira, the better. Start preparing the add-on, once that Atlassian publishes a new EAP release.
- test feature-wise – as Atlassian describes the changes to be included into the next release, you may turn them into the compatibility checklist, by comparing the Atlassian product’s new features with the list of integrations (the contents of the add-on descriptor file)
- If a data model is to be changed, make sure, no data is lost on the end user productions, and the old-formatted entries can still be used in my new version
- Eat your own dogfood – try to use me as the part of own production installation.
I, the add-on can never die. In one or the other form, I come again. As long as there are people, who want to get more from their issue trackers, wiki sites or development toolkits, the add-ons will arise. Fun fact: most of the Atlassian product features, starting with the introduction of the plugin framework 2 are add-ons themselves.
Change often, my wee lad. Try to adapt to the people’s needs. After all, what is an add-on as not an improvement over a platform?
If you would like to see a particular feature implemented with your JIRA or Confluence profile, it may be possible to develop it as plugin. We would be happy to implement these and other required functionality for you. Please feel free to contact us.
Author: Serhiy Onyshchenko