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

Coding first Listener Not firing.

CJ_Marchand May 17, 2023

 

 

Hi everyone.

I built a Behavior that is working but am not having luck with Listener.

The listener does not seem to be firing.

I need it to fire on a field changed event. 

I added the "Issue create" Event to see if I could get anything but am not having any luck.   

 

This is my code for now.

I have stripped it code down for testing.  Just want to see the event fire.

 

import com.atlassian.jira.issue.Issue                       ;
import com.onresolve.jira.groovy.user.FieldBehaviours       ;
import groovy.transform.BaseScript                          ;
import com.atlassian.jira.issue.IssueFieldConstants         ;
@BaseScript FieldBehaviours fieldBehaviours                 ;


try {
     getFieldById('customfield_18801').setFormValue( "Hello txtField" ) ;    
    getFieldById('description').setFormValue( "Hello from Listener" ) ;
} catch(Exception e1) {
    getFieldById('customfield_18801').setFormValue( e1.getMessage() ) ;
}

pic of my Listener setup is included.

 

2 answers

1 accepted

Suggest an answer

Log in or Sign up to answer
0 votes
Answer accepted
Peter-Dave Sheehan
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.
May 17, 2023

Script listeneres and behaviours are complete different beast and very listtle code can be shared between the two.

Namely, behaviour comes with several built-in methods that won't exist in the script listener. You can find a partial list here.

For script listeners, you will be dealing more directly with Jira API (like you might with workflows scripts). There are several examples here.

 

Here is your example converted to use the correct methods:

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue

//event.issue is built in all event that fire for issue. This won't work on a CustomFieldUpdated event which fires when a custom field configuration is changed
MutableIssue issue = event.issue as MutableIssue

def cfm = ComponentAccessor.customFieldManager
def is = ComponentAccessor.issueService
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

def txtCustomField = cfm.getCustomFieldObject('customField_18801')

def iip = is.newIssueInputParameters()

iip.description = "Hello from Listener"
iip.addCustomFieldValue txtCustomField.idAsLong, 'Hello txtField'

try {
def validationResult = is.validateUpdate(currentUser, issue.id, iip)
if(!validationResult.valid){
log.error "There the issue update validation was invalid: $validationResult.errorCollection"
return
}
def updateResult = is.update(currentUser,validationResult)
if(!updateResult.valid){
log.error "There the issue update resul was invalid: $validationResult.errorCollection"
}
} catch (e){
log.error "There was an unknown error when performing the issue update: $e"
}
CJ_Marchand May 17, 2023

Thanks for the reply Peter.  Looking at code now but it looks like "event.issue" Is not recognized. 

Am I missing an import statement?

Thanks,

cj

 

 

Undeclared.PNG

Peter-Dave Sheehan
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.
May 17, 2023

That's normal in an external IDE.

"event" is a variable that will be injected by scriptrunner during runtime.

If you use the scriptrunner in-line code editor, you will see that in there, event will not have any error.

To know what variables will be injected into a script in any context, click on the question mark below the script editor field.

Like CJ_Marchand likes this
CJ_Marchand May 17, 2023

Oh, so design time error may not be a runtime error.  Good to know!

Do you use another editor/IDE to write code?  I would really like to use a good editor.

Looks like VS-Code has Jira plugins.

 

I would like to say last question but I seriously doubt it. 

I have a SelectList(Single Choice) field I need to get the selected value.

Is this the right object to retrieve that?  If so which method?

 

def strSelectedChoice   = cfm.getCustomFieldObject('customfield_18812').value?? 

 

I really appreciate your help on this.  

 

C.J.

Peter-Dave Sheehan
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.
May 17, 2023

I use Intellij Community Edition. It has good free support for Java and Groovy.

You can follow the adapatavist instructions for setting up a development environment. By using one of their sample projects, you can import all the dependencies.

 

cfm.getCustomFieldObject only gets a custom field object.  

To get a value for a custom field, you have to integrate the issue object

def cfSelectChoice=cfm.getCustomFieldObject('customfield_18812')
issue.getCustomFieldValue(cfSelectChoice)

For a Select field, this will return an instance of Option

def cfSelectChoice=cfm.getCustomFieldObject('customfield_18812')
def selectedOption = issue.getCustomFieldValue(cfSelectChoice)
if(selectedOption.value == "Text of option to check"){
//do something
}
Like CJ_Marchand likes this
CJ_Marchand May 19, 2023

Peter, sorry for the delay in responding.

We have had Firewall issues here and just getting some connectivity. 

I cannot get to my test instance to work so will have to wait till they get everything lined out.

 

Thanks for your help.

CJ_Marchand May 22, 2023

Peter, 

I put the following code inline in the Listerner and it is saying that issue is not a property of "event".  

Not getting any response from the Listerner.

Thanks,

cj

 

 

InlineCode.PNG

Peter-Dave Sheehan
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.
May 22, 2023

The event variable will dynamically be interpreted in the in-line code box depending on the Events selected in the form. 

If you only have "Issue Created" in the form, the static type checking should identify it correctly.

But if you have more than 1 event selected, all events must be the same type and contain the same methods and properties. 

