Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Script Listener with JQL don´t show updated issue

Joerg Strehl January 15, 2020

Hello,

I need some help with an problem regarding to Listener´s and JQL querys.

So I wrote an Listener which sends an custom mail to the teamleader if the issue is set to priority 1.
In the first step I get the search results from some of our saved filters and then I check if the issue is in one of these filters. Based on the filter I send the mail to the right teamleader.

This works fine until I have an issue with an approval inside the workflow, it seems that the listener is faster than the re-index of the issue in the approval transition. 
When I test the script in the console it works. 

Is there any way to slow down the listener or wait until the re-index is done?

 

Thanks

Joerg

 

3 answers

Suggest an answer

Log in or Sign up to answer
0 votes
Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 24, 2020

Hi @Joerg Strehl ,

I am still not sure why you are running a JQL (maybe I understand if wrong). If you run the script in a post-function and if the priority is 1, send the mail about this particular issue. If you want to run JQLs, I would probably do it in a service every hour (for example) and send a mail if an issue with priority 1 is found.

Anyway I was able to replicate your issue and fix by running the code in a thread and adding a reindex : 

Thread.start({

def issueIndexingService = ComponentAccessor.getComponent(IssueIndexingService)
issue.store()
issueIndexingService.reIndex(issue)

//Run your code here

})

Hope that helps.

Joerg Strehl January 24, 2020

Hi @Antoine Berry 

Thank you for your help but I can´t get it work.

Where I have to put this code, into the "Approval" - Postfunction or into the Script Listener?

Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 24, 2020

That would be in the script listener, using your current code. :)

Joerg Strehl January 27, 2020

Ok I tried it, but when I add the "Thread.start" code it is not working. 

This is my code whitout the "Tread" code: 

import groovy.text.GStringTemplateEngine
import com.atlassian.mail.Email
import com.atlassian.mail.server.MailServerManager
import com.atlassian.mail.server.SMTPMailServer
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.bc.user.search.UserSearchService
import com.atlassian.jira.user.UserPropertyManager
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.issue.search.SearchRequest
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.util.ImportUtils


Issue issue = event.issue
def issueKey = issue.getKey()


def userManager = ComponentAccessor.getUserManager()
def cfManager = ComponentAccessor.getCustomFieldManager()
def userPropertyManager = ComponentAccessor.getUserPropertyManager()
def constantManager = ComponentAccessor.getConstantsManager()
def currentAppUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def issueFactory = ComponentAccessor.getIssueFactory()
def issueManager = ComponentAccessor.getIssueManager()
def customFieldManager = ComponentAccessor.customFieldManager
def baseurl = com.atlassian.jira.component.ComponentAccessor.getApplicationProperties().getString("jira.baseurl")
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchService = ComponentAccessor.getComponent(SearchService)
def searchRequestService = ComponentAccessor.getComponent(SearchRequestService)
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def groupManager = ComponentAccessor.getGroupManager()
def adminUsers = groupManager.getUsersInGroup("jira-administrators")




def rendererManager = ComponentAccessor.getComponent(com.atlassian.jira.issue.RendererManager.class)
def fieldLayoutItem = ComponentAccessor.getFieldLayoutManager().getFieldLayout(issue).getFieldLayoutItem("description")
def renderer = rendererManager.getRendererForField(fieldLayoutItem)
String desc = renderer.render(issue.description, null)

