Hi,
I am able to add my custom field type (which was added via a plugin by extending MultiSelectCFType) in Jira and associate it with screen and projects. However it does not show up in the screen(eg create issue screen with which it was associated). I populate the MultiSelectCFType with in jira after adding it.
My code for the field is:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import webwork.action.ActionContext;
import com.atlassian.jira.bc.issue.search.SearchService;
import com.atlassian.jira.bc.project.component.ProjectComponent;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.config.FeatureManager;
//import com.atlassian.jira.issue.customfields.impl.*;
//import com.atlassian.jira.issue.customfields.impl.MultiSelectCFType;
import com.atlassian.jira.issue.customfields.impl.MultiSelectCFType;
//import com.atlassian.jira.issue.customfields.impl.GenericTextCFType;
import com.atlassian.jira.issue.fields.rest.json.beans.JiraBaseUrls;
import com.atlassian.jira.issue.customfields.manager.GenericConfigManager;
import com.atlassian.jira.issue.customfields.manager.OptionsManager;
import com.atlassian.jira.issue.customfields.option.Option;
import com.atlassian.jira.issue.customfields.persistence.CustomFieldValuePersister;
import com.atlassian.jira.issue.customfields.persistence.PersistenceFieldType;
import com.atlassian.jira.issue.customfields.impl.FieldValidationException;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.fields.config.FieldConfig;
import com.atlassian.jira.issue.fields.config.FieldConfigScheme;
import com.atlassian.jira.issue.fields.config.manager.FieldConfigSchemeManager;
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem;
import com.atlassian.jira.security.JiraAuthenticationContext;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
public class MyCustomField extends MultiSelectCFType 
{
	private JiraAuthenticationContext authContext;
	private OptionsManager optionsManager;
	
	private static final Logger log = LoggerFactory.getLogger(MyCustomField.class);
    
	public MyCustomField(OptionsManager optionsManager,	CustomFieldValuePersister valuePersister, GenericConfigManager genericConfigManager, JiraBaseUrls jiraBaseUrls, SearchService searchService, FeatureManager featureManager)
	{
		super(optionsManager, valuePersister, genericConfigManager, jiraBaseUrls, searchService, featureManager);
		this.optionsManager = optionsManager;
		this.authContext = authContext;
	}
    
    @Override
    public Map<String, Object> getVelocityParameters(final Issue issue,
                                                     final CustomField field,
                                                     final FieldLayoutItem fieldLayoutItem) 
     {
        final Map<String, Object> params = super.getVelocityParameters(issue, field, fieldLayoutItem);
        //field.getOptions(arg0, arg1)
       params.put("currentUser", authContext.getLoggedInUser().getName() );
          
       params.put("options", ActionContext.getParameters().get(field.getName()) );
       return params;
    }
 }
My plugin description uses two velocity files.
<customfield-type name="My Custom Field" i18n-name-key="my-custom-field.name" key="my-custom-field" class="com.fieldPlugin.jira.customfields.MyCustomField">
    <description key="my-custom-field.description">The My Custom Field Plugin</description>
    <resource name="view" type="velocity" location="templates/view-readonly-user.vm"/>
    <resource name="column-view" type="velocity" location="templates/view-readonly-user.vm"/>
    <resource name="xml" type="velocity" location="templates/view-readonly-user.vm"/>
    <resource name="edit" type="velocity" location="templates/edit-readonly-user.vm"/>
  </customfield-type>
My edit-readonly-user.vm is:
#customControlHeader ($action $customField.id $customField.name $fieldLayoutItem.required
					    $displayParameters)
<select name="$customField.id" id="$customField.id" multiple size="5">
            <option value="-1">None</option>
	#foreach ($option in $options)
            <option value="$option.id">$option.name</option>    
        #end
</select>
#customControlFooter ($action $customField.id $fieldLayoutItem.fieldDescription
					    $displayParameters)
