how can I manage all custom fields in Jira instance

Is there a way of representing graphically which custom fields are being used by what screen schemes and which projects?? I know the admin screens for custom fields gives you this information but it's difficult to get a holistic view of the relationships. Having some graphs or tables would really help me understand and monitor what custom fields are being used and by which project; this in turn would allow me to monitor custom field creation and usage across a (growing) number of 'expert users' we have in our organisation (who all have admin privs). These guys have the ability to tailor projects to suite their business area but the down side to this flexibility is over time it gets more and more difficult to co-ordinate and manage........I was thinking that maybe the Dataplane plugin could help but thought I'd ask the wider community first...

2 answers

Cool - thanks for your prompt and detailed reply Vasiliy!! Do you know if the JIRA dev team are thinking of adding this kind of functionality into the standard JIRA offering?? I'm guessing other people must have come across this kind of problem, especially when managing large JIRA instances......

Vasiliy Zverev Community Champion Nov 30, 2015

I am glad to help you.

0 votes
Vasiliy Zverev Community Champion Nov 29, 2015

Hi Graeme!

I faced similar question once and I wrote a script to find specified string into workflows. May it could help you. You need ScriptRunner to use it. It is free for JIRA 6.0 and not free for JIRA 7.0.

package Workflow

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.security.roles.ProjectRole
import com.atlassian.jira.workflow.JiraWorkflow
import com.atlassian.jira.workflow.WorkflowManager
import com.opensymphony.workflow.loader.*

/**
 * Created by VZverev on 02.06.2015.
 *
 * Script for searching of concrete string into bisness-pricess
 * For all elements it is recuared to use element id
 */

String searchedStr = "11800" //this string will be searched

WorkflowManager workflowManager = ComponentAccessor.getWorkflowManager();
ArrayList<JiraWorkflow> jiraWorkflowList = new ArrayList<JiraWorkflow>();
jiraWorkflowList = workflowManager.getWorkflows()
//jiraWorkflowList.add(workflowManager.getWorkflow("WF.KIS.Dev"));//) JiraWorkflow curWF =

ArrayList<WorkFlowActionRecord> actionRecords = new ArrayList<WorkFlowActionRecord>();

//A loop on all actions
for (JiraWorkflow curWF: jiraWorkflowList) {
    if(curWF.isActive())
        for (ActionDescriptor wfActDescr : curWF.getAllActions()) {
            if (wfActDescr.getRestriction() != null)
                addConditionToArrayList(wfActDescr.getRestriction().getConditionsDescriptor().getConditions(), actionRecords, curWF.getName() + ": " + wfActDescr.getName());

            addValidatorToArrayList(wfActDescr.getValidators(), actionRecords, curWF.getName() + ": " + wfActDescr.getName());
            addPostFunctionToArrayList(curWF.getPostFunctionsForTransition(wfActDescr), actionRecords, curWF.getName() + ": " + wfActDescr.getName());
        }
}

//Вывод результата
StringBuilder forExcel = new StringBuilder("Begin");
for (WorkFlowActionRecord wfActRec : actionRecords) {
    if (wfActRec.isIncludeThisString(searchedStr))
        forExcel.append("\n" + wfActRec.toString());
}

return forExcel.toString();

/**
 * The class for storing action of WorkFlow
 */
public class WorkFlowActionRecord {
    private String actionName;
    private String type;
    private String value;

    private HashMap<String, String> args;

    //for search of conrete objects
    private CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();
    private ProjectRole    projectRoles = ComponentAccessor.getComponent(ProjectRole.class);

    public WorkFlowActionRecord(String _actionName, String _type, String _name) {
        actionName = _actionName;
        type = _type;
        value = _name;
        args = new HashMap<>();
    }

    public void AddArg(String _argName, String _argVal) {
        args.put(_argName, _argVal + tryToDecrVal(_argVal)  );
    }

    public boolean isIncludeThisString(String _SearchString) {
        if ((type.indexOf(_SearchString) > -1) | value.indexOf(_SearchString) > -1)
            return true
        else {
            if (args.size() > 0) {
                Iterator iterator = args.entrySet().iterator();
                Map.Entry entry;
                while (iterator.hasNext()) {
                    entry = (Map.Entry) iterator.next();
                    if ((entry.getKey().toString().indexOf(_SearchString) > -1)
                            | (entry.getValue().toString().indexOf(_SearchString) > -1))
                        return true
                }
            } else
                return false;
        }
    }

