I have been following the excellent tutorial to create my first Jira plugin, but it has been a bit of an uphill struggle to progress beyond the noddy example. In particular, I keep hitting the same class loading error when executing the wired tests.
In order to use the backdoor methods in the Jira testkit, I have the following dependencies in my plugin's POM (note that jira.version is defined as 7.12.3):
<dependency>
<groupId>org.eclipse.gemini.blueprint</groupId>
<artifactId>gemini-blueprint-core</artifactId>
<version>${gemini.blueprint.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugins.rest</groupId>
<artifactId>atlassian-rest-module</artifactId>
<version>3.2.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-api</artifactId>
<version>${jira.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.sal</groupId>
<artifactId>sal-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- junit.version = 4.11!!!!! -->
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-tests</artifactId>
<version>${jira.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.atlassian.jira.tests</groupId>
<artifactId>jira-testkit-client</artifactId>
<version>${testkit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
I have reconfigured the maven-jira-plugin as follows:
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-jira-plugin</artifactId>
<version>${amps.version}</version>
<extensions>true</extensions>
<configuration>
<productVersion>${jira.version}</productVersion>
<productDataVersion>${jira.version}</productDataVersion>
<jvmArgs>-Xms1g -Xmx1g -XX:MaxPermSize=1g -XX:-UseGCOverheadLimit -server</jvmArgs>
<testBundleExcludes>
<testBundleExclude>
<groupId>atlassian</groupId>
</testBundleExclude>
<testBundleExclude>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
</testBundleExclude>
</testBundleExcludes>
<!--Uncomment to install TestKit backdoor in JIRA.-->
<pluginArtifacts>
<pluginArtifact>
<groupId>com.atlassian.jira.tests</groupId>
<artifactId>jira-testkit-plugin</artifactId>
<version>${testkit.version}</version>
</pluginArtifact>
<pluginArtifact>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-func-test-plugin</artifactId>
<version>${jira.version}</version>
</pluginArtifact>
</pluginArtifacts>
<enableQuickReload>true</enableQuickReload>
<enableFastdev>false</enableFastdev>
<!-- See here for an explanation of default instructions: -->
<!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
<instructions>
<Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>
<!-- Add package to export here -->
<Export-Package>
com.atlassian.tutorial.myPlugin.api
</Export-Package>
<!-- Add package import here -->
<Import-Package>
org.springframework.osgi*;resolution:="optional",
org.eclipse.gemini.blueprint*;resolution:="optional",
*;version="0";resolution:="optional"
</Import-Package>
<!-- Ensure plugin is spring powered -->
<Spring-Context>*</Spring-Context>
</instructions>
</configuration>
</plugin>
This allows me to compile the following lines in the wired tests:
protected Backdoor backdoor;
...
@Before
public void setup() {
backdoor = new Backdoor(new TestKitLocalEnvironmentData());
...
The file src/test/resources/atlassian-plugin.xml (after much unsuccessful experimentation) has the following content:
<atlassian-plugin key="${project.groupId}.${project.artifactId}-tests" name="${project.name}" plugins-version="2">
<plugin-info>
<description>Tests for ${project.description}</description>
<version>${project.version}</version>
<vendor name="${project.organization.name}" url="${project.organization.url}" />
<bundle-instructions>
<Import-Package>
org.springframework.osgi*;resolution:="optional",
org.eclipse.gemini.blueprint*;resolution:="optional",
*;version="0";resolution:="optional"
</Import-Package>
</bundle-instructions>
</plugin-info>
<!-- from our base plugin -->
<component-import key="myComponent" interface="com.atlassian.tutorial.myPlugin.api.MyPluginComponent"/>
<!-- from the product container -->
<component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties" />
</atlassian-plugin>When I execute the command "atlas-integration-test", the plugin-tests module is loaded successfully, but (regardless of whether the above bundle-instructions section is included or not) it fails to execute the wired tests:
[INFO] [talledLocalContainer] java.lang.NoClassDefFoundError: com/atlassian/jira/util/collect/MapBuilder
[INFO] [talledLocalContainer] at com.atlassian.jira.testkit.client.xmlbackup.XmlBackupCopier.createBaseUrlSubstitution(XmlBackupCopier.java:267)
[INFO] [talledLocalContainer] at com.atlassian.jira.testkit.client.xmlbackup.XmlBackupCopier.<init>(XmlBackupCopier.java:77)
[INFO] [talledLocalContainer] at com.atlassian.jira.testkit.client.DataImportControl.<init>(DataImportControl.java:115)
[INFO] [talledLocalContainer] at com.atlassian.jira.testkit.client.Backdoor.<init>(Backdoor.java:80)
[INFO] [talledLocalContainer] at it.com.atlassian.tutorial.myPlugin.MyComponentWiredTest.setup(MyComponentWiredTest.java:119)
[INFO] [talledLocalContainer] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
What could be going wrong? I've tried everything I can think of (including asking lots of colleagues). By adding suitable debugging statements, I can see that the classloader being used is an instance of
com.atlassian.plugins.rest.module.ChainingClassLoader
and by asking it to reveal its list of packages, I discover that it only has access to generic Java packages - no com.atlassian or org.atlassian ones.