User Macro fails with Ajax call to JIRA

zaphnet August 30, 2019

Prototyping a plugin using User macros.

As a newbie in js I'm struggling with understanding the escaping of URL:s.

From the following post I get that the Ajax call expects "No quotes": https://community.atlassian.com/t5/Answers-Developer-Questions/AJAX-call-to-external-API-in-user-macro/qaq-p/494128

AJS.$.ajax({
  url: URL_WITH_NO_QUOTES,
type: "GET",
contentType: "application/json",
  success: function(msg){
    alert(msg);
  }
});

 

When experimenting with a call with a JQL with example below:

It works as long as I have an JQL that does nott contain any space or quotes. 

For generic JQL:s I've attempted using "encodeURIComponent" or "encodeURI" - the REST call fails in the Ajax call, but works fine in a browser. I don't understand why?

Also tried with hardcoded "paths" with %20, %22 and so on, they alos work OK in broowser or command line, but fails in the USer Macro.

From: https://community.atlassian.com/t5/Jira-questions/How-to-perform-calculations-in-confluence-using-Jira-issues/qaq-p/1162542 

jQuery.ajax({
  type: "GET",
  url: "<Confluence URL>/plugins/servlet/applinks/proxy?appId=<UUID>&path=<JIRA URL>/rest/api/latest/search/jql=<YOUR_JQL>",
  dataType: "json",
  async: false,
  success: function( data ) {
      //process data and render it in html tags
  }
});

 

Another example attempting to get the Sum Story points printed from a JQL.

The path looks OK in console in browser, but fails in Ajax call! And Ok in browser

<script>

theurl = "/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=" + "$paramJql" + " AND issueFunction in aggregateExpression(\"Totalpoints\", \"storyPoints.sum()\")"
// theurl = "/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=" + "$paramJql" + " AND issueFunction in aggregateExpression(\"Totalpoints\", \"storyPoints.sum()\")"
// theurl = '/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=' + encodeURIComponent("$paramJql" + ' AND issueFunction in aggregateExpression("Totalpoints", "storyPoints.sum()")')
//encodeURIComponent
//encodeURI
console.log( "theurl: " + theurl);

AJS.toInit(function(){
jQuery.ajax({
type: "GET",
url: "https://confluence.assaabloy.net/plugins/servlet/applinks/proxy?appId=<UUID>&path=" + theurl,
dataType: "json",
async: false}).done(function (response) {

var txt3 = document.createElement("p"); // Create with DOM
var divContainer = document.getElementById("showJira");

one = response.Totalpoints;
txt3.innerHTML = txt3.innerHTML + "Total StoryPoints: " + one;
divContainer.innerHTML = "";
console.log( "Total StoryPoints: " + one);
console.log( "response: " + response);

divContainer.appendChild(txt3);
divContainer.innerHTML = "";
divContainer.appendChild(txt3);
});
});
</script>

The Ajax call returns with null.

2 answers

1 accepted

0 votes
Answer accepted
Rafael Pinto Sperafico
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 4, 2019

Hi @zaphnet ,

Sorry for delay on getting back to you.

After running some tests, please find below an example on how to build the AJAX request.  For this to work you must have an Application Link between Jira and Confluence working.

If the Application Link is configured with OAuth only, you must Allow the user in Confluence performing the action to perform Actions with Jira, the famous "Login & Approve".

## Macro title: My Jira Search Macro
## Macro has a body: Y
## Body processing: Rendered
## Output: No Output
##
## Developed by: Rafael Pinto Sperafico
## Date created: 04/09/2019
## Installed by: Rafael Pinto Sperafico

## User Macro to search in Jira
## @noparams

