Script Runner: Sending an email to a scripted field

This is what I want to achieve:

Once an issue is opened we "Qualify" it and defined a team that will handle it, that team is identified by an email, and each team is a group in our JIRA system, eg.:

  • development [AT] acme.com
  • it [AT] acme.com
  • etc.

I want that team to be notified that an issue has been assigned to them.

I have written a scripted field that get the email address of the team based on the Tempo Team selected:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.config.properties.APKeys
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import org.apache.http.HttpRequestInterceptor
import org.apache.http.HttpRequest
import org.apache.http.HttpResponse
import org.apache.http.protocol.HttpContext
import groovyx.net.http.RESTClient
import com.atlassian.jira.user.ApplicationUser
/*
 * Initialize the API connection by getting the JIRA-SD base url
 * and building the Rest client with the fields needed in order
 * to register a worklog.
 */
String baseUrl = ComponentAccessor.getApplicationProperties().getString(APKeys.JIRA_BASEURL)
RESTClient http = new RESTClient(baseUrl)
HttpResponse response
def statusCode
String apiuser = 'admin'
String apipasswd = 'admin'
String auth = "${apiuser}:${apipasswd}".bytes.encodeBase64().toString()
// append the authentication header
http.client.addRequestInterceptor(new HttpRequestInterceptor() {
    void process(HttpRequest httpRequest, HttpContext httpContext) {
        httpRequest.addHeader('Authorization', 'Basic ' + auth)
        httpRequest.addHeader('X-Atlassian-Token', "no-check")
    }})

// get the issue Team identifier, and retrieve its name with the Tempo API
CustomFieldManager customFieldManager = (new ComponentAccessor()).getCustomFieldManager()
CustomField teamCustomField = customFieldManager.getCustomFieldObjectByName('Team')
String tempoTeamId
String tempoTeamName
ApplicationUser user
try {
    tempoTeamId = teamCustomField.getValue(issue)
    if (!tempoTeamId) throw new Exception()
    response = http.get(path:"/rest/tempo-teams/1/team/${tempoTeamId}")
    statusCode = response.getStatusLine().statusCode
    tempoTeamName = response.getData().name
    user = getUserByTempoTeam(tempoTeamName)
    if (!user) throw new Exception()
    return user
} catch (Exception ex) {
    return null
}

def getUserByTempoTeam(teamName) {
    UserManager userManager = ComponentAccessor.getUserManager()
    def users = [
        0:  [name: 'Accounting', username: 'compta [AT] acme.ch'],
        1:  [name: 'Direction', username: 'direction [AT] acme.ch'],
        2:  [name: 'Exploit-Dev', username: 'dev [AT] acme.ch'],
        3:  [name: 'Exploit-NOC', username: 'noc [AT] acme.ch'],
        4:  [name: 'Exploit-System', username: 'systeme [AT] acme.ch'],
        5:  [name: 'Exploit-VOIP', username: 'systeme [AT] acme.ch'],
        6:  [name: 'Infra-Dev', username: 'dev [AT] acme.ch'],
        7:  [name: 'Infra-NOC', username: 'noc [AT] acme.ch'],
        8:  [name: 'Infra-System', username: 'systeme [AT] acme.ch'],
        9:  [name: 'Sales', username: 'vente [AT] acme.ch'],
        10: [name: 'Security', username: 'security [AT] acme.ch'],
        11: [name: 'Support-N1', username: 'dev [AT] acme.ch']
    ]
    def match = users.find { it.value.name.toLowerCase() == teamName.toLowerCase() }
    if (!match) throw new Exception()
    return userManager.getUserByKey(match.value.username)
}

This ends up in filling the scripted field correctly:

image2016-6-27 16:40:4.png

 

But then, on a "Qualify Issue" event, I want to send an email to that user:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.issue.watchers.WatcherManager
import com.atlassian.jira.config.properties.APKeys
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import org.apache.http.HttpRequestInterceptor
import org.apache.http.HttpRequest
import org.apache.http.HttpResponse
import org.apache.http.protocol.HttpContext
import groovyx.net.http.RESTClient
import groovyx.net.http.HttpResponseException
import com.atlassian.jira.user.ApplicationUser
// get the issue Team identifier, and retrieve its name with the Tempo API
CustomFieldManager customFieldManager = (new ComponentAccessor()).getCustomFieldManager()
CustomField fld = customFieldManager.getCustomFieldObjectByName('Assigned-team')
String tempoTeamId
String tempoTeamName
ApplicationUser user
user = fld.getValue(event.issue)
log.error(user)

