- Introduction
- About
- Get started
- Migration to Cloud
- Bundled Fields
- Bundled Fields Overview
- Adding Bundled Fields
- Bundled Fields Configuration
- Format and validation
- Using Bundled Fields
- Advanced settings
- Bundled Fields Searcher
- Java API (ScriptRunner)
- Data Sources
- Email notifications
- Bundled Fields v.6.8.x - 6.9.x
- Bundled Fields v.6.7.x
- Dynamic Forms
- Dynamic Forms
- Supported fields
- Visibility
- Request Types visibility
- Fields visibility
- Customer Portal visibility
- Options visibility
- Requirements visibility
- SLAs visibility
- Java API
- Multilevel Structure
- Configuration
- Using a multilevel structure on the Customer Portal
- User Synchronization
- Organizations and Groups Synchronization
- Issue View
- Issue View
- Add user's IP address post function
- Restart SLA post function
- Update SLA to date post function
- Customer Portal
- Links
- Export list
- Split column
- Request details view
- Additional fields
- Additional options
- Compatibility
- Configuration Manager
Java API (ScriptRunner)
Learn how to use data from Bundled Fields in ScriptRunner
Extension for Jira Service Management allows you to use data from Bundled Fields in ScriptRunner, or any other similar app. You’ll find all possible actions that you can perform this way in the right-hand side navigation menu.
Our API methods are public services that can be used in any code editor. The examples, however, are prepared to match the ScriptRunner’s format in particular. If you’d like to use the methods in other applications, you will need to adjust the code according to their requirements.
We’ve tested all methods in this chapter and made sure that they work in the form provided in the examples. Nevertheless, the support we provide doesn’t include verifying custom scripts. In case of any issues with customized code, we recommend checking out the ScriptRunner documentation, too.
- Currently we don’t support ScriptRunner’s Behaviours.
- To investigate any problems with scripts using Bundled Fields’ API, go to Troubleshooting.
- To see an example of a Bundled Fields’ JSON structure and descriptions of the attributes, go to Examples and definitions.
Before you start, make sure that the Bundled Fields custom field is added to the Edit screen in your workflow. Otherwise, the scripts might not work.
Get bundled field
Get an object representing a bundled field for the given issue object or issue key and the bundled field’s ID.
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
Get bundled field draft
Build an object representing a draft of a bundled field for the given issue object or issue key and the bundled field’s ID:
Bundled field draft objects allow you to make multiple changes (one by one) on a single bundled field object. You can find the list of all available methods that interact with drafts in the List of available signatures and SaveableBundledField below. After all changes are made on a bundled field, commit them by calling the save function.
def bundledFieldDraft = bundledFieldService.getBundledFieldDraft(issueOrKey, bundledFieldId)
You can make changes by using:
bundledFieldDraft.setSubfieldValue("Subfield name 1", "Value in every Subfield name 1 in all groups");
bundledFieldDraft.setSubfieldValue("Subfield name 2", "Value in every Subfield name 2 in all groups");
bundledFieldDraft.setSubfieldValue("Subfield name 1", "Value in Subfield name 1 in first group", 0);
You need to save to apply changes:
bundledFieldDraft.save()
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.deviniti.plugins.bundledfields.api.issue.BundledFieldService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.deviniti.plugins.bundledfields.api.issue.Subfield
String issueOrKey = 'TEST-38'
String bundledFieldId = "customfield_12000"
@WithPlugin("com.intenso.jira.plugin.jsd-extender")
@PluginModule
BundledFieldService bundledFieldService;
def bundledFieldDraft = bundledFieldService.getBundledFieldDraft(issueOrKey, bundledFieldId);
bundledFieldDraft.setSubfieldValue("Subfield name 1", "Value in every Subfield name 1 in all groups");
bundledFieldDraft.setSubfieldValue("Subfield name 2", "Value in every Subfield name 2 in all groups");
bundledFieldDraft.setSubfieldValue("Subfield name 1", "Value in Subfield name 1 in first group", 0);
bundledFieldDraft.save();
Get subfield
Get a subfield object for the given name and group index.
def subField = bundledField.getSubfield("Name", 0)
Groups numbering starts from 0.
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
def subField = bundledField.getSubfield("Name", 0)
You can also retrieve a subfield by its originId. Learn more
Get group by index
Get a group object using index.
def group = bundledField.getGroup(0)
Rows numbering starts from 0.
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
def group = bundledField.getGroup(0)
Get all groups of a field
Get a list of all groups of a bundled field.
def groups = bundledField.getGroups()
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
def groups = bundledField.getGroups()
Add new group with subfields
Add a new group containing subfields from the list defined above. Either the value and originId, or the name will be recognized.
If you want to perform this type of action on the bundledField object more than once, consider using the draft method.
def newGroupFields = [
Subfield.builder()
.originId("7a23604a-c78a-4a54-b5ff-9f92175ba7a7")
.value("John")
.build(),
Subfield.builder()
.name("Date of arrival")
.value(new Date())
.build(),
Subfield.builder()
.originId("f9ad017e-df32-4b7a-8120-ef1e9e8fff36")
.value(['fdd8d043-f13b-4d71-8ea3-1f838e7c178b'])
.build()
]
bundledField.addGroup(newGroupFields)
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
def newGroupFields = [
Subfield.builder()
.originId("7a23604a-c78a-4a54-b5ff-9f92175ba7a7")
.value("John")
.build(),
Subfield.builder()
.name("Date of arrival")
.value(new Date())
.build(),
Subfield.builder()
.originId("f9ad017e-df32-4b7a-8120-ef1e9e8fff36")
.value(['fdd8d043-f13b-4d71-8ea3-1f838e7c178b'])
.build()
]
bundledField.addGroup(newGroupFields)
Override - copy field value
This method overrides fields on which it is used and generates new group/subfield identifiers.
Subfields that receive no value from the source field are cleared. A field needs to have the same name or be mapped to receive a value.
Exceptions:
- A source field has a different number of groups (min/max groups)
- A designated subfield is required and won’t receive a value (or the value will be empty)
- Invalid value type
There are two options:
- Search for names (a field that you want to copy must have the same subfield names)
targetBF.override(sourceBF)
- Transfer name or originId subfield mapping (can be useful when subfield names are different, in this case you can connect two subfields so the mechanism knows which subfield should be considered in terms of value).
def subfieldMappings = [
"date time picker subfield": "date time 2",
"385dffb9-6d11-433d-9a97-4cc72200e3e7": "4785ef1c-04e5-4d55-bf6e-c7dae781af31"
]
targetBF.override(sourceBF, subfieldMappings);
targetBF.save()
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String sourceIssueKey = 'DF-2'
String targetIssueKey = 'TEST-14'
String bundledFieldId= "customfield_10500"
def sourceBF = extensionBundledService.getBundledFieldDraft(sourceIssueKey, bundledFieldId)
def targetBF = extensionBundledService.getBundledFieldDraft(targetIssueKey, bundledFieldId)
targetBF.override(sourceBF);
targetBF.save()
Remove group by parameter
Remove a group of the given parameter.
If you want to perform this type of action on the bundledField object more than once, consider using the draft method.
bundledField.removeGroup(group)
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
def group = bundledField.getGroup(0)
bundledField.removeGroup(group)
Remove group by index
Remove a group of the given index.
If you want to perform this type of action on the bundledField object more than once, consider using the draft method.
bundledField.removeGroup(2)
Rows numbering starts from 0.
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
bundledField.removeGroup(2)
Remove first group
Remove the first group - respectively to removeGroup(0).
If you want to perform this type of action on the bundledField object more than once, consider using the draft method.
bundledField.removeFirstGroup()
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
bundledField.removeFirstGroup()
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
bundledField.removeFirstGroup()
Remove last group
Remove the first group - respectively to removeGroup(bundledField.getGroups().size() - 1)
If you want to perform this type of action on the bundledField object more than once, consider using the draft method.
bundledField.removeLastGroup()
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
bundledField.removeLastGroup()
Example of retrieving values from selected options, using select and checkbox subfields
Here’s how to get subfield values from the first group in an issue with two groups and two subfields.
Exemplary Bundled Fields’ configuration
Exemplary script for getting subfield values in the first group
import com.deviniti.plugins.bundledfields.api.issue.BundledField
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.deviniti.plugins.bundledfields.api.issue.CheckboxField
import com.deviniti.plugins.bundledfields.api.issue.SelectField
import com.deviniti.plugins.bundledfields.api.issue.Option
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import org.apache.log4j.Logger
import org.apache.log4j.Level
log.setLevel(Level.DEBUG)
String ISSUE_OR_KEY = "DFT-67";
String EXT_BF_CUSTOM_FIELD_ID = "customfield_15500";
int FIRST_GROUP = 0;
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
BundledField ext_bf = extensionBundledService.getBundledField(ISSUE_OR_KEY, EXT_BF_CUSTOM_FIELD_ID);
String selectFieldName = "Select Field 1";
def selectField1 = ext_bf.getSubfield(selectFieldName, FIRST_GROUP)
if (selectField1 instanceof SelectField) {
Option selectedOption = selectField1.getSelectedOption()
log.debug("Value of \""+selectFieldName+"\" in group " + FIRST_GROUP + ":")
log.debug("Id: " + selectedOption.getId())
log.debug("Name: " + selectedOption.getName())
}
log.debug("---------")
String checkboxFieldName = "Checkbox Field 1";
def checkboxField1 = ext_bf.getSubfield(checkboxFieldName, FIRST_GROUP)
if (checkboxField1 instanceof CheckboxField) {
List<Option> selectedOptions = checkboxField1.getSelectedOptions();
log.debug("Values of \""+checkboxFieldName+"\" in group " + FIRST_GROUP + ":")
for(selectedOption in selectedOptions){
log.debug("Id: " + selectedOption.getId())
log.debug("Name: " + selectedOption.getName())
}
}
Output
2022-01-13 13:56:05,096 DEBUG [runner.ScriptBindingsManager]: Value of "Select Field 1" in group 0:
2022-01-13 13:56:05,096 DEBUG [runner.ScriptBindingsManager]: Id: 0ec8f0ce-1ee5-4a50-90f5-0e459efa5fb7
2022-01-13 13:56:05,096 DEBUG [runner.ScriptBindingsManager]: Name: One
2022-01-13 13:56:05,096 DEBUG [runner.ScriptBindingsManager]: ---------
2022-01-13 13:56:05,098 DEBUG [runner.ScriptBindingsManager]: Values of "Checkbox Field 1" in group 0:
2022-01-13 13:56:05,098 DEBUG [runner.ScriptBindingsManager]: Id: 09f2a202-028b-4b32-a832-98e6786bce4b
2022-01-13 13:56:05,098 DEBUG [runner.ScriptBindingsManager]: Name: One
2022-01-13 13:56:05,098 DEBUG [runner.ScriptBindingsManager]: Id: 418270b4-f965-4e3f-bff0-308b54f721bb
2022-01-13 13:56:05,098 DEBUG [runner.ScriptBindingsManager]: Name: Two
Set subfield value in all groups
Set a value for a subfield in all groups (without defining the index).
If you want to perform this type of action on the bundledField object more than once, consider using the draft method.
Type of the value must be compatible with the configured field’s type.
bundledField.setSubfieldValue("Name", "Jane Doe")
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
bundledField.setSubfieldValue("Name", "Jane Doe")
Set subfield value in a group
Set a value for a subfield in a group (with a defined index).
If you want to perform this type of action on the bundledField object more than once, consider using the draft method.
bundledField.setSubfieldValue("Name", "Jane Doe", 2)
Example
import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = 'TEST-38'
String bundledFieldId= "customfield_12000"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
bundledField.setSubfieldValue("Name", "Jane Doe", 2)
List of available signatures
BundledFieldService
BundledField getBundledField(String issueOrKey, String customFieldId);
BundledField getBundledField(Issue issue, String customFieldId);
SaveableBundledField getBundledFieldDraft(String issueOrKey, String customFieldId);
SaveableBundledField getBundledFieldDraft(Issue issue, String customFieldId);
BundledField
If you want to perform below methods on the bundled field object more than once, consider using the SaveableBundledField
type.
Subfield getSubfield(String name, int groupIndex)
Group getGroup(int groupIndex)
List<Group> getGroups()
void setSubfieldValue(String name, Object value)
void setSubfieldValue(String name, Object value, int groupIndex)
void addGroup(List<Subfield> fields)
void removeGroup(int groupIndex)
void removeGroup(Group group)
void removeFirstGroup()
void removeLastGroup()
SaveableBundledField
You can find here a list of methods designed to make multiple changes (one by one) to a single bundled field object. After all changes are made on a bundled field, commit them by calling the save function.
Subfield getSubfield(String name, int groupIndex)
Group getGroup(int groupIndex)
List<Group> getGroups()
void setSubfieldValue(String name, Object value)
void setSubfieldValue(String name, Object value, int groupIndex)
void addGroup(List<Subfield> fields)
void removeGroup(int groupIndex)
void removeGroup(Group group)
void removeFirstGroup()
void removeLastGroup()
void save()
Group
String getId()
List<Subfield> getFields()
Subfield
String getId()
String getOriginId()
Object getValue()
String getName()
String getType()
Correct values for each type
Subfield type | Supported data type | Additional conditions |
---|---|---|
TEXT | String | Maximum length 255 characters. Value should be compatible with a regular expression, mask, or set formatting (for example, number for the Currency type). |
TEXTAREA | String | |
USER | String | Contains a key of a user existing in Jira |
SELECT | String | Contains ID/Name of the configured option. |
CHECKBOX | Iterable | Collection of IDs/Names of the configured options. |
DATE | Date | |
DATETIME | Date | |
TIME | Date |
Use a null or an empty string to clear the value.
Validation
ScriptRunner Validation is possible with a method overloading script within the BundledFieldService
. It allows you to use a specific object from a postfunction (or validation) that’s being executed during transition.
BundledField getBundledField(Issue issue, String customFieldId)
Example
Here’s an example of validating a certain word as forbidden.
Script
Result
The ScriptRunner postfunction must be placed below the “Update change history for an issue and store the issue in the database” step:
Otherwise, the value you’ve defined in the script will be overwritten by the value from the screen assigned to the transition.
Tip: Removing the field from the screen solves this problem, too.
Classes representing subfield types
All classes listed in the below table inherit from the Subfield
object and get retrieved by the BundledField
object’s methods, depending on their type.
derived class | subfield’s type | path | methods defined in the class |
---|---|---|---|
CheckboxField |
checkbox | import com.deviniti.plugins.bundledfields.api.issue.CheckboxField |
List<Option> getSelectedOptions |
SelectField |
select | import com.deviniti.plugins.bundledfields.api.issue.SelectField |
Option getSelectedOption |
DateField |
date, datetime, time | import com.deviniti.plugins.bundledfields.api.issue.DateField |
|
TextField |
textarea, text | import com.deviniti.plugins.bundledfields.api.issue.TextField |
|
UserField |
user | import com.deviniti.plugins.bundledfields.api.issue.UserField |
Example of using the returned SelectField type
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.deviniti.plugins.bundledfields.api.issue.Subfield
import com.deviniti.plugins.bundledfields.api.issue.CheckboxField
import com.deviniti.plugins.bundledfields.api.issue.SelectField
import com.deviniti.plugins.bundledfields.api.issue.Option
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String issueOrKey = "TEST-1"
String bundledFieldId= "customfield_10200"
def bundledField = extensionBundledService.getBundledField(issueOrKey, bundledFieldId)
Subfield subField = bundledField.getSubfield("select", 0)
if (subField instanceof SelectField) {
Option selectedOption = subField.getSelectedOption()
log.info(selectedOption.getName())
}
Methods available in the returned Option object
String getId()
String getName()
SubfieldUtils Class
This class contains additional methods for checking the type of a Subfield object and casting it to a specific derived class. If the subfield is of a different type than the one listed in the table in the first section, the following exception is thrown: SubfieldClassCastException
to inform about the conflict: %s subfield cannot be cast to %s subfield
.
SubfieldUtils path
import com.deviniti.plugins.bundledfields.api.issue.utils.SubfieldUtils;
SubfieldUtils methods
boolean isCheckbox(Subfield subfield)
boolean isSelect(Subfield subfield)
boolean isDate(Subfield subfield)
boolean isText(Subfield subfield)
boolean isUser(Subfield subfield)
CheckboxField toCheckboxField(Subfield subfield)
SelectField toSelectField(Subfield subfield)
DateField toDateField(Subfield subfield)
TextField toTextField(Subfield subfield)
UserField toUserField(Subfield subfield)
Implementation of the toString method in classes: Group, Subfield, and Option
When you type any of the above mentioned objects into the console you will be able to immediately see all the information it contains, for example:
Group(id=baseGroupId, fields=[TextField(super=Subfield(id=b0603214-7ab4-4880-9a9a-ba14d3c26156, originId=b0603214-7ab4-4880-9a9a-ba14d3c26156, value=Some value, name=text field, type=text)), SelectField(super=Subfield(id=740bf7fc-1f6e-475e-93a0-986f0f4ebb4e, originId=740bf7fc-1f6e-475e-93a0-986f0f4ebb4e, value=[6a559b54-7821-40f8-bb11-ce78d0ee8f19], name=select, type=select), selectedOption=Option(id=6a559b54-7821-40f8-bb11-ce78d0ee8f19, name=s2))])
Retrieving a field by originId
In most cases, retrieving a field by its name will be enough but we also provide the possibility to retrieve a field by its originId when using the getSubfield and setSubfieldValue methods.
Differences between ID and originId
Please note that the originId of a subfield differs from its ID. Here are the definitions:
- originId – indicator of a subfield existing in the configuration as its identifier
- ID – is an identifier of a subfield within the Bundled Fields custom field (unique across all groups)
How to find originId
There is a number of places you can get the originId from:
- ScriptRunner console. You’ll see the originId in the Result tab after retrieving a group:
- Database. You’ll find the originId in the
AO_2AE210_JSD_BUNDLED_FIELD
table. Navigate to theFIELD_ID
column and select a specific record based on the customfield’s ID and its context. - Developer console in browser (Jira issue view, edit issue screen, or configuration screen):
Cases that throw exceptions
- Providing a data type that is not compatible with the configured subfield’s type.
- Exceeding the character limit (255) in a text field (single-line).
- Trying to set a value for the separator (which is a technical field).
- Providing a non-existent option as a value.
- Providing a userKey of a non-existent user.
- Providing a non-existent subfield name.
- Providing a non-existent group index.
- Providing an empty value for a required subfield.
- Providing a value that is not compatible with the defined formatting, regular expression, or value mask.
- Trying to exceed the configured number of groups for an issue.
- Trying to create a new group without a required subfield.
- Trying to perform an operation on a Bundled Field that hasn’t been configured (no configuration of such field has ever been saved).
- Error during form validation while trying to update the issue (the possible reason may be a globally required field that hasn’t been filled).
Data types for date-specific custom fields
Before inserting a date-type sub-field value into a Date Picker/Date Time Picker custom field , you need to convert: java.util.Date
-> java.sql.Timestamp
- Value type custom field Date Picker and Date Time Picker is
java.sql.Timestamp
- Value type sub-field Date Picker and Date Time Picker is
java.util.Date
Below is a script showing how you can set the value in custom fields.
In the script:
- copying Date Picker sub-field value → Date Picker type custom field
- copying sub-field Date Time Picker value → Date Time Picker type custom field
- each stage of value retrieving and conversion has been reflected in logs to illustrate what happens in each step.
import org.apache.log4j.Level
import java.sql.Timestamp
import java.util.Date
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.component.ComponentAccessor
import com.intenso.jira.plugins.bundledfields.api.ExtensionBundledService
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
log.setLevel(Level.DEBUG)
@WithPlugin("com.intenso.jira.plugins.jsd-extender")
@PluginModule
ExtensionBundledService extensionBundledService
String ISSUE_OR_KEY = 'EXP-2'
String BUNDLED_FIELD_ID = "customfield_13300"
String DATE_PICKER_CUSTOM_FIELD_ID = "customfield_13301"
String DATE_TIME_PICKER_CUSTOM_FIELD_ID = "customfield_13302"
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();
IssueManager issueManager = ComponentAccessor.getIssueManager();
CustomField dateCustomField = customFieldManager.getCustomFieldObject(DATE_PICKER_CUSTOM_FIELD_ID);
CustomField dateTimeCustomField = customFieldManager.getCustomFieldObject(DATE_TIME_PICKER_CUSTOM_FIELD_ID);
Issue currentIssue = issueManager.getIssueObject(ISSUE_OR_KEY);
ApplicationUser currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();
def bundledField = extensionBundledService.getBundledField(ISSUE_OR_KEY, BUNDLED_FIELD_ID)
def dateSubfield = bundledField.getSubfield("Date Field 1", 0)
log.debug('Bundled Field DateField object: ' + dateSubfield)
log.debug('Bundled Field DateField value: ' + dateSubfield.getValue())
log.debug('Bundled Field DateField type: ' + dateSubfield.getValue().getClass())
log.debug('');
def dateTimeSubfield = bundledField.getSubfield("Date Time Field 1", 0)
log.debug('Bundled Field DateTimeField object: ' + dateTimeSubfield)
log.debug('Bundled Field DateTimeField value: ' + dateTimeSubfield.getValue())
log.debug('Bundled Field DateTimeField type: ' + dateTimeSubfield.getValue().getClass())
log.debug('');
Object customfieldDate = dateCustomField.getValue(currentIssue)
log.debug("Custom Field Date Picker value: " + customfieldDate);
log.debug("Custom Field Date Picker type: " + customfieldDate.getClass());
log.debug('');
Object customfieldDateTime = dateTimeCustomField.getValue(currentIssue)
log.debug("Custom Field Date Time Picker value: " + customfieldDateTime);
log.debug("Custom Field Date Time Picker type: " + customfieldDateTime.getClass());
log.debug('');
Timestamp convertedDate = toTimeStamp((Date)dateSubfield.getValue());
Timestamp convertedDateTime = toTimeStamp((Date)dateTimeSubfield.getValue());
log.debug("Bundled Field DateField converted to SQL Timestamp: " + convertedDate)
log.debug("Bundled Field DateTimeField converted to SQL Timestamp: " + convertedDateTime)
//update issue
currentIssue.setCustomFieldValue(dateCustomField, convertedDate);
currentIssue.setCustomFieldValue(dateTimeCustomField, convertedDateTime);
issueManager.updateIssue(currentUser, currentIssue, EventDispatchOption.DO_NOT_DISPATCH, false);
log.setLevel(Level.ERROR)
Timestamp toTimeStamp(Date date) {
return new java.sql.Timestamp(date.getTime());
}
Need help?
If you can’t find the answer you need in our documentation, raise a support request. Include as much information as possible to help our support team resolve your issue faster.