My view-readonly-user.vm is:
$!value
I believe I might be getting the $options in the edit-readonly-user.vm wrong (from code).
Can anyone solve this for me? I have not been able to find a working tutorial for a multi-select custom field which gave the .vm as well.
Thanks
Hi,
Have you implemented getValueFromIssue method. A sample is as below
@Override
public Collection<Option> getValueFromIssue(CustomField field, Issue issue) {
	Collection<Option> retValues = new ArrayList<Option>();
	List<Object> values = customFieldValuePersister.getValues(field, issue.getId(),
					PersistenceFieldType.TYPE_LIMITED_TEXT);
	for (Iterator<Object> iterator = values.iterator(); iterator.hasNext();) {
		Long optionId = Long.valueOf((String)iterator.next());
				retValues.add(optionsManager.findByOptionId(optionId));
}
	return retValues;
}
And in the vm file try using $configs.options
#foreach ($option in $configs.options)
... #end
Tuncay Senturk
Yes I am aware of this funciton, however is it mandatory to override it?
After all I am extending MultiSelectCFType and would not mind using the super class function.
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.
will try it tommorrow
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@TuncayYes I tried the vm part you suggested. It didnt work.
My edit vm is:
#customControlHeader ($action $customField.id $customField.name $fieldLayoutItem.required
                        $displayParameters)
<select name="$customField.id" id="$customField.id" multiple size="5">
    <option value="-1">None</option>
 
    #foreach ($option in $configs.options)
            <option value="$option.id">$option.name</option>    
    #end
</select>
#customControlFooter ($action $customField.id $fieldLayoutItem.fieldDescription
                        $displayParameters)
While my class is:
public class MyCustomField extends MultiSelectCFType 
{
	private JiraAuthenticationContext authContext;
	private OptionsManager optionsManager;
	
	private static final Logger log = LoggerFactory.getLogger(MyCustomField.class);
    
	public MyCustomField(OptionsManager optionsManager,	CustomFieldValuePersister valuePersister, GenericConfigManager genericConfigManager, JiraBaseUrls jiraBaseUrls, SearchService searchService, FeatureManager featureManager)
	{
		super(optionsManager, valuePersister, genericConfigManager, jiraBaseUrls, searchService, featureManager);
		this.optionsManager = optionsManager;
		this.authContext = authContext;
	}
    
    @Override
    public Map<String, Object> getVelocityParameters(final Issue issue,
                                                     final CustomField field,
                                                     final FieldLayoutItem fieldLayoutItem) 
     {
        final Map<String, Object> params = super.getVelocityParameters(issue, field, fieldLayoutItem);
        //field.getOptions(arg0, arg1)
       params.put("currentUser", authContext.getLoggedInUser().getName() );
	   return params;
	   }
};
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Also I tried putting in this function as is you suggested in the class:
@Override
public Collection<Option> getValueFromIssue(CustomField field, Issue issue) {
    Collection<Option> retValues = new ArrayList<Option>();
    List<Object> values = customFieldValuePersister.getValues(field, issue.getId(),
                    PersistenceFieldType.TYPE_LIMITED_TEXT);
 
    for (Iterator<Object> iterator = values.iterator(); iterator.hasNext();) {
        Long optionId = Long.valueOf((String)iterator.next());
                retValues.add(optionsManager.findByOptionId(optionId));
}
 
    return retValues;
}
still the field doesnt show.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for the sample @Tuncay.
The field doenst show up on the screen even when the type has been added.
One thing to know is that when I edit the custom field and go the edit custom field details from JIRA,
it says:
There are no search templates for this custom field type.
Could that be the problem?
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.
I have been able to find out the reason why it was not working.
In the getVelocityParameters function of the class I was doing:
params.put("currentUser", authContext.getLoggedInUser().getName() );
For some reason with that particular statement present the class extended from MultiSelectCFType would not show.
@jobin kuruvilla[Go2Group]
I used your tutorial on how to make a custom field type where you made a class: ReadOnlyUserCF extends GenericTextCFType and used the statement :
params.put("currentUser", authContext.getLoggedInUser().getName() );
for illustration. It didnt give any problems displaying the field on the screen however when extending from MultiSelectCFType this prevents the field from even displaying.
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.
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.