Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

ClassCast Exception when copying multi-user field from one issue to another

Eva
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 7, 2011

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!

1 answer

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

0 votes
Answer accepted
Dieter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 7, 2011

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);
}

Dieter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 7, 2011

sorry for so many edits but i don't get the code formatting work anymore :(

Dieter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 13, 2011

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

Eva
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 13, 2011

What if the field is a Multi-line free text field? Would this sitll works?

Eva
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 13, 2011

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!

Dieter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 13, 2011

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);
}

TAGS
AUG Leaders

Atlassian Community Events