<script type="text/javascript">
AJS.toInit(function() {

// JQL: jql=project=QWERTY
// url: AJS.Confluence.getBaseUrl() + '/plugins/servlet/applinks/proxy?appId=' + applicationLink.id + '&path=' + applicationLink.rpcUrl + encodeURI('/rest/api/2/search?jql=project=QWERTY'),

// JQL: jql=project="Basic Software Development"
// url: AJS.Confluence.getBaseUrl() + '/plugins/servlet/applinks/proxy?appId=' + applicationLink.id + '&path=' + applicationLink.rpcUrl + encodeURI('/rest/api/2/search?jql=project%3D%22Basic%20Software%20Development%22'),

// JQL: jql=issueFunction in aggregateExpression(total,"originalEstimate.sum()")
// url: AJS.Confluence.getBaseUrl() + '/plugins/servlet/applinks/proxy?appId=' + applicationLink.id + '&path=' + applicationLink.rpcUrl + encodeURI('/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=issueFunction%20in%20aggregateExpression(total%2C%22originalEstimate.sum()%22)'),

var search = function(applicationLink) {
jQuery.ajax({
url: AJS.Confluence.getBaseUrl() + '/plugins/servlet/applinks/proxy?appId=' + applicationLink.id + '&path=' + applicationLink.rpcUrl + encodeURI('/rest/api/2/search?jql=project%3D%22Basic%20Software%20Development%22'),
type: "GET",
contentType: "application/json",
success: function(data) {
console.log(data);
}
})
.done(function(data) {
console.log(data);
})
}

//
// Get a list of all application link configured in Confluence
//
jQuery.ajax({
url: AJS.Confluence.getBaseUrl() + '/rest/applinks/1.0/listApplicationlinks.json',
type: "GET",
dataType: "json",
success: function(data) {
console.log(data);
}
})
.done(function(data) {
//
// Iterate over a list of application links
// search for Jira application link
// search in Jira application link found
//
jQuery.each(data.list, function(i, v) {
if (v.application.typeId == 'jira') {
AJS.log(v.application);
search(v.application);
}
})
});
});
</script>

Tested on Confluence 6.6.7 and 6.15.2

Kind regards,
Rafael

zaphnet October 13, 2019

Thanks for your help!

Finally got some time to review all my posts/attempts.

The call to get proxy and jira server failed due to websudo, but those were never the problem.

I must have made some other typo in combination with the final working url:

var theurl = encodeURI(confbase + "/plugins/servlet/applinks/proxy?appId=" + confproxy +"&path=" + jirabase + "/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=" + encodeURIComponent('fixversion="$paramProjectIssue" AND issueFunction in aggregateExpression("Totalpoints", "storyPoints.sum()")'));

{"Totalpoints":"235"}

Finally got all the "" and '' to work with $paramProjectIssue parameter from Built In Macro.

sviengkhou December 11, 2019

Hello,

I'm trying to do something similar to Zaphnet and currently am running into error 500.

 

I'm using HTML macro from Confluence and trying to do some JQL query to JIRA.

I've followed the steps where you get the Jira UUID and the do the JQL query but in vain.

My query looks something like this

https://<ConfluenceURL>/plugins/servlet/applinks/proxy?appId=<UUDI>&path=https://<JIRAURL>/rest/api/2/search?jql=project=<MYPROJECT>

And if I try this directly from a web page I still get 500 error.

Any thought? 

 

Thanks

0 votes
Rafael Pinto Sperafico
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 31, 2019

Hi @zaphnet ,

I usually perform the JQL search in Jira first, e.g:

text ~ "sample feature" and project = "Basic Software Development"

This is result in the following encoding in my web browser address bar:

jql=text%20~%20"sample%20feature"%20and%20project%20%3D%20"Basic%20Software%20Development"%20