    public String toString() {
        String result = actionName + ": " + type + ": " + value;
        if (args.size() > 0) {
            Iterator iterator = args.entrySet().iterator();
            Map.Entry entry;

            while (iterator.hasNext()) {
                entry = (Map.Entry) iterator.next();
                result += "/arg = " + entry.getKey() + " val = " + entry.getValue();
            }
        }
        return result;
    }

    private String tryToDecrVal(String _input){

        if ( _input.indexOf('customfield_') == 0 )
        {
            return "(custom field: " + customFieldManager.getCustomFieldObject( Long.parseLong( _input.substring('customfield_'.length(),'customfield_'.length() + 5 ))) + ")"
        }
        return "";
    }
}
/***
 * Adds a condition to given List
 * @param _addedList
 * @param _addHereList
 * @param _actionName
 */
public void addConditionToArrayList(List _addedList, List _addHereList, String _actionName)
{
    WorkFlowActionRecord wfActRec;
    ConditionDescriptor cndDescr;
    int cndPackCnt = 0; //condition package number

    for(int i = 0; i < _addedList.size(); ++i)
    {
        if (_addedList.get(i).class == ConditionDescriptor ) {
            cndDescr = (ConditionDescriptor) _addedList.get(i);
            wfActRec = new WorkFlowActionRecord(_actionName, "condition " + cndDescr.getType(), cndDescr.getName());

            iterator = cndDescr.getArgs().entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                wfActRec.AddArg(entry.getKey(), entry.getValue());
            }
            _addHereList.add(wfActRec);
        }
        else
        {
            List cndDescrLst = ((ConditionsDescriptor) _addedList.get(i)).getConditions();
            ++cndPackCnt;

            for(int iCnd = 0; iCnd < cndDescrLst.size(); ++iCnd)
            {
                cndDescr = (ConditionDescriptor) cndDescrLst.get(iCnd)
                wfActRec = new WorkFlowActionRecord(_actionName, "condition pack " + cndPackCnt + cndDescr.getType(), cndDescr.getName());

                iterator = cndDescr.getArgs().entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry entry = (Map.Entry) iterator.next();
                    wfActRec.AddArg(entry.getKey(), entry.getValue());
                }

                _addHereList.add(wfActRec);
            }
        }
    }

}

/**
 * Adds a validater to List
 * @param _addedList
 * @param _addHereList
 * @param _actionName
 */
public void addValidatorToArrayList(List _addedList, List _addHereList, String _actionName) {
    WorkFlowActionRecord wfActrec;
    Iterator iterator;
    for (int i = 0; i < _addedList.size(); ++i) {
        ValidatorDescriptor validatorDescriptor = (ValidatorDescriptor) _addedList.get(i);

        wfActrec = new WorkFlowActionRecord(_actionName, "validator: " + validatorDescriptor.getType(), validatorDescriptor.getName());

        iterator = validatorDescriptor.getArgs().entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            wfActrec.AddArg(entry.getKey(), entry.getValue());
        }
        _addHereList.add(wfActrec);
    }
}

/**
 * Adds a postFunction to specified list
 * @param _collection
 * @param _addHereList
 * @param _actionName
 */
public void addPostFunctionToArrayList(Collection _collection, List _addHereList, String _actionName) {
    Iterator iterator;
    List Functions = _collection.toList();
    FunctionDescriptor fnDescr;
    WorkFlowActionRecord wfActRec;
    for (int i = 0; i < Functions.size(); ++i) {
        fnDescr = (FunctionDescriptor) Functions.get(i);

        wfActRec = new WorkFlowActionRecord(_actionName, "postfunction " + fnDescr.getType(), fnDescr.getType());

        iterator = fnDescr.getArgs().entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            wfActRec.AddArg(entry.getKey(), entry.getValue());

        }

        _addHereList.add(wfActRec);
    }
}

Suggest an answer

Log in or Sign up to answer
Community showcase
Posted Tuesday in Statuspage

How do your teams prepare for really high (planned) traffic days like Cyber Monday?

Hi there! Shannon from Statuspage here.  👋  With Cyber Monday quickly approaching, we're looking to hear from Atlassian customers – specifically from teams who touch incident response li...

58 views 0 5
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you