//--------- Wert aus dem Feld Priority reason holen ---------
def prioReasonVal = issue.getCustomFieldValue(ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Priority reason").getAt(0)) as String
String prioReason = renderer.render(prioReasonVal, null);


//--------- Prüfung auf IssueType um Ausführung zu steuern ---------
def acceptedIssueTypes = ["Service Request",
"Service Request with Approvals",
"Approved Account Request",
"Services Article Data",
"Services Customer Master",
"Serial number ActionCode",
"SAP Service",
"SAP changes in forms",
"SAP mass creation of order ",
"Reservation mobile POS",
"Store sales promotion",
"daex-sftp.onconrad",
"Service Request Hardware with Approvals",
"Service Request Permissions with Approvals",
"Service Request Software with Approvals",
"SR - Disable User IT ",
"SR - STEP User/Supplier",
"SR - Telephone",
"Data exchange workflow",
"SR - Approval GF",
// "Qlik",
"SR - GCP Project",
// "RST",
"EDI Service",
"Mobile Device Configuration"]
// "CBDP Data Governance"]


if (issue.priority?.name != 'Prio 1 - Critical')
{ return true }

if (issue.getStatus().name == "Waiting for approval")
{ return true }

if (issue.isSubTask())
{ return true }

if (issue.issueType.name.contains("eCom") || issue.issueType.name.equals("Analytic Requests (CI)") || issue.issueType.name.contains("MDM") || issue.issueType.name.equals("OM Marketing Services") || issue.issueType.name.equals("RST") || issue.issueType.name.equals("Contract management") )
{ return true }

if(issue.getIssueType().name in (acceptedIssueTypes))
{



//--------- JQL Abfrage für PO Zuordnung ---------

String jqlQuery = ""
def query = null
def searchResultsInfraOps = null
def searchResultsSysOps = null
def searchResultsXCM = null
def searchResultsCRM = null
def searchResultsBigData = null
def searchResultsPOS = null
def searchResultsSCM = null
def searchResultsEWM = null
def searchResultsOMS = null


adminUsers.each{ adminUsersFilter ->
searchRequestService.getOwnedFilters(adminUsersFilter).each{SearchRequest filter->

if (filter.name.toString() == "DE Infra-Ops All"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsInfraOps = searchService.search(adminUsersFilter,query, PagerFilter.getUnlimitedFilter()).getResults()
}

else if (filter.name.toString() == "CESD: XCM All"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsXCM = searchService.search(adminUsersFilter, query, PagerFilter.getUnlimitedFilter()).getResults()
}

else if (filter.name.toString() == "CESD: Queue CRM - Open Issues"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsCRM = searchService.search(adminUsersFilter, query, PagerFilter.getUnlimitedFilter()).getResults()
}
else if (filter.name.toString() == "CESD: Queue BigData/PBis - Open Issues"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsBigData = searchService.search(adminUsersFilter, query, PagerFilter.getUnlimitedFilter()).getResults()
}
else if (filter.name.toString() == "CESD: Queue POS - Open Issues"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsPOS = searchService.search(adminUsersFilter, query, PagerFilter.getUnlimitedFilter()).getResults()
}
else if (filter.name.toString() == "CESD: SCM All"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsSCM = searchService.search(adminUsersFilter, query, PagerFilter.getUnlimitedFilter()).getResults()
}
else if (filter.name.toString() == "CESD: Queue IT-EWM - Open Issues"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsEWM = searchService.search(adminUsersFilter, query, PagerFilter.getUnlimitedFilter()).getResults()
}
else if (filter.name.toString() == "CESD: Queue OMS - Open Issues"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsOMS = searchService.search(adminUsersFilter, query, PagerFilter.getUnlimitedFilter()).getResults()
}

else if (filter.name.toString() == "CESD: SysOps All"){
jqlQuery = filter.query?.getQueryString()
query = jqlQueryParser.parseQuery(jqlQuery)
searchResultsSysOps = searchService.search(adminUsersFilter,query, PagerFilter.getUnlimitedFilter()).getResults()
}
}
}



log.warn("Filter InfraOps ${searchResultsInfraOps}")

//--------- Setzen der eMail-Adressen ---------

def emailAddr = ""
def emailAddrCC = ""
def filter = null

if (searchResultsInfraOps.toString().contains(issueKey)) {
emailAddr = "mail1@test.de"
filter = searchResultsInfraOps
}
else if (searchResultsXCM.toString().contains(issueKey)) {
emailAddr = "mail@test.de"
filter = searchResultsXCM
}
else if (searchResultsSysOps.toString().contains(issueKey)) {
emailAddr = "mail2@test.de"
filter = searchResultsSysOps
}
else if (searchResultsCRM.toString().contains(issueKey)) {
emailAddr = "mail3@test.de"
filter = searchResultsCRM
}
else if (searchResultsBigData.toString().contains(issueKey)) {
emailAddr = ("mail4@test.de")
filter = searchResultsBigData
}
else if (searchResultsPOS.toString().contains(issueKey)) {
emailAddr = "mai5l@test.de"
filter = searchResultsPOS
}
else if (searchResultsSCM.toString().contains(issueKey)) {
emailAddr = "mail6@test.de"
filter = searchResultsSCM
}
else if (searchResultsEWM.toString().contains(issueKey)) {
emailAddr = "mail7@test.de"
filter = searchResultsEWM
}
else if (searchResultsOMS.toString().contains(issueKey)) {
emailAddr = "mail8@test.de"
filter = searchResultsOMS
}


else { emailAddr = "mail@test.de"
//return true
}

def status = issue.getStatus().name
//--------- Erstellen der EMail ---------

def subject = "Issue ${issue.key} was created with Prio 1 - Critical"
def body = """<div style="color:#172b4d;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;font-size:14px;font-weight:400;line-height:1.429;letter-spacing:0">
<div>
<br>
<p>
<b>Issue Key:</b><br>
${issueKey}
</p>
<p>
<b>WF-Status:</b><br>
${status}
</p>
<p>
<b>EMail Empfänger:</b><br>
${emailAddr}
</p>
<p>
<b>Filter InfraOps:</b><br>
${searchResultsInfraOps}
</p>
<p>
<b>Filter Ergebnis:</b><br>
${filter}
</p>
<p>
<b>Reporter:</b><br>
${issue.reporter.name}
</p>
<p>
<b>Issue priority:</b><br>
${issue.priority.name}
</p>

<p>
<b>Summary:</b><br>
${issue.summary}
</p>

<p>
<b>Description:</b>
${desc}
</p>

<br>
<p>
<a href="${baseurl}/servicedesk/customer/portal/1/${issue.getKey()}">View request</a>
</p>

</div>
</div>
<p style="color:#7a869a;font-size:12px">
Conrad Service Desk, powered by <a href="https://www.atlassian.com/software/jira/service-desk/powered-by?utm_medium=email&utm_source=service-desk_email-notification_server&utm_campaign=service-desk_email-notification_server" style="color:#0052cc;text-decoration:none" target="_blank" data-saferedirecturl="https://www.google.com/url?q=https://www.atlassian.com/software/jira/service-desk/powered-by?utm_medium%3Demail%26utm_source%3Dservice-desk_email-notification_server%26utm_campaign%3Dservice-desk_email-notification_server&source=gmail&ust=1568799068422000&usg=AFQjCNHsRij9VI1uF-1vLco6cCyleAZqgA">Jira Service Desk</a>
, sent you this message.
</p>"""



//--------- Versand der EMail ---------

SMTPMailServer mailServer = ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer();

if (mailServer)
{
Email email = new Email(emailAddr)
email.addHeader("X-Priority", "1 (Highest)")
email.setMimeType("text/html")
//email.setCc(emailAddrCC)
//email.setBcc(emailAddrBCC)
email.setSubject(subject)
email.setBody(body)
mailServer.send(email)
}
else
{
// Problem getting the mail server from JIRA configuration, log this error
}
//}
}
Boris Berenberg - Atlas Authority
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.
January 27, 2020

Not sure if this is your issue, but we hit something similar when working on the latest release of Notification Assistant for Jira. We had one environment, where for some reason, a single event wouldn't properly trigger the email to be sent. We diagnosed that SEND_MAIL was false https://docs.atlassian.com/software/jira/docs/api/8.5.0/com/atlassian/jira/event/issue/IssueEvent.html#SEND_MAIL The part that makes this super weird is that if we delete that transition and re-create it, then it send the notification fine. If we export the workflow to XML before and after re-creating the transition, then the XML we see is identical. We're still not sure of the underlying cause 🤷‍♂️, but I would try recreating the transition and seeing if it helps you as well.

Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 27, 2020

If i understood your code correctly you are just checking if the priority is the highest and send a mail in this case. If that is so your code is overkill, I would advise to simply use a check for the priority value : 

def priorityName = issue.getPriority().getName()
if (priorityName == "Highest"){
//send mail
}

Antoine

Joerg Strehl January 28, 2020

The mail should be sent at priority "critical" and only for certain issue types. We differentiate between Incidents and Service Requests because different SLAs apply in each case. This Script Listener should be used for Service Requests.

To make sure that the mail is sent to the right team leader, I get the JQL queries from the centrally stored filters that we have created for the queues in the service desk. Based on this I know to which team the issue belongs to and I can set the right email adress of the teamleader.

My plan behind this is that I can use only two listener scripts to control the mail sending for the priority warnings centrally.

And I am really new to groovy and I'm not a programmer so I have to learn it by trial and error

Joerg Strehl January 28, 2020

@Boris Berenberg - Atlas Authority 

In my case the mail is sended, but not to the right person because the issue which is changed (approved) don´t show up in the JQL query. 

It seems that the listener is executed to fast or the issue is still in the cache with the old status. 

Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 28, 2020

I see, it is quite an innovative way to handle the issue. The best way to debug is to check the logs and add displays in the code if necessary with something like :

log.error("value of variable : " + variable)

If you add 

Thread.start({

def issueIndexingService = ComponentAccessor.getComponent(IssueIndexingService)
issue.store()
issueIndexingService.reIndex(issue)

adminUsers.each{ adminUsersFilter ->
searchRequestService.getOwnedFilters(adminUsersFilter).each{SearchRequest filter->

/*************************
run your code until the end
***************************/

})

 What do you get in the logs ? The thread is supposed to shift the execution and thus having your priority updated.

Joerg Strehl January 31, 2020

f I put my code into an thread it looks like it stops at the part where i get the jql querys from the saved filters.

This is what i get in the log file:

2020-01-31 10:34:52,443 http-nio-8080-exec-158 url:/rest/servicede...roval/6131/approve username:joerg.strehl@conrad.de INFO joerg.strehl@conrad.de 634x65442x1 e7cpvq 80.150.21.6,162.158.90.253,35.190.16.234,130.211.2.247 /rest/servicedesk/approvals/1/approval/6131/approve [c.onresolve.jira.groovy] Prio-1 Listener error log
2020-01-31 10:34:52,448 http-nio-8080-exec-158 url:/rest/servicede...roval/6131/approve username:joerg.strehl@conrad.de INFO joerg.strehl@conrad.de 634x65442x1 e7cpvq 80.150.21.6,162.158.90.253,35.190.16.234,130.211.2.247 /rest/servicedesk/approvals/1/approval/6131/approve [c.onresolve.jira.groovy] Start JQL Querys
2020-01-31 10:34:52,451 Thread-972 INFO joerg.strehl@conrad.de 634x65442x1 e7cpvq 80.150.21.6,162.158.90.253,35.190.16.234,130.211.2.247 /rest/servicedesk/approvals/1/approval/6131/approve [c.onresolve.jira.groovy] Start - reIndex
2020-01-31 10:34:52,456 Thread-972 WARN joerg.strehl@conrad.de 634x65442x1 e7cpvq 80.150.21.6,162.158.90.253,35.190.16.234,130.211.2.247 /rest/servicedesk/approvals/1/approval/6131/approve [c.onresolve.jira.groovy] Reindex issue CESD-41818 286730
2020-01-31 10:34:52,509 Thread-972 INFO joerg.strehl@conrad.de 634x65442x1 e7cpvq 80.150.21.6,162.158.90.253,35.190.16.234,130.211.2.247 /rest/servicedesk/approvals/1/approval/6131/approve [c.onresolve.jira.groovy] Status after reIndex: Waiting for support CESD-41818 286730
2020-01-31 10:34:52,510 Thread-972 INFO joerg.strehl@conrad.de 634x65442x1 e7cpvq 80.150.21.6,162.158.90.253,35.190.16.234,130.211.2.247 /rest/servicedesk/approvals/1/approval/6131/approve [c.onresolve.jira.groovy] Admin Users: [joerg.strehl@conrad.de(joerg.strehl)]
2020-01-31 10:38:18,681 indexing-stats-0 INFO [c.a.j.issue.index.IndexingStatsManager] [indexing-stats] Top 10 addIndex total (noFieldIndexers: 700, sum: 329891ms): [{field: watcher, addIndex: {sum/allSum:27.7%, sum:91481ms, avg:0.4ms, max:230ms, count:252272}}, {field: attachment, addIndex: {sum/allSum:24.9%, sum:82118ms, avg:0.3ms, max:242ms, count:252272}}, {field: voter, addIndex: {sum/allSum:23.1%, sum:76206ms, avg:0.3ms, max:227ms, count:252272}}, {field: parent, addIndex: {sum/allSum:20.5%, sum:67708ms, avg:0.3ms, max:193ms, count:252272}}, {field: votes, addIndex: {sum/allSum:0.5%, sum:1562ms, avg:0.0ms, max:7ms, count:252272}}, {field: timeoriginalestimate, addIndex: {sum/allSum:0.5%, sum:1493ms, avg:0.0ms, max:13ms, count:252272}}, {field: progress, addIndex: {sum/allSum:0.4%, sum:1450ms, avg:0.0ms, max:0ms, count:252272}}, {field: issuekey, addIndex: {sum/allSum:0.4%, sum:1391ms, avg:0.0ms, max:4ms, count:252272}}, {field: subtasks, addIndex: {sum/allSum:0.3%, sum:1059ms, avg:0.0ms, max:193ms, count:252272}}, {field: customfield_11401 (Team Role), addIndex: {sum/allSum:0.3%, sum:996ms, avg:35.6ms, max:991ms, count:28}}]
2020-01-31 10:38:18,684 indexing-stats-0 INFO [c.a.j.issue.index.IndexingStatsManager] [indexing-stats] Top 10 addIndex snapshot (noFieldIndexers: 700, sum: 379ms): [{field: scriptrunner, addIndex: {sum/allSum:18.9%, sum:71ms, avg:5.1ms, max:6ms, count:14}}, {field: customfield_11000 (Approvals), addIndex: {sum/allSum:17.2%, sum:65ms, avg:4.7ms, max:6ms, count:14}}, {field: customfield_10001 (Sprint), addIndex: {sum/allSum:5.7%, sum:21ms, avg:1.5ms, max:2ms, count:14}}, {field: customfield_10002 (Epic Link), addIndex: {sum/allSum:5.6%, sum:21ms, avg:1.5ms, max:2ms, count:14}}, {field: customfield_13903 (Parent attachment), addIndex: {sum/allSum:4.9%, sum:18ms, avg:1.3ms, max:4ms, count:14}}, {field: customfield_10000 (Rank), addIndex: {sum/allSum:4.2%, sum:15ms, avg:1.1ms, max:1ms, count:14}}, {field: attachment, addIndex: {sum/allSum:2.7%, sum:10ms, avg:0.7ms, max:1ms, count:14}}, {field: watcher, addIndex: {sum/allSum:2.3%, sum:8ms, avg:0.6ms, max:1ms, count:14}}, {field: versions, addIndex: {sum/allSum:2.1%, sum:8ms, avg:0.6ms, max:1ms, count:14}}, {field: customfield_11117 (Time to resolution), addIndex: {sum/allSum:2.0%, sum:7ms, avg:0.6ms, max:1ms, count:14}}]
Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 31, 2020

I am not familiar with these logs, looks like it is stuck on reindexing. I would advise to add a lot of logs in your code to pinpoint which line exactly is faulty / causes the script to stop.

0 votes
Joerg Strehl January 23, 2020

Hi @Antoine Berry , 

i have created an custom event for approved issues.

I run the JQLs because we have about 10 teams which work in the Jira Service Desk, so i look if the issue is in one of the service desk queues (filter) and based on this i send an custom email to the PO and the teamleader. 

It works fine if the issue is shown in the filter direct after the creation. But in all of our filters we don´t show the issues which are in the status "Waiting for approval". 
When the issue is approved, the event is fired and the listener runs but it looks like that the issue is not found by the filter. When i run the code of the listener in the script console after the approval, it works. It seems that the listener starts before the reindex of the issue is done.

The event is in the transition after the re-index function.

 

Thank you 

0 votes
Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 21, 2020

Hi @Joerg Strehl ,

What even are you listening to ? I am not sure why you need to run a JQL here. Maybe check the order of post-functions, particularly in the approval transition.

TAGS
AUG Leaders

Atlassian Community Events