In your case, remove the CustomFieldUpdatedEvent (if it's still there).

Like CJ_Marchand likes this
CJ_Marchand May 23, 2023

Removing the CustomFieldUpdatedEvent cleared the error but i am still getting no response from the Listener.  

I would think the code above would be bare minimum for me to test and make sure the Listener is working. Just display Hello into a field. I am stumped till I can get a response of some kind.

 

Do you see anything that would prevent it from working?

 

Thanks again!!

cj

Peter-Dave Sheehan
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.
May 23, 2023

You do understand that script listeners are server-based events right?

This fires AFTER you submit the form to create the new issue and after the "create" transition in your workflow is executed.

So to know whether the listener fired or not, you will need to create/save a new issue then review the listener logs/history.

If you want, you can add some extra logging to help troubleshoot:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import org.apache.log4j.Level

log.setLevel(Level.INFO) //make sure logging is enabled at least at the INFO level

log.info "Start of listener for event $event (eventTypeId=$event.eventTypeId)"
//event.issue is built in all event that fire for issue. This won't work on a CustomFieldUpdated event which fires when a custom field configuration is changed
MutableIssue issue = event.issue as MutableIssue
log.info "Event is for issue $issue.key"

def
cfm = ComponentAccessor.customFieldManager
def is = ComponentAccessor.issueService
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

def txtCustomField = cfm.getCustomFieldObject('customField_18801')

def iip = is.newIssueInputParameters()

iip.description = "Hello from Listener"
iip.addCustomFieldValue txtCustomField.idAsLong, 'Hello txtField'

try {
log.info "Validating the planned update for $issue.key"
def validationResult = is.validateUpdate(currentUser, issue.id, iip)
if(!validationResult.valid){
log.error "There the issue update validation was invalid: $validationResult.errorCollection"
return
}
log.info "Attempting to update/save the issue"
def updateResult = is.update(currentUser,validationResult)
if(!updateResult.valid){
log.error "There the issue update result was invalid: $validationResult.errorCollection"
}
log.info "issue $issue.key was updated succesfully"
} catch (e){
log.error "There was an unknown error when performing the issue update: $e"
}
log.info "End of event"
Like CJ_Marchand likes this
CJ_Marchand May 24, 2023

Peter, first off I really appreciate you taking the time to help with this.

I do understand Client/Server webpages. I have over 20 years coding .NET apps.  I am used to having access to EVERY event that happens on a Webpage.  But this is a different environment all together. 

So a Behavior will fire at “Issue Creation Initialization”. This seems to be working. 

But if I understand you the Listener will only fire when clicking the “Create” button AFTER edits?  There is no way to access events while still editing the Issue before submitting the finished Issue by the “Create” button?

My customer would like custom instructions entered into the description field depending on what option they pick form a custom “SelectSingleChoice” field.  I would think there would be a way to detect that event and load the proper text in the description field.  If I understand you, this would not be possible with a Listener.  Is there something else that is between a Behavior and a Listener to gain access to events during editing?

Sorry for so many questions and thanks again for your help!

C.J.

Peter-Dave Sheehan
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.
May 24, 2023

Script Listeners react to server-level events. Those are generally post-transaction events.

Behavior Initializer scripts fire when a form opens (whether a new issue is being created or edited).

Behavior Field scripts fire when the field it's associated with changes.

So what you need is a behaviour linked to your CustomSingeChoice, detect the value of the field and set the description accordingly. Be careful to check that the description is not already set so you don't overwrite what the user might have already entered or that it doesn't fire during later edits.

Like CJ_Marchand likes this
CJ_Marchand May 24, 2023

Thanks Peter!

I will work on a Behaviour.

Also thanks for your patience of a newbie.

There is a learning curve with everything.  I will get better.

CJ_Marchand May 24, 2023

Works fine!

Built a behaviour and added the selectSingleChoice field, then added code file.

 

Here is the code in case someone else may need to do the same.

A big thank you to Peter.  You saved me days of searching and testing.

 

SelectChange.PNG

Peter-Dave Sheehan
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.
May 24, 2023

You're welcome.

Maybe your longer experience would point to reasons why one is better than the other but wanted to share what pattern I would choose to reduce the verbosity of your code.

Something like this:

import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript

@BaseScript FieldBehaviours fieldBehaviours

def fieldMap = [
'Batch Run Request': EEText.batchRun,
'DB Change: Data Fix': EEText.dataFix,
'DB Change: RT Change': 'direct text instead of using a class'
//...
]

def formField = getFieldById('customfield_xxxxx')
def targetDesc = fieldMap[formField.value]
if(targetDesc) getFieldById('description').setFormValue(targetDesc)

class EEText {
static String batchRun = '''all your text here'''
static String dataFix = '''another default description''
}

The main crux is using a map instead of a switch. 

Also, if you set up your script root correctly per the instructions in the adaptivist documentation, you can save your EEText in a separate file (EEText.groovy) and just import it in your behaviour script.

CJ_Marchand May 24, 2023

 

Thanks Peter.

I like the Field Map.  Will play with it.

Learning to build a class Library is on my short list of things to do.  

 

On another subject, is there a way to do some text formating when I send text to Description field?  I read HTML is disabled for security reasons but i would like to be able to Bold, Underline, Font size...... stuff like that.

Peter-Dave Sheehan
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.
May 24, 2023

You should be able to apply wiki style formatting to the text assuming your environment is configured to allow that.

https://confluence.atlassian.com/adminjiraserver0820/rich-text-editing-1095777774.html

You may need to also enable the correct renderer in your project field config.

0 votes
CJ_Marchand May 17, 2023

Added pic of Listener setup.

 

 

Listener1.PNG

TAGS
AUG Leaders

Atlassian Community Events