TrustedRequestFactory is a Jira-supplied way of authenticating against Jira itself. If I wanted to authenticate against the current instance, or an external instance, this is what I’d consider using.
This script iterates through a collection of Jira URLs, and processes them as TrustedRequestFactory GET requests in parallel. This is useful in cases when a large number of requests need to be submitted as HTTP; instead of waiting for each one to finish in turn, we can run them all at once.
As it stands, this script authenticates using the logged-in user. However, this could be amended pretty easily by simply adding the correct type of authentication as a header on the request. As well, if you wanted to authenticate against a different Jira instance, the URL structure would need to be amended slightly.
I’ve commented the code as best I can, but quite frankly I’m still learning about parallel execution myself. I’m next going to dig into async vs. threading, and see what I can discover.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.properties.APKeys
import com.atlassian.sal.api.net.Response
import com.atlassian.sal.api.net.ResponseException
import com.atlassian.sal.api.net.ReturningResponseHandler
import com.atlassian.sal.api.net.TrustedRequest
import com.atlassian.sal.api.net.TrustedRequestFactory
import com.atlassian.sal.api.net.Request
import groovy.json.JsonSlurper
import groovyx.net.http.ContentType
import groovyx.net.http.URIBuilder
import java.net.URL;
import java.util.concurrent.Callable
import java.util.concurrent.Executors
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def baseUrl = ComponentAccessor.applicationProperties.getString(APKeys.JIRA_BASEURL)
def trustedRequestFactory = ComponentAccessor.getOSGiComponentInstanceOfType(TrustedRequestFactory)
//We use an instance of TrustedRequestFactory to authenticate against Jira
def endPointPath = '/rest/api/2/issue/'
def responses = []
//Define an array to hold the responses as they come in
def urls = [
baseUrl + endPointPath + "DEMO-40",
baseUrl + endPointPath + "DEMO-41",
baseUrl + endPointPath + "DEMO-42"
]
def responseHandler = new ReturningResponseHandler < Response, Object > () {
Object handle(Response response) throws ResponseException {
if (response.statusCode != HttpURLConnection.HTTP_OK) {
log.error "Received an error while posting to the rest api. StatusCode=$response.statusCode. Response Body: $response.responseBodyAsString"
return null
} else {
def jsonResp = new JsonSlurper().parseText(response.responseBodyAsString)
responses.add(jsonResp)
}
}
}
//Define a response handler that we'll feed to the executeAndReturn method
//This is also where the information from the request is returned. It gets stored in the responses array as a collection of JSON objects
def executeRequest = {
url ->
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.GET, url) as TrustedRequest
//This works, not sure why the script console complains about it
request.addTrustedTokenAuthentication(new URIBuilder(baseUrl).host, currentUser.name)
request.addHeader("Content-Type", ContentType.JSON.toString())
request.addHeader("X-Atlassian-Token", 'no-check')
request.executeAndReturn(responseHandler)
} //Define an execution request. This includes the creation of the request, and the authentication parameters
def executor = Executors.newFixedThreadPool(urls.size())
//Define an Executor and thread pool, the size of which is determined by the number of URLs we predefined
def futures = urls.collect {
url ->
executor.submit(new Callable < Object > () {
Object call() throws Exception {
executeRequest(url)
}
})
}//Iterate through the collection of URLS, submitting each as a callable object
executor.shutdown()
executor.awaitTermination(Long.MAX_VALUE, java.util.concurrent.TimeUnit.SECONDS)
//Shut down the Executor after all of the URLs have been processed
responses.each {
response ->
log.warn(response.self)
}//Iterate through the responses
Leave a Reply