ga-idea

I recently started building Confluence plugins. The first one being my Google Analytics plugin for Confluence. This post outlines my "journey" into Confluence plugin development. It documents a beginner's pitfalls when developing with the Atlassian Plugin SDK. Hopefully others can learn from, or at least laugh at my mistakes.

Where I was starting from:

  • No experience of maven
  • No understanding of how Confluence plugins work or how they are written
  • Some experience of Java - Mainly uPortal/Luminis portal development for the University of Nottingham and some consultancy work e.g. for Astra Zeneca, Documentum and 3Com
  • No experience of unit testing or integration testing in Java - oh dear
  • I prefer UI work to real programming

Initial failure

I tried to setup a development environment for plugin development using Atlassian's documentation a little before the beta release of version 3 of the Atlassian Plugin SDK. It was a pain. This was no fault of the documentation — it was really just to do with my schedules and available time to experiment.

The problem was two-fold:

  1. I'd not done this before, so was clueless to what was involved
  2. The setup was a complete ball-ache considering the time restraints

I was well aware of point 1 and the pain it was likely to cause. Point 2 seemed to be the old chestnut - install and configure the exact correct versions of the software you need in the correct sequence, then start.

Wait. I don't know what that means, see point 1. Yes, I've got maven installed on my MacBook! Woo! Let's go. Hang on, it's not the correct version. Where do I get that from?

In many ways, it reminded me of my initial experience of building and installing Apache 1.x on Solaris SPARC boxes back in the day:

cd /path/to/apache/source; make; make install;
Oh. Wrong version of make. Where do I get that from? Hmmm.
Install correct version of make. Damn, make needs the correct version of gcc. Where do I get that from?
And so on. Moving further and further away from the problem you're trying to solve.

So, I stopped there. No shiny Confluence plugins for me. I've got plenty of other things to do anyway thank you very much.

Reboot

Then Atlassian released the Plugin SDK beta and all this nastiness was removed. Everything you need to build an Atlassian plugin was bundled in one place. Refreshing. All commands have been wrapped and so are prefixed with atlas- to prevent conflict with whatever else you've got installed.

For the impatient, this really drives down the barriers to entry for plugin development.

Following the documentation for installing the Plugin SDK was a piece of cake. It just worked.

  • Download
  • Unzip
  • Add some environment settings. Edit ~/.profile and add:
    
    PATH=$PATH:.
    PATH=$PATH:$HOME/
    PATH=$PATH:$HOME/bin
    PATH=$PATH:$HOME/atlassian-plugin-sdk/atlassian-plugin-sdk-3.0-beta3
    PATH=$PATH:$HOME/atlassian-plugin-sdk/atlassian-plugin-sdk-3.0-beta3/bin
    export PATH
  • Start building a plugin

Starting out to build your Atlassian plugin is documented here. It's a fairly straightforward set of instructions.

You start by doing something like this:


mkdir ~/projects/davidsimpson.me/
mkdir ~/projects/davidsimpson.me/confluence
cd ~/projects/davidsimpson.me/confluence

atlas-create-confluence-plugin
...
...
...
When prompted
Define value for groupId: : me.davdsimpson.confluence.plugins
Define value for artifactId: : googleanalytics
Define value for version: 1.0-SNAPSHOT: :
Define value for package: me.davdsimpson.confluence.plugins: :
Confirm properties configuration:
groupId: me.davdsimpson.confluence.plugins
artifactId: googleanalytics
version: 1.0-SNAPSHOT
package: me.davdsimpson.confluence.plugins

Then type...

cd googleanalytics
atlas-run

...and sit back. If maven doesn't fall over for lack of memory at this point, you're laughing. Go away, have a beer or two. This may take some time.

Beer

On your return, maven will hopefully have finished dragging all manner of nonsense from Australia and installed a working copy of Confluence, together with an empty plugin onto your computer. Nice. Next, write some code.

I like to run before I can walk. It seems like much more fun to attempt something that's harder. You do fall over a lot more often though. So rather than some kind of silly little hello world or equivalent plugin, my first plugin was an integration of Google Analytics with Confluence using the Google Analytics API to fetch data from Google. It requires some additional JARs from Google.

Google doesn't have a public maven repository to my knowledge and I'd no idea how to get these JARs added into maven. Luckily, people had already written about parts of this, so I put 2 and 2 together.

Add Google Analytics JARs to maven:


atlas-mvn install:install-file -DgroupId=com.google.gdata
-DartifactId=gdata-core
-Dversion=1.0
-Dpackaging=jar
-Dfile=/path/to/gdata-core-1.0.jar
-DgeneratePom=true

atlas-mvn install:install-file -DgroupId=com.google.gdata
-DartifactId=gdata-analytics
-Dversion=2.0
-Dpackaging=jar
-Dfile=/path/to/gdata-analytics-2.0.jar
-DgeneratePom=true

