Hello,
I'm new to groovy script and I'm not a developer. I'm looking to close subtasks when the parent is closed. I am trying to use the code from the Scriptrunner site: https://docs.adaptavist.com/sr4js/latest/features/workflows/post-functions/custom-post-functions/custom-post-function-examples/auto-close-sub-tasks
I've modified it a bit to say if the status of the subtask isn't closed, then close it. The workflow allows a transition from any status to the Closed status.
import com.atlassian.jira.component.ComponentAccessor
import org.apache.log4j.Logger
import org.apache.log4j.Level
def log = Logger.getLogger("com.acme.workflows")
log.setLevel(Level.DEBUG)
def issueService = ComponentAccessor.getIssueService()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def parentstatus = issue.getStatusObject().getName()
def parentResolution = issue.getResolutionObject().getName()
log.debug "status of parent is ${parentstatus}"
log.debug "resolution of parent is ${parentResolution}"
def subTasks = issue.getSubTaskObjects()
subTasks.each {
if (it.statusObject.name != "Closed") {
log.debug "status of subtask is $it.statusObject.name"
def issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.with {
setResolutionName("Done") // resolution to be set to Done
log.debug "resolution of subtask is $it.ResolutionObject.name"
setComment("Closing as a result of the parent issue being closed.")
setSkipScreenCheck(true)
}
// validate and transition subtask
def validationResult = issueService.validateTransition(user, it.id, 6, issueInputParameters)
if (validationResult.isValid()) {
def issueResult = issueService.transition(user, validationResult)
if (!issueResult.isValid()) {
log.warn("Failed to transition subtask ${it.key}, errors: ${issueResult.errorCollection}")
}
} else {
log.warn("Could not transition subtask ${it.key}, errors: ${validationResult.errorCollection}")
}
}
}
Here is the error log. I seem to be having a problem with the resolution. I've tried all sorts of things.
groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.setResolutionName() is applicable for argument types: (String) values: [Done] at Script183$_run_closure1$_closure2.doCall(Script183.groovy:24) at Script183$_run_closure1.doCall(Script183.groovy:23) at Script183.run(Script183.groovy:18)
I'd love some help.
Thanks!
Laurie
I think the error you're getting is because there is no issueInputParameter called "setResolutionName"
on this line:
setResolutionName("Done") // resolution to be set to Done
That's what this part of the error translates to:
No signature of method: ...setResolutionName() is applicable for ...[Done]
I wish they'd leave out the extraneous stuff in the error messages and just tell you what exactly went wrong, but oh well.
You'd need to get the Resolution's Id and use it instead of the name.
That's probably why this method was used in the original example:
setResolutionId(
"1"
)
// resolution of "Fixed"
To find the Resolution Id, what I'd do to cheat having to look it up through code, is go in to the Jira Admin area under Issues, then Resolutions. Hover over the Edit link that's next to the Done resolution. Then look at the URL that appears at the bottom (or wherever) of your browser:
That number at the end is the Id of the resolution. In this case, mine would look like:
setResolutionId("10002") // resolution of "Done"
Your Id will probably be different.
Can I just say, that you have earned the Wonder Woman title?! Thank you so much for taking the time to explain all of that for me. That was super kind!
That makes a lot of sense.
So I updated it to
setResolutionID("10000")
and got the following error:
groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.setResolutionID() is applicable for argument types: (String) values: [10000] at Script238$_run_closure1$_closure2.doCall(Script238.groovy:24) at Script238$_run_closure1.doCall(Script238.groovy:23) at Script238.run(Script238.groovy:18)
So I thought maybe the quotes around it were making it look like a string rather than an ID, so I changed it to
setResolutionID(10000)
and got the following error:
groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.setResolutionID() is applicable for argument types: (Integer) values: [10000]
at Script243$_run_closure1$_closure2.doCall(Script243.groovy:24)
at Script243$_run_closure1.doCall(Script243.groovy:23)
at Script243.run(Script243.groovy:18)
Although I see in your documentation, that it is expecting a string. Obviously, I'm still missing something. I feel like it is rather simple, but I'm just not sure what it is...
Any additional thoughts on what I might try?
Thanks again WW!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Also, do I need to have this in a particular order in the post-functions? I put it 3rd because it felt like the parent needed to be closed first. I had tried it at the end and it didn't work their either. Not sure if it matters in this instance?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I am trying to reply to your comment, but it's saying I already posted the answer. Maybe entering this comment will let the other one be added.
Finally! I had to copy/paste to Notepad to remove any formatting, then re-add formatting before it allowed me to submit the reply. They need to fix that issue, I've come up against it multiple times.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You are welcome. I like to explain in detail and in plain English, especially if the questioner says they're not a developer, but I suspect you know more than you say (or maybe think) you do. ;)
You're definitely right to question the order of the Post Functions. It can make a difference, but in your case, I think it's in the right spot.
The line with validateTransition does have a different number for actionId in the example than in yours.
validateTransition(ApplicationUser user, Long issueId, int actionId, IssueInputParameters issueInputParameters)
This method will validate parameters and check the transition conditions and if all checks pass it will construct a new instance of the Issue and will update it with the new parameters.
The error might be happening on that line, since it checks to see if the issueInputParameters are valid. Sometimes an error message can appear to be for one part of the code, but really end up being for another part of the code that influenced the code shown in the error. Who knows?
Your actionId=6, the example's actionId=5.
You are in luck, though, because this particular method is actually documented fairly decently, which is rare. :) It says:
actionId - is the id of the workflow action that you would like to transition the issue through.
So, I'm not sure if your actionId is 6 because that's your workflow's action. I'm guessing that's the same as the transition Id, but I'm not sure. I'd experiment here with hovering over links in the workflow edit screen to find the right actionId, if it's not 6.
Or maybe there's some other ResolutionId that I'm unaware of. So you could try to use "1" like in the example, just to see if it does anything.
Beyond that, I can't see any other differences between yours and the example.
PS: Instead of having to write the 4 lines of code for the logger, you can just use this line (if you're not using it in a class or something more complicated than a simple script):
log.setLevel(org.apache.log4j.Level.DEBUG)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks again @WW
I've tried everything for the actionID - resolution ID, transition ID, workflow step ID - with and without quotes.
I'm still getting the same error on the log, no matter what I do.
Is there something potentially related to the issueInputParameters.with? it really isn't getting past the setResolutionID().
Is there a way to do the transition prior to setting the resolution? Although the validate step seems to rely on that resolution.
Ugh.. feeling like it is right in front of my eyes somewhere, I'm just missing it...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I know the feeling, @LaurieC :)
I just saw it!
Your error message says:
setResolutionID()
The example code and documentation say:
setResolutionId
()
Do you see it now?
I HATE these kinds of errors. Why can't the language be smarter than that?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Woohoo @WW ! That was it! Amazing!
Wow, it took me three times looking at what you wrote to find the problem. Thank you! Thank you! Thank you!!
Now... on to getting the resolution reason from the parent and using it for the subtasks.
If you've got energy for that one, I can tell you what I've got. If not, you've gotten me over the big hurdle and I'm grateful!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yes, I've learned that they never capitalize the "d" in Id anywhere in Jira. (At least I hope they don't or that will get confusing!)
I don't have the time to write the code for your next step, but if you get stuck, put out another question, and I'll see if I can help answer it. :)
If you do post to another question, let me know on here or @mention me (if it's possible) in a comment on the other question so that I get a notification.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks again @WW .
I got it working! (with a little help) Here's my final code that also carries down the parent resolution.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.ResolutionManager
log.setLevel(org.apache.log4j.Level.DEBUG)
def issueService = ComponentAccessor.getIssueService()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def parentstatus = issue.getStatusObject().getName()
def resolutionManager = ComponentAccessor.getComponent(ResolutionManager)
def parentResolution = issue.getResolutionObject()?.getId()
log.debug "status of parent is ${parentstatus}"
log.debug "resolution of parent is ${parentResolution}"
def subTasks = issue.getSubTaskObjects()
subTasks.each {
if (it.statusObject.name != "Closed") {
log.debug "status of subtask is $it.statusObject.name"
def issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.with {
setResolutionId(parentResolution) // resolution to be set to same as parent resolution
setComment("Closing with as a result of the parent issue being closed.")
setSkipScreenCheck(true)
}
// validate and transition subtask
def validationResult = issueService.validateTransition(user, it.id, 161, issueInputParameters)
if (validationResult.isValid()) {
def issueResult = issueService.transition(user, validationResult)
if (!issueResult.isValid()) {
log.warn("Failed to transition subtask ${it.key}, errors: ${issueResult.errorCollection}")
}
} else {
log.warn("Could not transition subtask ${it.key}, errors: ${validationResult.errorCollection}")
}
}
}
Have a great weekend!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Good job! :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Laurie,
Thank you for the script, I believe I found why you are running into such errors. There are several problems with the current script:
1) In variable *parentResolution* you were getting a Resolution Name.
def parentResolution issue.getResolutionObject().getName()
2) The setResolutionID() is not correct the correct method setResolutionId()
setResolutionID(parentResolution)
1) You would need to replace the *parentResolution* to be as below:
def parentResolution = issue.getResolutionObject()?.getId()
2) Then you need to change the setResolutionID() to be:
setResolutionId(parentResolution)
If you can see from this setResolutionId()|method, it was expecting a resolutionId instead of a name which what we get from Step 1.
Kind regards,
Amirul
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.