JIRA SERVER

This article shows how to create a JIRA link between the source and a destination issue and keep the link even if the issue has been Unexalated.

By default, the Exalate app displays remote issue link on the Sync panel, but once you 'Unexalate' an issue, the sync panel will be removed from the issue view. 

In some cases, it would be handy to keep the remote issue link on the source issue, even if the synchronization is finished.

It could be achieved with the help of Jira Server API

Source side

Outgoing sync

 // ADD AN ISSUE LINK WHEN THE ISSUE IS CREATED
replica.id            = issue.id
// END: ADD AN ISSUE LINK WHEN THE ISSUE IS CREATED


Destination side

Incoming sync

 // ADD AN ISSUE LINK WHEN THE ISSUE IS CREATED
final def connectionName = relation.name as String
final def replicaId = replica.id as Long
final def remoteIssueKey = replica.key as String
final def remoteIssueUrl = remoteReplica.payload.issueUrl
Thread.start {
    def count = 0
    while (nodeHelper.getLocalIssueFromRemoteId(replicaId) == null && count < Integer.MAX_VALUE) {
        sleep(100L);
        count++
    }
    def createdIssueId = nodeHelper.getLocalIssueFromRemoteId(replicaId).id as Long
    def issueManager = com.atlassian.jira.component.ComponentAccessor.getIssueManager()
    def remoteIssueLinkService = com.atlassian.jira.component.ComponentAccessor.getComponent(com.atlassian.jira.bc.issue.link.RemoteIssueLinkService.class)
    final def nservInternal = com.atlassian.jira.component.ComponentAccessor.getOSGiComponentInstanceOfType(com.exalate.api.node.INodeService.class)
    def proxyAppUserInternal = nservInternal.getProxyUser()
    def createdIssue = issueManager.getIssueObject(createdIssueId)
    if (createdIssue != null) {
        def message = { com.atlassian.jira.util.ErrorCollection c ->
            """Field errors: `${c.errors.entrySet().collect { e -> "${e.key} - ${e.value}".toString() }.join(",")}`, Messages: `${c.errorMessages.join(",")}`, Reasons: `${c.reasons.collect{ r -> r.name() }.join(",")}`""".toString()
        }
        com.atlassian.jira.issue.link.RemoteIssueLinkBuilder builder = new com.atlassian.jira.issue.link.RemoteIssueLinkBuilder();

        builder.issueId(createdIssue.id)
        builder.title(remoteIssueKey);

        builder.applicationName(connectionName);
        builder.applicationType("com.exalate.jiranode.script");
        builder.relationship("Escalated from");
        builder.url(remoteIssueUrl);

        com.atlassian.jira.bc.issue.link.RemoteIssueLinkService.CreateValidationResult validation = ({try {
                return remoteIssueLinkService.validateCreate(proxyAppUserInternal, builder.build())
            } catch (Exception ignore) {
                return remoteIssueLinkService.validateCreate(proxyAppUserInternal.getDirectoryUser(), builder.build())
            }})()
        if (!validation.isValid()) {
            throw new com.exalate.api.exception.IssueTrackerException("Couldn't create a link on " +
                    createdIssue.key + " " +
                    "using proxy user '" + proxyAppUserInternal.getDisplayName() + "' " +
                    "via the JIRA API: " + message(validation.getErrorCollection()));
        }


        com.atlassian.jira.bc.issue.link.RemoteIssueLinkService.RemoteIssueLinkResult remoteIssueLinkResult =
                ({try {
                    return remoteIssueLinkService.create(proxyAppUserInternal, validation)
                } catch (Exception ignore) {
                    return remoteIssueLinkService.create(proxyAppUserInternal.getDirectoryUser(), validation)
                }})()
        if (!remoteIssueLinkResult.isValid()) {
            throw new com.exalate.api.exception.IssueTrackerException("Couldn't create a link on " +
                    createdIssue.key + " " +
                    " using proxy user '" + proxyAppUserInternal.getDisplayName() + "'" +
                    " via the JIRA API: " + message(remoteIssueLinkResult.getErrorCollection()));
        }
    }
}
// END: ADD AN ISSUE LINK WHEN THE ISSUE IS CREATED
Check the example below


The remote issue link display on the Sync panel and in the Issue Links section

The remote issue link remains in the Issue Links section (the issue is not under sync anymore)