I am using the following instructions to automatically transition an issue sub-task of type "Application CR Sub-Task" (CR stands for Change Request for the curious) from "Awaiting Approval" to "Start Review":
https://developer.atlassian.com/display/JIRADEV/Performing+Issue+Operations
(see "Transitioning an existing issue")
I am attempting to execute this logic in response to the IssueEvent.ISSUE_CREATED event for the above issue type, using the following instructions for creating an event listener:
When executing the necessary transitioning logic, however, I get the following error message:
It seems that you have tried to perform a workflow operation (Start Review) that is not valid for the current state of this issue (TINT-89). The likely cause is that somebody has changed the issue recently, please look at the issue history for details.
This didn't make any sense to me, though, because right before this error message being returned from the validation of my transition, I echoed out the following to the log:
[INFO] [talledLocalContainer] 2011-12-07 11:52:56,295 http-2780-2 DEBUG admin 712x4862x1 nz4t4g 127.0.0.1 /secure/CreateIssueDetails.jspa [plugins.issue.transition.IssueTransitioner] issue == TINT-89, transitionName == Start Review, loggedInUser == admin, issueId == 10727, actionId == 11, issueStatusId = 10000, issueStatusName = Awaiting Review, nextActionId == 191, nextAction == null, nextActionXml == null
So the issue is in "Awaiting Review" state (id 10000), and all I'm trying to do is to execute the "Start Review" action (id 11), which according to the Workflow's own XML, is a valid action id for that state id:
<step id="1" name="Open"> <meta name="jira.status.id">10000</meta> <actions> <common-action id="2" /> <action id="11" name="Start Review"> <meta name="opsbar-sequence">20</meta> <results> <unconditional-result old-status="Finished" status="Underway" step="2"> <post-functions> <function type="class"> <arg name="field.value"></arg> <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueFieldFunction</arg> <arg name="field.name">resolution</arg> </function> <function type="class"> <arg name="class.name">com.atlassian.jira.workflow.function.issue.AssignToCurrentUserFunction</arg> </function> <function type="class"> <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg> </function> <function type="class"> <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg> </function> <function type="class"> <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg> </function> <function type="class"> <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg> </function> <function type="class"> <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg> <arg name="eventTypeId">11</arg> </function> </post-functions> </unconditional-result> </results> </action> </actions> </step>
So I went a little deeper into how that error message gets generated and discovered that DefaultIssueService.validateTransition() -> IssueUtilsBean.isValidAction() -> IssueUtilsBean.loadAvailableActions() -> AbstractWorkflow.getAvailableActions(issueObject.getWorkflowId(), inputs) for the issue in question returns an empty array of action IDs because the WorkflowEntry that corresponds to the issue's workflow ID is still in a CREATED state, not an ACTIVATED state. I had to create extensions and/or wrappers for both IssueUtilsBean and Workflow to find this out, because I couldn't get either to log its output.
Anyways, what I want to functionally achieve is to perform a valid workflow action on an issue once it is created *and* once the WorkflowEntry corresponding to the workflow ID of the issue is actually ACTIVATED.
If the way to accomplish this is not an EventListener that listens for IssueEvent.ISSUE_CREATED events, because at that point, the workflow entry behind that issue is not yet active, what is the appropriate way? Implement a com.opensymphony.workflow.util.WorkflowListener? Is there an example for how to do this appropriately in a JIRA 4.4.x environment?
Thanks,
Mike
Community moderators have prevented the ability to post new answers.
The only way around this for now is to perform the transition yourself after you create the issue, and not delegate the logic to a listener that responds to an ISSUE_CREATED event, because at that precise moment, the workflow entry for the issue is still not activated.
I have additionally asked Atlassian to consider an enhancement request that would allow developers to register listeners to be notified when workflow entries associated with issues change state.
use this code to activate workflow entry in your listener before transition:
List<GenericValue> workflowEntries = ComponentAccessor.getOfBizDelegator().findByAnd("OSWorkflowEntry", FieldMap.build("id", issue.getWorkflowId())); for (GenericValue workflowEntry : workflowEntries) { if (workflowEntry.getInteger("state") == null || "0".equals(workflowEntry.getInteger("state").toString())) { workflowEntry.set("state", new Integer(WorkflowEntry.ACTIVATED)); workflowEntry.store(); } }
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you so much! I looked for this more than month. It's a real solution.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Brilliant. Unfortunately I have only one vote.
Thanks
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I have the same strange problem. But, every time a got:
java.lang.UnsupportedOperationException: We don't currently index workflowid - can't get it from document
when I try to use:
List<GenericValue> workflowEntries = ComponentAccessor.getOfBizDelegator().findByAnd("OSWorkflowEntry", FieldMap.build("id", issue.getWorkflowId()));
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I am not sure, but this may happen in case if your issue is type of Issue instead of MutableIssue
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I had the same problem, but sorted out by using the Script Runner Plugin's feature: added a Script Post-function to the Create transition of the workflow, called the Fast-track transition an issue. Entered a condition which would start the transition, selected the transition, and it works nicely. Don't forget to move the post function below the Fire Event post function.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
We can't get fasttrack to work with two stacked, mutually exclusive conditioned PFs. Set after the create event in precedence.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
My way around this was to create a separate thread to do the transition, after waiting a few seconds. This gives the workflow process time to activate the new instance. It's hacky for sure but it works the way you would expect.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Could you please give more details on this? Do you create a thread to call issueService.transition(user, validationResult)?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I am answering this here so that if anyone (me included) runs into this we have some idea on how to solve it. So here is what I done to solve it.
This works for me YMMV.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This appeared to work for my login (as a JIRA admin). But for some reason didn't work for other service desk agents in the team. After tinkering a bit (including adding a post function to the transition to "Set issue status to the linked status of the destination workflow step"), I eventually found that I needed to set the automation task to run asynchronously. As I had other automation tasks that ran for certain agents, I also had to set these to run asynchronously. I don't know why this worked, but it did. Only setting 1 to async didn't work. It had to be both. The other automation task only changed a custom field in the issue as well and it wasn't status related.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Do you have conditions or a validator involved in that step? Probably need to see some code of how you're making the transition.
~Matt
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
No conditions on the Create Issue transition. Just a permissions validator to make sure the user has Create Issue permisison. There are no conditions or validators on the "Start Review" transition.
Here is the code I'm using to make the transition:
public ErrorCollection transition(Issue issue, String transitionName) throws IssueTransitionException { ErrorCollection errors = null; User loggedInUser = getAuthnCtxt().getLoggedInUser(); Long issueId = issue.getId(); int actionId = WorkflowUtils.getActionId(transitionName, issue, getWorkflowMgr()); Status issueStatus = issue.getStatusObject(); String issueStatusId = issueStatus.getId(); String issueStatusName = issueStatus.getName(); IssueInputParameters issueInputParams = new IssueInputParametersImpl(); issueInputParams.setAssigneeId(getAuthnCtxt().getLoggedInUser().getName()); TransitionValidationResult transValidationResult = getIssueSvc().validateTransition(loggedInUser, issueId, actionId, issueInputParams); if (transValidationResult.isValid()) { IssueResult transitionResult = getIssueSvc().transition(loggedInUser, transValidationResult); if (!transitionResult.isValid()) { errors = transitionResult.getErrorCollection(); } } else { errors = transValidationResult.getErrorCollection(); } return errors; }
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
And here is the logic in AbstractWorkflow.getAvailableActions() that's causing no actions to be returned because, apparently, the created issue is still associated with a workflow entry that is only created, not activated:
public int[] getAvailableActions(long id, Map inputs) { try { WorkflowStore store = getPersistence(); WorkflowEntry entry = store.findEntry(id); if (entry == null) { throw new IllegalArgumentException("No such workflow id " + id); } if (entry.getState() != WorkflowEntry.ACTIVATED) { return new int[0]; } <snip> } catch (Exception e) { log.error("Error checking available actions", e); return new int[0]; } }
I verified by extending this class, overriding getAvailableActions(), and adding logging that this method is returning an empty array because entry.getState() == WorkflowEntry.CREATED.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
How to solve this using SIL post function I am getting the error
jjupin.JPG
And my script is
string li;
bool alldesign =
true
;
//we should have here a do - while, but this will work for the sake of the example
for
(li in linkedIssues(parent.key)) {
if
(%li%.status !=
"Design Completed"
&& li != key) {
alldesign =
false
;
}
}
if
(alldesign) {
autotransition(
"Design Completed"
, parent.key);
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Community moderators have prevented the ability to post new answers.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.