Creating a reciprocal remote link with postfunction



I have 2 JIRA instances (01 & 02) and in them I created 2 projects (project "TEST01" in instance 01 & project "TEST02" in instance 02). My goal now is to write a postfunction for instance 01, that creates a new issue in instance 02 and furthermore creates a reciprocal remote link between the 2 issues.

I have already written a script, that creates a new issue (in instance 02) via the REST API. Then, also via the REST API the script links the new issue to the issue in instance 01.

The problem now is, that I don't know how I am supposed to create the link from issue in instance 01 to the new issue in instance 02.


Script overview:

  1. Creating application link
  2. Creating new issue in instance 02
  3. Creating URLs
  4. Create remote link from new issue (in instance 02) to original issue (in instance 01)
  5. Creating remote link

The error occurs in the last few lines - in the "Creating remote link" section.

Does somebody know why the validation result is invalid? Or is there a better approach to creating a reciprocal remote link?


Thank you for your help!


import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.applinks.api.ApplicationLinkService
import com.atlassian.applinks.api.application.jira.JiraApplicationType
import com.atlassian.sal.api.component.ComponentLocator
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import static
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.comments.CommentManager
import org.apache.log4j.Category
import org.apache.log4j.Level

def Category log = Category.getInstance("com.onresolve.jira.groovy.PostFunction")

// Get access to 2nd Jira instance
def appLinkService = ComponentLocator.getComponent(ApplicationLinkService)
def appLink = appLinkService.getPrimaryApplicationLink(JiraApplicationType)
def applicationLinkRequestFactory = appLink.createAuthenticatedRequestFactory()

// Creating new issue in instance 02
def input = new JsonBuilder([
    fields: [
        project: [
            id: "10006"                    // Determines in which project the issue is created
        summary: "I am new",
        issuetype: [
            id: "10001"                    // Determines the IssueType that is created
        reporter: [
            name: "admin"

def createdIssue            
def responseContentJson
def request = applicationLinkRequestFactory.createRequest(POST, "/rest/api/2/issue")
    .addHeader("Content-Type", "application/json")

request.execute(new ResponseHandler<Response>() {
    void handle(Response response) throws ResponseException {
        responseContentJson = response.responseBodyAsString                // The response is converted to a Json String
        def jsonSlurper = new JsonSlurper()
        createdIssue = jsonSlurper.parseText(responseContentJson)        // The Slurper parses the Json Format, so that the properties can be extracted
        if ( response.statusCode != 201) {
            log.error("Creating jira issue failed: ${response.responseBodyAsString}")

// Creating URLs
def createdIssueKey = createdIssue.key.toString()
def injectedIssueKey = issue.getKey().toString()
def injectedIssueUrl = ("" + injectedIssueKey)
def createdIssueUrl = ("" + createdIssueKey)
def post2 = ("/rest/api/2/issue/" + createdIssueKey + "/remotelink")

log.debug('URL from created Issue: ' + createdIssueUrl)
log.debug('URL from injected Issue: ' + injectedIssueUrl)

// Create remote link from new issue (in instance 02) to original issue (in instance 01)
def input2 = new JsonBuilder([
    object: [
        url: injectedIssueUrl,
        title: injectedIssueKey

def request2 = applicationLinkRequestFactory.createRequest(POST, post2)
    .addHeader("Content-Type", "application/json")

def responseContentJson2
request2.execute(new ResponseHandler<Response>() {
    void handle(Response response2) throws ResponseException {
        responseContentJson2 = response2.responseBodyAsString
        if ( response2.statusCode != 201) {
            log.error ("Remote linking jira issue failed: ${response2.responseBodyAsString}")

// Create reciprocal link
def user = ComponentAccessor.getUserManager().getUserByName("admin")'User: ' + user)

def linkBuilder = new RemoteIssueLinkBuilder()

def remoteIssueLinkService = ComponentManager.getComponentInstanceOfType(RemoteIssueLinkService.class)

def validationResult = remoteIssueLinkService.validateCreate(user,
log.debug("Validation result: " + validationResult)

remoteIssueLinkService.create(user, validationResult)


2017-11-14 10:28:48,403 DEBUG [groovy.PostFunction]: URL from created Issue:
2017-11-14 10:28:48,427 DEBUG [groovy.PostFunction]: URL from injected Issue:
2017-11-14 10:28:48,532 INFO [groovy.PostFunction]: User: admin(admin)
2017-11-14 10:28:48,564 DEBUG [groovy.PostFunction]: Validation result:$CreateValidationResult@1f2386c9
2017-11-14 10:28:48,602 ERROR [workflow.ScriptWorkflowFunction]: *************************************************************************************
2017-11-14 10:28:48,604 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: TEST01-3, actionId: 31, file: <inline script>
java.lang.IllegalStateException: You cannot create a remote issue link with an invalid validation result.
	at$create$ Source)


1 answer

1 accepted

1 vote
Accepted answer

Hi Robert,

I think you are close enough. So for the create remote issue link part hopefully the following script will help you.

import com.atlassian.jira.component.ComponentAccessor

def user = ComponentAccessor.getUserManager().getUserByName("admin")

//this will be the issue that the remote link will get created
def sourceIssue = ComponentAccessor.issueManager.getIssueByCurrentKey("ATG-1")

def linkBuilder = new RemoteIssueLinkBuilder()


def remoteIssueLinkService = ComponentAccessor.getComponent(RemoteIssueLinkService)
def validationResult = remoteIssueLinkService.validateCreate(user,

if (validationResult.isValid()) {
remoteIssueLinkService.create(user, validationResult)
log.debug "Remote link created"
else {
log.error validationResult.errorCollection.errorMessages

Please ping me if this does not help. Hopefully now you will be able to get more info in your logs why the validationResult is not valid.

regards, Thanos

Hi Thanos,


thank you very much for your help! Indeed that was the problem. I simply did not specify the source issue. The "linkBuilder.issueId()" was missing. Now it's working!

For whatever reason I thought that this was already given in a post function.

Again, thank you for your help!


Best regards


@Robert PejicThanks for sharing this code. I see you're using appLink.createAuthenticatedRequestFactory() to create the request.

I wonder how have you configured your app links, since I can´t make it work for me. I get a code 401 (Unauthorized) from request.execute.

I also would like to know if in your scenario the user that is executing the transition in jira 01 always exists and has the permission to create issues in Jira 02, even when you are setting the reporter to admin in the issue in Jira 02.



Suggest an answer

Log in or Sign up to answer
Community showcase
Published Jan 08, 2019 in Jira

How to Jira for designers

I’m a designer on the Jira team. For a long time, I’ve fielded questions from other designers about how they should be using Jira Software with their design team. I’ve also heard feedback from other ...

1,101 views 4 9
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you