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

Earn badges and make progress

You're on your way to the next level! Join the Kudos program to earn points and save your progress.

Deleted user Avatar
Deleted user

Level 1: Seed

25 / 150 points

Next: Root

Avatar

1 badge earned

Collect

Participate in fun challenges

Challenges come and go, but your rewards stay with you. Do more to earn more!

Challenges
Coins

Gift kudos to your peers

What goes around comes around! Share the love by gifting kudos to your peers.

Recognition
Ribbon

Rise up in the ranks

Keep earning points to reach the top of the leaderboard. It resets every quarter so you always have a chance!

Leaderboard

Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,462,867
Community Members
 
Community Events
176
Community Groups

Make transition in listener

Hello community!

I try to make transition in scriptrunner custom listener, but I have 

It seems that you have tried to perform a workflow operation (251) that is not valid for the current state of this issue (XXXXXX). The likely cause is that somebody has changed the issue recently, please look at the issue history for details.

Event is Issue Created
I check workflow and there is a transition with id 251 (which i need)
My custom listener
0.png

if (summary.contains("Invalid item requisites")){
IssueService issueService = ComponentAccessor.getIssueService()
def issueInputParameters = issueService.newIssueInputParameters()
def user = ComponentAccessor.getUserManager().getUserByName('admin')
def transitionValidationResult = issueService.validateTransition(user, issue.id, 251, issueInputParameters)
if (transitionValidationResult.isValid()) {
def transitionResult = issueService.transition(user, transitionValidationResult)
if (transitionResult.isValid()){
log.warn("Transitioned issue ${event.issue.key}")
} else {
log.warn("Transition result is not valid")
log.warn(transitionResult.errorCollection)
}
} else {
log.warn("The transitionValidation is not valid")
log.warn(transitionValidationResult.errorCollection)
}
}

 

  But when I try to make that transition like that  

1.png

2.png

Everything works fine. 
Why I can't make transition in custom listener?

2 answers

I've found solution. Like @Alexey Matveev _Appfire_ answered here I've made different thread to move the issue to a different status and it works, but I really don't understand why I need another one thread
A post-function script:

import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueInputParameters
import org.apache.log4j.Logger

def user = ComponentAccessor.getUserManager().getUserByName('admin')
Thread newThread = new Thread(new MyThread(user, issue, transitionId, log))
newThread.start()

public class MyThread implements Runnable{
private Logger logger
private ApplicationUser threadUser
private Issue issue
private int transitionId

public MyThread(final ApplicationUser user,
final Issue issue, int transitionId, Logger logger){
this.threadUser = user
this.issue = issue
this.transitionId = transitionId
this.logger = logger
}

public void run(){
logger.info("Run method in MyThread")
MyThread.sleep(500) // delay for indexing
IssueService issueService = ComponentAccessor.getIssueService()
MutableIssue currentIssue = ComponentAccessor.getIssueManager().getIssueObject(issue.getId())
IssueInputParameters issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.setSkipScreenCheck(true)
def transitionValidationResult = issueService.validateTransition(this.threadUser, currentIssue.getId(), this.transitionId, issueInputParameters)
if (transitionValidationResult.isValid()) {
logger.info("transitionValidationResult is valid")
def transitionResult = issueService.transition(this.threadUser, transitionValidationResult)
if (transitionResult.isValid()){
logger.info("Transitioned issue ${issue.key} through action ${transitionId}")
} else {
logger.warn("Transition result is not valid")
logger.warn("${transitionResult.errorCollection}")
}
} else {
logger.warn("The transitionValidation is not valid")
logger.warn("${transitionValidationResult.errorCollection}")
}
}
}
0 votes

Hi @aas ,

your code seems correct! Two simple questions :

  • Did u try to perform a reindexing at project level to make sure that your issue is in the correct status where 251 action is available?
  • Are u sure that user used in the listener has transition permission and that 251 action has not conditions that affect your to do that?

Hope this helps,

Fabio

Hi @Fabio Racobaldo _Herzum_ ,

1. Do you mean that I need perform a reindexing somewhere in script listener? Smth like this?

boolean wasIndexing = ImportUtils.isIndexIssues()
ImportUtils.setIndexIssues(true)
ComponentAccessor.getComponent(IssueIndexingService.class).reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)

I've tried to add this code in custom listener before making transition but no luck.

2. User has all permissions. I can make transition in created issue manually via web interface.

Hi @aas ,

1. Please complete a manual reindex at project administartion level in order to be sure that issue is in the correct status.

2. Please check if that transition has some conditions that impact your code.

Hi @Fabio Racobaldo _Herzum_ ,

1. When you tell about manuall reindex you mean that?

3.png

I've done it, nothing has changed (

2. There're no any conditions that impact my code.

The only way my code works is using post-function. I've added another one transition 

4.png

And added Custom script post-function there. In that way script works and issue makes transition.

May be there no any available transition while issue creation so it tells that transition is not valid? I suppose issue must be created and only after that we can make transition or the logic is wrong? But how works fast-track transitions?

Please could you share your workflow in text view?

