Hi,
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:
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.issue.link.RemoteIssueLinkManager
import com.atlassian.jira.issue.link.RemoteIssueLinkBuilder
import com.atlassian.jira.bc.issue.link.RemoteIssueLinkService
import com.atlassian.jira.bc.issue.link.RemoteIssueLinkService.CreateValidationResult
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 com.atlassian.sal.api.net.Response
import com.atlassian.sal.api.net.ResponseException
import com.atlassian.sal.api.net.ResponseHandler
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import static com.atlassian.sal.api.net.Request.MethodType.POST
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")
log.setLevel(org.apache.log4j.Level.DEBUG)
// 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"
]
]
]).toString()
def createdIssue
def responseContentJson
def request = applicationLinkRequestFactory.createRequest(POST, "/rest/api/2/issue")
.addHeader("Content-Type", "application/json")
.setEntity(input)
request.execute(new ResponseHandler<Response>() {
@Override
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 = ("http://manubox01.bytesource.info/jira/browse/" + injectedIssueKey)
def createdIssueUrl = ("http://manubox02.bytesource.info/jira/browse/" + 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
]
]).toString()
def request2 = applicationLinkRequestFactory.createRequest(POST, post2)
.addHeader("Content-Type", "application/json")
.setEntity(input2)
def responseContentJson2
request2.execute(new ResponseHandler<Response>() {
@Override
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")
log.info('User: ' + user)
def linkBuilder = new RemoteIssueLinkBuilder()
linkBuilder.url(createdIssueUrl)
linkBuilder.title(createdIssueKey)
def remoteIssueLinkService = ComponentManager.getComponentInstanceOfType(RemoteIssueLinkService.class)
def validationResult = remoteIssueLinkService.validateCreate(user, linkBuilder.build())
log.debug("Validation result: " + validationResult)
remoteIssueLinkService.create(user, validationResult)
///////////////////////////////////////////////////////////////////////////////////////////
2017-11-14 10:28:48,403 DEBUG [groovy.PostFunction]: URL from created Issue: http://manubox02.bytesource.info/jira/browse/TEST02-18 2017-11-14 10:28:48,427 DEBUG [groovy.PostFunction]: URL from injected Issue: http://manubox01.bytesource.info/jira/browse/TEST01-3 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: com.atlassian.jira.bc.issue.link.RemoteIssueLinkService$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 com.atlassian.jira.bc.issue.link.DefaultRemoteIssueLinkService.create(DefaultRemoteIssueLinkService.java:201) at com.atlassian.jira.bc.issue.link.RemoteIssueLinkService$create$0.call(Unknown Source) at Script41.run(Script41.groovy:128)
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.bc.issue.link.RemoteIssueLinkService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.RemoteIssueLinkBuilder
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()
linkBuilder.issueId(sourceIssue.id)
linkBuilder.url("https://www.google.co.uk")
linkBuilder.title("Google")
def remoteIssueLinkService = ComponentAccessor.getComponent(RemoteIssueLinkService)
def validationResult = remoteIssueLinkService.validateCreate(user, linkBuilder.build())
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello @Thanos Batagiannis [Adaptavist]
I have created a similar question here - https://community.atlassian.com/t5/Jira-questions/Unable-to-create-an-remote-link-using-RemoteIssuelinkService-API/qaq-p/727097
Have you come across something similar ?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@RobertThanks 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.
Thanks!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.