I’m having a problem with a Bamboo task app that I have developed. Using Bamboo version 6.10.2.
It is the TaskExporter class that is not working.
When I try to export a plan to bamboo specs using the menuitem View plan as Java Specs it throws a LinkageError as below:
Export to Bamboo Specs failed: java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method “com.mmm.bamboo.plugins.releasenotes.exporter.ReleaseNotesTaskExporter.toSpecsEntity(Lcom/atlassian/bamboo/task/TaskDefinition;)Lcom/atlassian/bamboo/specs/api/builders/task/Task;” the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) of the current class, com/mmm/bamboo/plugins/releasenotes/exporter/ReleaseNotesTaskExporter, and the class loader (instance of org/apache/catalina/loader/WebappClassLoader) for interface com/atlassian/bamboo/task/export/TaskDefinitionExporter have different Class objects for the type com/atlassian/bamboo/specs/api/builders/task/Task used in the signature
The code for the exporter:
package com.mmm.bamboo.plugins.releasenotes.exporter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.atlassian.bamboo.specs.api.builders.task.Task;
import com.atlassian.bamboo.specs.api.model.task.TaskProperties;
import com.atlassian.bamboo.specs.api.validators.common.ValidationContext;
import com.atlassian.bamboo.specs.api.validators.common.ValidationProblem;
import com.atlassian.bamboo.task.TaskContainer;
import com.atlassian.bamboo.task.TaskDefinition;
import com.atlassian.bamboo.task.export.TaskDefinitionExporter;
import com.atlassian.bamboo.task.export.TaskValidationContext;
import com.atlassian.bamboo.util.Narrow;
import com.atlassian.util.concurrent.NotNull;
import com.google.common.base.Preconditions;
import com.mmm.bamboo.plugins.releasenotes.ReleaseNotesTaskConfigurator;
import com.mmm.bamboo.specs.model.task.ReleaseNotesTaskProperties;
public class ReleaseNotesTaskExporter implements TaskDefinitionExporter {
private static final ValidationContext VALIDATION_CONTEXT = ValidationContext.of("Release Notes task");
@NotNull
@Override
public Task toSpecsEntity(final TaskDefinition taskDefinition) {
final Map<String, String> configuration = taskDefinition.getConfiguration();
return new com.mmm.bamboo.specs.builders.task.ReleaseNotesTask()
.jiraFixVersion(configuration.get(ReleaseNotesTaskConfigurator.JIRA_FIX_VERSION_KEY))
.jiraLabel(configuration.getOrDefault(ReleaseNotesTaskConfigurator.JIRA_LABEL_KEY, null))
.jiraPassword(configuration.get(ReleaseNotesTaskConfigurator.JIRA_PASSWORD_KEY))
.jiraProjectName(configuration.get(ReleaseNotesTaskConfigurator.JIRA_PROJECT_NAME_KEY))
.jiraUser(configuration.get(ReleaseNotesTaskConfigurator.JIRA_USER_KEY))
.nuspecFilePath(configuration.get(ReleaseNotesTaskConfigurator.NUSPEC_FILE_NAME_KEY))
.pdfFilePath(configuration.get(ReleaseNotesTaskConfigurator.PDF_FILE_NAME_KEY))
.exportToNuGet(
Boolean.parseBoolean(configuration.get(ReleaseNotesTaskConfigurator.EXPORT_TO_NUGET_KEY)))
.exportToPdf(Boolean.parseBoolean(configuration.get(ReleaseNotesTaskConfigurator.EXPORT_TO_PDF_KEY)));
}
@Override
public Map<String, String> toTaskConfiguration(final TaskContainer taskContainer,
final TaskProperties taskProperties) {
final ReleaseNotesTaskProperties releaseNotesTaskProperties = Narrow.downTo(taskProperties,
ReleaseNotesTaskProperties.class);
Preconditions.checkState(releaseNotesTaskProperties != null,
"Don't know how to import task properties of type: " + taskProperties.getClass().getName());
final Map<String, String> cfg = new HashMap<>();
cfg.put(ReleaseNotesTaskConfigurator.JIRA_FIX_VERSION_KEY, releaseNotesTaskProperties.getJiraFixVersion());
cfg.put(ReleaseNotesTaskConfigurator.JIRA_PASSWORD_KEY, releaseNotesTaskProperties.getJiraPassword());
cfg.put(ReleaseNotesTaskConfigurator.JIRA_PROJECT_NAME_KEY, releaseNotesTaskProperties.getJiraProjectName());
cfg.put(ReleaseNotesTaskConfigurator.JIRA_USER_KEY, releaseNotesTaskProperties.getJiraUser());
if (releaseNotesTaskProperties.getNuspecFilePath() != null) {
cfg.put(ReleaseNotesTaskConfigurator.NUSPEC_FILE_NAME_KEY, releaseNotesTaskProperties.getNuspecFilePath());
}
if (releaseNotesTaskProperties.getJiraLabel() != null) {
cfg.put(ReleaseNotesTaskConfigurator.JIRA_LABEL_KEY, releaseNotesTaskProperties.getJiraLabel());
}
if (releaseNotesTaskProperties.getPdfFilePath() != null) {
cfg.put(ReleaseNotesTaskConfigurator.PDF_FILE_NAME_KEY, releaseNotesTaskProperties.getPdfFilePath());
}
cfg.put(ReleaseNotesTaskConfigurator.EXPORT_TO_NUGET_KEY,
Boolean.toString(releaseNotesTaskProperties.getExportToNuGet()));
cfg.put(ReleaseNotesTaskConfigurator.EXPORT_TO_PDF_KEY,
Boolean.toString(releaseNotesTaskProperties.getExportToPdf()));
return cfg;
}
@Override
public List<ValidationProblem> validate(final TaskValidationContext taskValidationContext,
final TaskProperties taskProperties) {
final List<ValidationProblem> validationProblems = new ArrayList<>();
final ReleaseNotesTaskProperties releaseNotesTaskProperties = Narrow.downTo(taskProperties,
ReleaseNotesTaskProperties.class);
if (releaseNotesTaskProperties != null) {
if (releaseNotesTaskProperties.getExportToNuGet() == true) {
if (releaseNotesTaskProperties.getNuspecFilePath() == null
|| releaseNotesTaskProperties.getNuspecFilePath().isEmpty()) {
validationProblems.add(new ValidationProblem(VALIDATION_CONTEXT, "Nuspec file path is not set!"));
}
}
if (releaseNotesTaskProperties.getExportToPdf() == true) {
if (releaseNotesTaskProperties.getPdfFilePath() == null
|| releaseNotesTaskProperties.getPdfFilePath().isEmpty()) {
validationProblems.add(new ValidationProblem(VALIDATION_CONTEXT, "PDF file path is not set!"));
}
}
}
return validationProblems;
}
}
The code for the Task:
package com.mmm.bamboo.specs.builders.task;
import com.atlassian.bamboo.specs.api.builders.task.Task;
import com.atlassian.bamboo.specs.api.validators.common.ImporterUtils;
import com.atlassian.util.concurrent.NotNull;
import com.atlassian.util.concurrent.Nullable;
import com.mmm.bamboo.specs.model.task.ReleaseNotesTaskProperties;
public class ReleaseNotesTask extends Task<ReleaseNotesTask, ReleaseNotesTaskProperties> {
@NotNull
private String jiraFixVersion;
@Nullable
private String jiraLabel;
@NotNull
private String jiraUser;
@NotNull
private String jiraPassword;
@NotNull
private String jiraProjectName;
@Nullable
private String nuspecFilePath;
@Nullable
private String pdfFilePath;
private boolean exportToNuGet;
private boolean exportToPdf;
public ReleaseNotesTask jiraFixVersion(@NotNull final String jiraFixVersion) {
ImporterUtils.checkNotEmpty("jiraFixVersion", jiraFixVersion);
this.jiraFixVersion = jiraFixVersion;
return this;
}
public ReleaseNotesTask jiraLabel(@Nullable final String jiraLabel) {
this.jiraLabel = jiraLabel;
return this;
}
public ReleaseNotesTask jiraPassword(@NotNull final String jiraPassword) {
ImporterUtils.checkNotEmpty("jiraPassword", jiraPassword);
this.jiraPassword = jiraPassword;
return this;
}
public ReleaseNotesTask jiraProjectName(@NotNull final String jiraProjectName) {
ImporterUtils.checkNotEmpty("jiraProjectName", jiraProjectName);
this.jiraProjectName = jiraProjectName;
return this;
}
public ReleaseNotesTask jiraUser(@NotNull final String jiraUser) {
ImporterUtils.checkNotEmpty("jiraUser", jiraUser);
this.jiraUser = jiraUser;
return this;
}
public ReleaseNotesTask nuspecFilePath(@Nullable final String nuspecFilePath) {
this.nuspecFilePath = nuspecFilePath;
return this;
}
public ReleaseNotesTask pdfFilePath(@Nullable final String pdfFilePath) {
this.pdfFilePath = pdfFilePath;
return this;
}
public ReleaseNotesTask exportToNuGet(final boolean exportToNuGet) {
this.exportToNuGet = exportToNuGet;
return this;
}
public ReleaseNotesTask exportToPdf(final boolean exportToPdf) {
this.exportToPdf = exportToPdf;
return this;
}
@Override
protected ReleaseNotesTaskProperties build() {
return new ReleaseNotesTaskProperties(this.description, this.taskEnabled, this.jiraFixVersion, this.jiraLabel,
this.jiraUser, this.jiraPassword, this.jiraProjectName, this.nuspecFilePath, this.pdfFilePath,
this.exportToNuGet, this.exportToPdf, this.requirements, this.conditions);
}
}
What am I doing wrong?
The task is working fine when using it in the UI and running a plan build, but we use bamboo-specs, so I need this to work.
Please help!
/Jan Lovstrand