Multi select custom field saves the value in DB whenever the issue is updated, eventhough it is null

Prasad Sekar June 26, 2019

I'm trying to write a Multi Project Picker custom field using plugin development. I have pulled all the projects and listed in the UI and saved the custom field with two projects. everything was successful.

 

But, the issue i'm facing right now is - In UI Edit screen, i'm just clicking the Update button without modifying any of the values. But in DB a new entry is created like the previous values are deleted and again the same two selected projects was pushed as new entry.

 

getValueFromCustomFieldParams function by default it stored the value into DB. How can i stop this?? I want a solution like if the custom field value gets changed only means the value should be updated in the DB.

 

Here is attached the History of the issue. 

 

image.png


Java file:

package com.athena.plugins.jira_features.jira.customfields;

import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.customfields.impl.AbstractMultiCFType;
import com.atlassian.jira.issue.customfields.impl.FieldValidationException;
import com.atlassian.jira.issue.customfields.manager.GenericConfigManager;
import com.atlassian.jira.issue.customfields.persistence.CustomFieldValuePersister;
import com.atlassian.jira.issue.customfields.persistence.PersistenceFieldType;
import com.atlassian.jira.issue.customfields.view.CustomFieldParams;
import com.atlassian.jira.issue.fields.config.FieldConfig;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.project.ProjectManager;
import com.atlassian.jira.util.ErrorCollection;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import java.util.*;
import java.lang.Object;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;

@Scanned
public class MultiProjectPickerField extends AbstractMultiCFType<String> {

@ComponentImport
private ProjectManager projectManager;

public MultiProjectPickerField(
@ComponentImport CustomFieldValuePersister customFieldValuePersister,
@ComponentImport GenericConfigManager genericConfigManager,
@ComponentImport ProjectManager projectManager
) {
super(
customFieldValuePersister,
genericConfigManager
);
this.projectManager = projectManager;
}

@Override
protected Comparator<String> getTypeComparator() {
return null;
}

@Override
protected Object convertTypeToDbValue(String value) {
return value;
}

@Override
protected String convertDbValueToType(Object dbValue) {
return (String) dbValue;
}

@Override
protected PersistenceFieldType getDatabaseType() {
return PersistenceFieldType.TYPE_LIMITED_TEXT;
}

@Override
public String getStringFromSingularObject(String stringFormObject) {
return stringFormObject;
}

@Override
public String getSingularObjectFromString(String objectFromString) throws FieldValidationException {
return objectFromString;
}

@Override
public void validateFromParams(CustomFieldParams customFieldParams, ErrorCollection errorCollection, FieldConfig fieldConfig) {
}

@Override
@SuppressWarnings("unchecked")
public Collection<String> getValueFromCustomFieldParams(CustomFieldParams customFieldParams) throws FieldValidationException {
return customFieldParams.getAllValues();
}

public Map<String, Object> getVelocityParameters(
final Issue issue,
final CustomField field,
final FieldLayoutItem fieldLayoutItem
) {
final Map<String, Object> velocityParams = super.getVelocityParameters(issue, field, fieldLayoutItem);

// This method is also called to get the default value, in
// which case issue is null so we can't use it
if (field != null && issue != null) {
final Map<String, String> selectedProjectsMap = new HashMap<>();
List<String> projects = new ArrayList<>();
for (final Project project : projectManager.getProjectObjects()) {
projects.add(project.getName());
}
velocityParams.put("projects", projects);
ArrayList testing = (ArrayList) field.getValue(issue);
try {
for (Object o : testing) {
String str = (String) o;
selectedProjectsMap.put(str, projectManager.getProjectObjByName(str).getKey());
}
} catch (Exception e) {
}
velocityParams.put("selectedProjects", selectedProjectsMap);
}
return velocityParams;
}
@Override
public Object getStringValueFromCustomFieldParams(CustomFieldParams customFieldParams) {
return customFieldParams.getValuesForNullKey();
}
}

 

Edit.VM


#controlHeader ($action $customField.id $customField.name $fieldLayoutItem.required $displayParameters.noHeader)
<select class="select cf-select" size="5" id="$customField.id" name="$customField.id" multiple="multiple">
#foreach($project in $projects)
#set($selected = false)
#if($selectedProjects && $selectedProjects.keySet().contains($project))
#set($selected = true)
#end
<option
#if($selected)
selected="selected"
#end
title="$!project" value="$!project">$!project
</option>
#end
</select>
#controlFooter ($action $fieldLayoutItem.fieldDescription $displayParameters.noHeader)
C

 

 

 

2 answers

0 votes
Sunny Lord July 24, 2019

Thanks for sharing

0 votes
Sunny Lord July 24, 2019

thanks for the information . . .

Suggest an answer

Log in or Sign up to answer