Running Parallel TrustedRequestFactory Instances Using Threads

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

Your email address will not be published. Required fields are marked *