And "User" is always empty, so no mail is sent.

Can someone help me with that ?

My other option would be to add the user to the watchers list instead of a scripted field, but he will be notified everytime a notification scheme send an email to all watchers, and I'd like to avoid that.

 

Thank you,

Cheers, Giulio

 

1 answer

Try at first to get class of returned value for custom field like this:

log.error(ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName('Assigned-team').getValue().getClass().getName() )

Returns an error:

2016-06-28 08:58:39,273 http-bio-8443-exec-56 WARN admin 538x99379x2 fkmhrg 10.0.105.52,192.168.15.13 /rest/scriptrunner/latest/user/exec/ [c.o.s.r.rest.common.UserScriptEndpoint] Script console script failed:
groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method com.atlassian.jira.issue.fields.config.manager.FieldConfigSchemeManagerImpl#getRelevantConfigScheme.
Cannot resolve which method to invoke for [null, class com.atlassian.jira.issue.fields.CustomFieldImpl] due to overlapping prototypes between:
        [interface com.atlassian.jira.issue.context.IssueContext, interface com.atlassian.jira.issue.fields.ConfigurableField]
        [interface com.atlassian.jira.project.Project, interface com.atlassian.jira.issue.fields.ConfigurableField]
        at com.atlassian.jira.issue.fields.config.manager.FieldConfigSchemeManager$getRelevantConfigScheme$0.call(Unknown Source)
        at com.onresolve.scriptrunner.customfield.GroovyCustomField.getRelevantConfig(GroovyCustomField.groovy:322)
        at com.onresolve.scriptrunner.customfield.GroovyCustomField$getRelevantConfig$0.callCurrent(Unknown Source)
        at com.onresolve.scriptrunner.customfield.GroovyCustomField$getRelevantConfig$0.callCurrent(Unknown Source)
        at com.onresolve.scriptrunner.customfield.GroovyCustomField.getValueFromIssue(GroovyCustomField.groovy:159)
        at com.atlassian.jira.issue.fields.CustomFieldImpl.getValue(CustomFieldImpl.java:386)
        at Script427.run(Script427.groovy:25)

The weird thing is that the error log is displayed in the console (catalina.out) but not on the web console, is this normal ?

It seems like there is a kind of delay preventing the scripted field to work correctly.

customfield.png

Add this to import header:

import com.atlassian.jira.component.ComponentAccessor

I also recommend you to use any IDE to write code to avoid such mistakes. I use Intellij IDEA

The import is present, I have no errors about imports.

I think my problem is a problem of "order of things done":

  1. Issue is qualified (transition)
  2. Event "Issue qualified" is raised
  3. (On event: Issue qualified) Field "Assigned-team" is filled (scripted field)
  4. (On event: Issue qualified) Send an email to "Assigned-team"

The problem is that the two event listeners are triggered parallelly, therefore the scripted field value isn't set yet.

 

How can I handle this ? Should I generate two events, one for qualification and one for sending the email to my team ? Or should I prefer a "watcher" approach (set the user as a watcher instead of a scripted field, and send an email to all watchers) but I'm not sure the problem will be any different.

 

 

I would recommend to set custom field value not into event listener, but into a postfunction. This is more robust approach. 

 

Ok that worked great, but now no email is sent with the Issue Qualified event.

image2016-6-28 12:25:58.png

The field is set properly with an existing user (that's what the script is doing) then an event is raised and configured in the JIRA Events, but no email is sent, never, the event is raised because adding an Event Listener it get called.

 

Any ideas ?

Are you sure than event is handeled by the listener?

Add any log messages to make it clear.

Suggest an answer

Log in or Join to answer
Community showcase
Sarah Schuster
Posted Jan 29, 2018 in Jira

What are common themes you've seen across successful & failed Jira Software implementations?

Hey everyone! My name is Sarah Schuster, and I'm a Customer Success Manager in Atlassian specializing in Jira Software Cloud. Over the next few weeks I will be posting discussion topics (8 total) to ...

3,227 views 14 19
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you
Atlassian Team Tour

Join us on the Team Tour

We're bringing product updates and pro tips on teamwork to ten cities around the world.

Save your spot