Hi @aas ,

all seems correct. Please could you share your whole listener code?

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.workflow.WorkflowManager
import com.atlassian.jira.workflow.JiraWorkflow
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.util.ImportUtils

def eventTypeManager = ComponentAccessor.getEventTypeManager()
def eventTypeName = eventTypeManager.getEventType(event.eventTypeId).getName()
log.warn("Event " + eventTypeName)

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
log.warn("User " + user.name)

def issueManager = ComponentAccessor.issueManager
def issue = issueManager.getIssueObject(event.issue.key)
log.warn("Issue " + issue.key)

def summary = issue.getSummary()
if (summary.contains("Somr string")){
def cf= ComponentAccessor.getCustomFieldManager().getCustomFieldObject("customfield_33320")
// find 1 level option
def fieldConfig = marsrut.getRelevantConfig(issue)
def op_1 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Option name"}
// find 2 level option
def op_2 = op_1.getChildOptions().find{it.value == "Option name"}
List<Option> list = new ArrayList()
list.add(op_1)
list.add(op_2)
cf.updateValue(null, event.issue, new ModifiedValue(null, list), new DefaultIssueChangeHolder())
reIndexIssue(issue)
validateAndTransition(251, issue)
} else {
log.warn("summary not contains \"Invalid item requisites\"")
}

def reIndexIssue(Issue issue){
//Re-index the issue after update
log.warn("Try index issue...")
boolean wasIndexing = ImportUtils.isIndexIssues()
log.warn("wasIndexing " + wasIndexing)
ImportUtils.setIndexIssues(true)
ComponentAccessor.getComponent(IssueIndexingService.class).reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)
}

def validateAndTransition(int transitionId, Issue issue){
IssueService issueService = ComponentAccessor.getIssueService()
def issueInputParameters = issueService.newIssueInputParameters()
def user = ComponentAccessor.getUserManager().getUserByName('username')

def transitionValidationResult = issueService.validateTransition(user, issue.id as long, transitionId, issueInputParameters)
if (transitionValidationResult.isValid()) {
log.warn("transitionValidationResult is valid")
def transitionResult = issueService.transition(event.user, transitionValidationResult)
if (transitionResult.isValid()){
log.warn("Transitioned issue ${event.issue.key} through action ${transitionId}")
} else {
log.warn("Transition result is not valid")
log.warn(transitionResult.errorCollection)
}
} else {
log.warn("The transitionValidation is not valid")
log.warn(transitionValidationResult.errorCollection)
log.warn(transitionValidationResult.toString())
}

Hi @aas ,

I don't understand the following portion of code

cf.updateValue(null, event.issue, new ModifiedValue(null, list), new DefaultIssueChangeHolder())

If you want to update some cf within your issue you should use the updateIssue method provided by IssueManager https://docs.atlassian.com/software/jira/docs/api/8.19.0/com/atlassian/jira/issue/IssueManager.html#updateIssue-com.atlassian.jira.user.ApplicationUser-com.atlassian.jira.issue.MutableIssue-com.atlassian.jira.issue.UpdateIssueRequest-

Could you try to test your listener without  the following lines?

 def cf= ComponentAccessor.getCustomFieldManager().getCustomFieldObject("customfield_33320")
// find 1 level option
def fieldConfig = marsrut.getRelevantConfig(issue)
def op_1 = ComponentAccessor.optionsManager.getOptions(fieldConfig)?.find { it.toString() == "Option name"}
// find 2 level option
def op_2 = op_1.getChildOptions().find{it.value == "Option name"}
List<Option> list = new ArrayList()
list.add(op_1)
list.add(op_2)
cf.updateValue(null, event.issue, new ModifiedValue(null, list), new DefaultIssueChangeHolder())
reIndexIssue(issue)

Hi @Fabio Racobaldo _Herzum_ ,

What's wrong with that code? It's simple update of custom field

cf.updateValue(null, event.issue, new ModifiedValue(null, list), new DefaultIssueChangeHolder())

 There're many examples of using it:
https://library.adaptavist.com/entity/update-the-value-of-a-custom-field-using-a-listener


https://community.atlassian.com/t5/Agile-articles/Three-ways-to-update-an-issue-in-Jira-Java-Api/ba-p/736585

 

Hi @aas ,

did u try without that part of code?

Yes, I've tried, has the same error 

It seems that you have tried to perform a workflow operation (Assigned to FD) that is not valid for the current state of this issue (**-*****). The likely cause is that somebody has changed the issue recently, please look at the issue history for details.

Could you try to update the step name from "New issue" to "Created" so it matches the associated status?

Hi @Fabio Racobaldo _Herzum_ 
Changing step name hasn't helped, unfortunately.
I supoose there are no transition with id 251 in the moment of issue craeation 

2.png

Fast Track Transition, I think, firstly create issue and only after that (when issue in Created status) try to make transition

Hi @aas ,

I don't figure out the reason. Listener works after creation because it start after that create event is fired as last post function in creation. Based on that, when listener works, issue should be created and in correct status.

Suggest an answer

Log in or Sign up to answer