Then, I copy the JQL above and paste it into the AJAX call surrounding it with single-quotes ('):

AJS.$.ajax({
url: 'http://localhost:8080/jira/rest/api/2/search?jql=text%20~%20"sample%20feature"%20and%20project%20%3D%20"Basic%20Software%20Development"',
type: "GET",
dataType: "json",
success: function(data) {
AJS.log(data);
}
});

Hope the above helps.

Kind regards,
Rafael

zaphnet September 2, 2019

I've tried a number of different hard-coded strings as:

aurl = 'https://localhost/plugins/servlet/applinks/proxy?appId=<UID>&path=/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=issuekey=STP-207%20AND%20issueFunction%20in%20aggregateExpression(%22Totalpoints%22%2C%20%22storyPoints.sum()%22)';

or:

aurl = 'https://localhost/plugins/servlet/applinks/proxy?appId=<UID>&path=/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=issuekey=STP-207%20AND%20issueFunction%20in%20aggregateExpression("Totalpoints"%2C%20"storyPoints.sum()")';

 

They all fail without a json object returned, but work OK if I paste them on commandline.

"Failed to run init function: TypeError: Cannot read property 'Totalpoints' of null"

In my example direct from rest API: 

{"Totalpoints":"8"}

 

Rafael Pinto Sperafico
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 2, 2019

Hi @zaphnet ,

Sorry, it took me some time to understand from your description that you are actually attempting on calling ScriptRunner REST API endpoint (from Adaptavist) to get the Sum Story points.

When running aggregateExpression from Adaptavist, the search request to be used is as you have mentioned:

# Adaptavist REST API
/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=

and not:

# Jira REST API
/rest/api/2/search?jql=

Just to be sure we are on the same page ;)

For testing purposes, could you please replace the endpoint with:

aurl = 'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=JIRA_BASE_URL/rest/api/2/issue/STP-207';

The testing purpose is to validate the request. You should get a STP-207 Jira Issue (https://docs.atlassian.com/software/jira/docs/api/REST/7.6.1/#api/2/issue-getIssue)

At the same time, would be possible to share your project somehow (e.g repository) so I could run some tests and get back to you with a resolution?

Kind regards,
Rafael

zaphnet September 3, 2019

Sorry for the confusion I've been having the same problem with both sql and script runner REST api:s.

The calls

aurl = 'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=JIRA_BASE_URL/rest/api/2/issue/STP-207';

and

aurl = 'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=/rest/api/2/issue/STP-207';

both work fine.

Still confusing to me how to write the url, some experiments in a browser (GurkaFilter a public example filter):

CCONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=<JIRA_UID>/rest/api/2/search?jql=filter=GurkaFilter

Works fine, now attempting with another filter using the filter number.

CCONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=<JIRA_UID>/rest/api/2/search?jql=filter=15593

Works fine, now attempting to use its name("Gurka Filter"):

None of below works

filter="Gurka Filter"

filter="Gurka%20Filter"

filter=\"Gurka%20Filter\"

filter=%27MY%20RFA%27

filter=%22Gurka%20Filter%22

Thanks for all the help, the problems that I encounter is in the combination of the application link/proxy and jira rest api.

Example above accessing jira rest api directly works fine

 <JIRA_UID>/rest/api/2/search?jql=filter="Gurka%20Filter"
Rafael Pinto Sperafico
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 4, 2019

Hi @zaphnet ,

Thank you for your update and examples.

Could you please try removing the quotes from your JQL search, e.g:

'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=<JIRA_BASE_URL>/rest/api/2/search?jql=filter=Gurka%20Filter'

Kind regards,
Rafael

zaphnet September 4, 2019

Still fails

'CONFLUENCE_BASE_URL/plugins/servlet/applinks/proxy?appId=<JIRA_UID>&path=<JIRA_BASE_URL>/rest/api/2/search?jql=filter=15593'

Works fine.

 

Attempted another workaround: Directly in jira rest api:


<JIRA_BASE_URL>/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=issuekey%20=%20STP-207%20AND%20issueFunction%20in%20aggregateExpression(Totalpoints,%20"storyPoints.sum()")

Works OK with output:

{"Totalpoints":"8"}

With a filter JQL: GurkaFilter

GurkaFilter=issuekey = STP-207 AND issueFunction in aggregateExpression(Totalpoints, "storyPoints.sum()") 

<JIRA_BASE_URL>/rest/scriptrunner-jira/latest/jqlfunctions/aggregateResult?jql=filter=GurkaFilter

Fails with 

{"message":"Negative array index [-1] too large for array size 0"}

...

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events