I am creating a postfunction plugin that copy a multi user value from one type of ticket to another ticket. I can copy the other fields fine, but when i copy anythign multi-select I get the following error:
[atlassian.jira.workflow.OSWorkflowManager] Caught exception while attempting to perform action 751 from workflow 18844 on issue 'TEST-3333'
java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.opensymphony.user.User
at com.atlassian.jira.issue.customfields.impl.MultiUserCFType.getStringFromSingularObject(MultiUserCFType.java:152)
Here is my code:
final IssueChangeHolder changeHolder = new DefaultIssueChangeHolder(); ModifiedValue mv = null; ChangeItemBean bean = null; FieldLayoutItem item = null; CustomFieldType cfType = null; Object oldValue = null; Object newValue = null; ArrayList<Object> changeItemBeans = null; //get custom fields that we need to copy over List<CustomField> originalFields = Utilities.getCustomFields(newIssue); issueToBe = issueManager.getIssueObject(oldIssue.getId()); //refresh this issue //update the old ticket with each of the custom field that is in the included list for (CustomField field : originalFields) { cfType = field.getCustomFieldType(); oldValue = oldIssue.getCustomFieldValue(field); newValue = newIssue.getCustomFieldValue(field); if (newValue != null){ mv = new ModifiedValue(oldValue, newValue); bean = new ChangeItemBean(ChangeItemBean.CUSTOM_FIELD, field.getName(), cfType.getStringFromSingularObject(oldValue), cfType.getStringFromSingularObject(oldValue), cfType.getStringFromSingularObject(newValue), cfType.getStringFromSingularObject(newValue)); changeItemBeans = new ArrayList<Object>(); // clear the list changeItemBeans.add(bean); //make the change try { item = fieldLayoutManager.getFieldLayout(oldIssue).getFieldLayoutItem(field); field.updateValue(item, issueToBe, mv, changeHolder); issueToBe.setUpdated(UtilDateTime.nowTimestamp()); issueToBe.store(); } catch (FieldLayoutStorageException e) { log.warn(e.getMessage()); } // now log the changes try { IssueUpdateBean issueUpdateBean = new IssueUpdateBean( issueToBe.getGenericValue(), oldIssue.getGenericValue(),EventType.ISSUE_UPDATED_ID, currUser); issueUpdateBean.setComment(changeHolder.getComment()); issueUpdateBean.setChangeItems(changeItemBeans); issueUpdateBean.setDispatchEvent(true); issueUpdateBean.setParams(EasyMap.build("eventsource", IssueEventSource.ACTION)); componentManager.getIssueUpdater().doUpdate(issueUpdateBean, true); } catch (JiraException e) { log.warn(e.getMessage()); } } }
Any help is greatly appreciated!
Community moderators have prevented the ability to post new answers.
Hi Eva,
The statement
oldValue = oldIssue.getCustomFieldValue(field);
will return a List of om.opensymphony.user.User objects if field is a MultiUserCFType. The method cfType.getStringFromSingularObject
() does not work with lists as the name implies. So if oldvalue is a ist of User objects you should first convert that into something readable like a comma separated list of user names. I'd suggest to replace the the lines
cfType.getStringFromSingularObject(oldValue), cfType.getStringFromSingularObject(oldValue), cfType.getStringFromSingularObject(newValue), cfType.getStringFromSingularObject(newValue));
by
makeString(oldValue,cfType), makeString(oldValue,cfType), makeString(newValue,cfType), makeString(newValue,cfType));
where makeString could look like:
private String makeString (Object value, CustomFieldType cfType) {
if (value instanceof List<User>) {
List<User> users = (List<User>)value;
StringBuilder sb = new StringBuilder();
for (User user: users) {
if (sb.length() > 0) {
sb.append(",");
}
sb.append(cfType.getStringFromSingularObject(user));
}
return sb.toString();
}
return cfType.getStringFromSingularObject(value);
}
sorry for so many edits but i don't get the code formatting work anymore :(
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yes, this should work since a multi-line free text field is not a List<User> and thus everything will fallback to your old code
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
What if the field is a Multi-line free text field? Would this sitll works?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Another quick question - What if I have other multi-values fields? Eclipse doesnt let me to do value instanceof List<Users>, it force me to use List<?>. And w/o knowing what type, I am not sure how to cast it. Any help is appreciated!
Thanks again!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This is the more generic approach that also should handle other multi valued field
private String makeString(Object value, CustomFieldType cfType) {
if (value instanceof Collection<?>) {
Collection<?> objects = (Collection<?>) value;
StringBuilder sb = new StringBuilder();
for (Object object : objects) {
if (sb.length() > 0) {
sb.append(",");
}
sb.append(cfType.getStringFromSingularObject(object));
}
return sb.toString();
}
return cfType.getStringFromSingularObject(value);
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.