Just a heads up: On March 24, 2025, starting at 4:30pm CDT / 19:30 UTC, the site will be undergoing scheduled maintenance for a few hours. During this time, the site might be unavailable for a short while. Thanks for your patience.
×Hello,
I use this Checklists Plugin and I am setting up a listener as they describe here to update the checklist based on the value of another attribute.
The updateValue(CustomField, Issue, Collection<ChecklistItem>) method needs a collection of items to load, and in the proposed solution that collection is built within the script.
I have created templates in the custom field and I am wondering if it would be possible to load them directly instead of building the item collection.
Do any of you know how? Any other proposal?
Thank you in advance!
Hi Reno,
We have not yet made the templates API public, so at the moment there is no documentation on how to use a template within scripts.
The current ways we have made templates useable in your processes are by:
- Using the template as "Default Local Items"
- Using the template in a workflow post function
This said, if your use-case is more specific and requires scripting, I can definitely help you with that! Just keep in mind that our APIs are not public so they can change in any update.
Importing a template essentially requires you to load the template, convert the template items into checklist items, and update the checklist with those items.
Here's a modified version of our documentation that does exactly that. The main difference with the default documentation is the `createItemsFromTemplate` function.
import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.MutableIssue;
@WithPlugin("com.okapya.jira.checklist")
import com.okapya.jira.customfields.*;
import java.util.stream.Collectors;
import com.okapya.jira.customfields.configuration.*;
import org.codehaus.jackson.type.TypeReference;
def Collection<ChecklistItem> createItemsFromTemplate(ChecklistCFType cfType, int templateId) {
TemplatesManager templatesManager = cfType.templatesManager;
Template template = templatesManager.getTemplate(templateId);
return ChecklistItem.mapper.readValue(template.getItems().toJson(), new TypeReference<ArrayList<ChecklistItem>>() {});
}
// Retrieve the Custom Field Type for the Checklist Custom Field
def customFieldManager = ComponentAccessor.getCustomFieldManager();
def checklistCustomField = customFieldManager.getCustomFieldObject("customfield_10203");
def checklistCustomFieldType = (ChecklistCFType) checklistCustomField.getCustomFieldType();
// Create a new checklist
def Collection<ChecklistItem> newChecklistValue = createItemsFromTemplate(checklistCustomFieldType, 29);
// Update the issue with the new checklist
def issue = (MutableIssue) event.issue;
checklistCustomFieldType.updateValue(checklistCustomField, issue, newChecklistValue);
The sample script has hard-coded the ID of the template (29). In order to know the ID of the desired template in you system, I suggest you to edit the template in your browser with the developer console open (F12), and retrieve the ID from the network tab.
We will be looking in the future to add an friendlier API to use templates in scripts, and also to find the template's ID.
I hope this helps! Don't hesitate to ask if you have any additional questions.
Kind regards
Max
Hello Max,
Thank you for the answer, it is what I was looking for!
I tried your code for my listener (modifying the IDs) but the execution is failing. I am using Checklists v5.2.4. Should it work in that version?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Reno,
I believe it should work in that version.
Can you provide information about the failing execution? I will try to help debug your issue.
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Max,
I am quite new with ScriptRunner and I am not yet able to get logs and debug what's happening. If you can suggest something specific I can try :)
And thank you again!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hey Reno,
You can see logs by clicking on the history column of your listener:
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hey Reno,
Interesting, here's what we'll do:
- Provide the initial code you had that added items to the checklist based on another field. I will modify it to work.
- Which events are you linked to? I would expect "Issue Updated" and "Issue Created".
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hey Max,
This is the listener, linked to the "Issue Updated" and "Issue Created" events:
import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.MutableIssue;
@WithPlugin("com.okapya.jira.checklist")
import com.okapya.jira.customfields.*;
import java.util.stream.Collectors;
import com.okapya.jira.customfields.configuration.*;
import org.codehaus.jackson.type.TypeReference;
def Collection<ChecklistItem> createItemsFromTemplate(ChecklistCFType cfType, int templateId) {
TemplatesManager templatesManager = cfType.templatesManager;
Template template = templatesManager.getTemplate(templateId);
return ChecklistItem.mapper.readValue(template.getItems().toJson(), new TypeReference<ArrayList<ChecklistItem>>() {});
}
// Retrieve the Custom Field Type for the Checklist Custom Field
def customFieldManager = ComponentAccessor.getCustomFieldManager();
def checklistCustomField = customFieldManager.getCustomFieldObject("customfield_11309");
def checklistCustomFieldType = (ChecklistCFType) checklistCustomField.getCustomFieldType();
// Create a new checklist
def Collection<ChecklistItem> newChecklistValue = createItemsFromTemplate(checklistCustomFieldType, 29);
// Update the issue with the new checklist
def issue = (MutableIssue) event.issue;
checklistCustomFieldType.updateValue(checklistCustomField, issue, newChecklistValue);
And this is how I got the ID for the template, as you described:
Just to mention, in my final code I will have a switch like in the original article.
Thank you so much for your help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Reno,
It appears that the code only works on our latest version (6.0.0) after all. There's some bizzare typing conflicts with Jackson's "TypeReference" and ScriptRunner.
I've created a different version of the code that works on any version:
import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.MutableIssue;
@WithPlugin("com.okapya.jira.checklist")
import com.okapya.jira.customfields.*;
import java.util.stream.Collectors;
import com.okapya.jira.customfields.configuration.*;
def Collection<ChecklistItem> createItemsFromTemplate(ChecklistCFType cfType, int templateId) {
TemplatesManager templatesManager = cfType.templatesManager;
Template template = templatesManager.getTemplate(templateId);
ArrayList<ChecklistItem> items = new ArrayList<ChecklistItem>();
for (def templateItem in template.getItems()) {
String templateItemJson = ChecklistItem.mapper.writeValueAsString(templateItem);
items.add(ChecklistItem.mapper.readValue(templateItemJson, ChecklistItem.class));
}
return items;
}
// Retrieve the Custom Field Type for the Checklist Custom Field
def customFieldManager = ComponentAccessor.getCustomFieldManager();
def checklistCustomField = customFieldManager.getCustomFieldObject("customfield_10203");
def checklistCustomFieldType = (ChecklistCFType) checklistCustomField.getCustomFieldType();
// Create a new checklist
def Collection<ChecklistItem> newChecklistValue = createItemsFromTemplate(checklistCustomFieldType, 29);
// Update the issue with the new checklist
def issue = (MutableIssue) event.issue;
checklistCustomFieldType.updateValue(checklistCustomField, issue, newChecklistValue);
Also, as a side note: Since you want to change the Checklist value when another field changes, you should take a look at this example to verify if the other field has actually changed before updating the checklist. Otherwise, with our documentation alone, you will always end up overwriting the checklist value on every issue update.
(I will create an internal issue to update our documentation so it better represents this use-case)
Regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Max,
Thank you for the solution! I tried it and it works, I'll keep in mind what you said about this not being part of the public API and the versions (we may update the plugin soon).
About your side note, yes I noticed, what I added is this:
import com.atlassian.jira.event.type.EventType
if(event.eventTypeId == EventType.ISSUE_UPDATED_ID){
def changeItems = ComponentAccessor.changeHistoryManager.getChangeHistoryById(event.changeLog.id as Long).changeItemBeans
if (!changeItems.any { it.field == 'Area' } && !changeItems.any { it.field == 'Work Product Type' }) {
// Skip this listener if the Area and Work Product Type fields were not changed
return
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Reno,
This is good to hear!
I've created tasks in our backlog to improve documentation and also add public APIs for manipulating templates.
EDIT: Here's a method you can use that would replace the bottom part of the "createItemsFromTemplate" method.
com.okapya.jira.customfields.ChecklistSerializer.deserializeChecklist(template.getItemsJson())
Have a nice day too!
Max
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello,
If you have an update about the groovy templates management API implementation, we're waiting about it :)
If found the following method signature, but i do not know the parameters names that must be called:
com.okapya.jira.customfields.configuration.TemplatesManager.getTemplates(java.lang.Integer, java.lang.String, java.lang.Long, java.lang.Long, java.lang.Long)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Julien,
We have since created a sample in our documentation for how to import a template in a checklist:
You should use getTemplate(integer) to get a single template by ID. The other method is for retrieving a list of template from multiple filters.
Kind regards
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Show up and give back by attending an Atlassian Community Event: we’ll donate $10 for every event attendee in March!
Join an Atlassian Community Event!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.