atlas-mvn install:install-file -DgroupId=com.google.collect
-DartifactId=google-collect
-Dversion=1.0
-Dpackaging=jar
-Dfile=/path/to/google-collect-1.0-rc3.jar

Edit the Project Object Model (POM) to add the dependencies

Edit the pom:

vi ~/projects/davidsimpson.me/confluence/googleanalytics/pom.xml

Add this bit to the end of the dependencies node:


<!-- Add Google Analytics dependencies: -->

com.google.gdata
gdata-core
1.0

com.google.gdata
gdata-analytics
2.0

com.google.collect
google-collect
1.0

Next, fire up your IDE

My chosen IDE is IntelliJ IDEA.

  • Open the pom.xml in IntelliJ IDEA (File | Open project)
  • Override/set the maven home directory: /Users/davidsimpson/atlassian-plugin-sdk-3.0-beta3/apache-maven
  • Set the JDK for build as 1.5 or 1.6
  • Start editing the plugin

Hiccups

It's not all straightforward. Here's some of the annoyances that I came across.

Maven needs more memory

I needed more memory for maven. Not really a problem - append to ~/.profile:


export MAVEN_OPTS=-Xmx512m

Annoying warnings on atlas-run

I noticed this on running atlas-run - it probably shouldn't be there:

[WARNING] Using platform encoding (MacRoman actually) to copy filtered resources, i.e. build is platform dependent!

Of course, someone has already blogged about it — Red Leopard — and it's easily fixed by editing the POM to add the correct encoding.


3.0.2
3.0

<!-- Fix for MacRoman warnings on build -->
UTF-8
UTF-8

Now, we have no nasty warnings.

The macro browser icon

I love the Macro Browser in Confluence. It's a nice step forward in the evolution of the UI. So as a result, I wanted my macro to have a shiny icon in the macro browser. That damn Macro Browser icon ate up several hours of my life. Looking at the comments on the documentation page, several other people have had a whole load of fun getting their pretty icon to show up too.

[caption id="attachment_521" align="alignnone" width="440" caption="The macro browser icon: What we"]The macro browser icon: What we're aiming for[/caption]

Could I get the Macro Browser to show my plugin's icon. No. I followed the documentation. It did not work. I looked again. This time I really paid attention. Was it my fat fingers? Was I just being stupid? (Probably.) I ignored this for a while — maybe it would be better after a night's sleep.

Everything seemed to work a whole lot better when I dropped the beta and moved to version 3.0.2 of the Plugin SDK.
Note: I had to update my ~/.profile to point to the new version of the SDK and update the references to maven in Intelli-J at this point.

I also followed a different tack on getting the macro browser icon to work

  • Find a macro that has a custom icon in the macro browser
  • Go to the Atlassian public subversion repository and browse to the source for that macro plugin.
  • Copy the exact syntax from the atlassian-plugin.xml and paste into your macro's own atlassian-plugin.xml
  • Name the icon exactly the same as in the atlassian-plugin.xml and put it in the correct place in the directory structure

I'm not entirely sure whether it was the copy and paste approach that helped or moving away from the beta. It works now, so I'm not going to loose sleep on why.

Adding a configuring UI to the plugin

My plugin needed to store Google account credentials and display a list of Google Analytics sites, so you can choose the correct profile. How do you do that? Hmmm. Go back to the documentation. It wasn't nearly detailed enough for my liking, so time to vent a little.

Again, it seemed the best way to learn was to find a plugin that has a similar kind of configuration to that you're hoping for and start appropriating the code.

Unit testing and integration testing

This is a good idea. Period. Did I have a clue how to do it for Confluence? Of course not.

Again, the community helped out. Atlassian partners at Adaptavist, Comala Technology and Customware have written about this:

Browsing around the Atlassian public subversion repository was also a help. I've got to say that I'm an easy convert to testing. It just makes sense.

Update (2010-05-04): A nice feature of the SDK is running or testing your plugin against different versions of the product. This is straightforward:


# Integration tests for different versions
atlas-integration-test -v 3.0
atlas-integration-test -v 3.1
atlas-integration-test -v 3.2
# Run different versions of Confluence
atlas-run -v 3.0
atlas-run -v 3.1
atlas-run -v 3.2

Wrapping up

After a good deal of stumbling around, it turns out that I can write a Confluence plugin after all. Everything started working a lot better after I updated from the beta version, but that could just be coincidence. The documentation could be a little better to help the uninitiated but it was equally my fault for not learning to walk first. There is a lot of good information, but it is spread over a few different spaces.

My next step was to get the plugin added to Atlassian Plugin Exchange. It took a little while to get this done — maybe that's best saved for a follow up post. The plugin is now available on Atlassian Plugin Exchange. I hope other people get some use out of it.