Tutorial - Creating a custom field type

Level of experience BEGINNER
Time estimate 0:30
Atlassian application JIRA 4.X+

On this page:

Tutorial overview

This tutorial shows you how to create a new custom field type for JIRA using the plugin development platform. You'll create a custom field that can only be edited as an admin user. Your custom field will be written and installed as a JIRA plugin, and include a Java class that extends the GenericTextCFT class. You'll use a Velocity template, a format that combines Java and HTML, to render your field and control who can edit or view the field. To tether your Java class and template together, you'll define both in a single customfield-type plugin module in your atlassian-plugin.xml descriptor file. 

This tutorial covers the following topics: 

  • An overview of custom fields and the files that comprise the plugin
  • Extending the custom field type class, GenericTextCFT, for your plugin
  • Using the customfield-type plugin module type for JIRA

About these Instructions

You can use any supported combination of OS and IDE to create this plugin. These instructions were written using Eclipse Indigo on Mac OS X. If you are using another OS or IDE combination, you should use the equivalent operations for your specific environment.

This tutorial was last tested with JIRA 6.1.2. 

Prerequisite knowledge

To complete this tutorial you should already understand basic Java development. Familiarity with JIRA is also helpful. You should be able to complete this tutorial even if you've never created a plugin before.

Plugin Source

We encourage you to work through the tutorial. If you'd like to skip ahead or check your work when you're done, you can find the plugin source on Atlassian Bitbucket. Bitbucket serves as a public Git repository containing the tutorial's source code. To clone the repository for this plugin, issue the following command: 

$ git clone https://bitbucket.org/atlassian_tutorial/jira-custom-field-tutorial.git

Alternatively, you can download the source code for this plugin project.

Step 1. Create the plugin project and trim the skeleton

In this step you'll generate a JIRA plugin skeleton. You'll use atlas- commands to automate the plugin creation. Some files are automatically generated by the SDK that you won't need for this tutorial, so you'll delete them in this step.

  1. Open a terminal window and navigate to your Eclipse (or equivalent IDE) workspace directory. 

  2. Enter the following command to create a JIRA plugin skeleton: 

    $ atlas-create-jira-plugin
  3. When prompted, enter the following information to identify your plugin: 

    group-id

    com.atlassian.jira.plugin.customfield.example

    artifact-id

    jira-custom-field-example

    version

    1.0-SNAPSHOT

    package

    com.example.plugins.tutorial.customfields

  4. Confirm your entries when prompted with Y or y.

    Your terminal notifies you of a successful build:

    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 1 minute 11 seconds
    [INFO] Finished at: Thu Aug 28 11:30:23 PDT 2013
    [INFO] Final Memory: 82M/217M
    [INFO] ------------------------------------------------------------------------
    
  5. Change to the jira-custom-field-example directory created by the previous step.

    $ cd jira-custom-field-example
  6. Delete the test directories.
    Set up up testing for your custom field isn't part of this tutorial. Use the following commands to delete the test directories. 

    $ rm -rf ./src/test/java/
    $ rm -rf ./src/test/resources/
  7. Delete the unnecessary Java files. 
    You'll build a Java class for your plugin in future steps.

    rm ./src/main/java/com/atlassian/jira/plugin/customfield/example/*.java
  8. Edit the src/main/resources/atlassian-plugin.xml descriptor file.

  9. Remove the generated myPluginComponent declaration from atlassian-plugin.xml file.

    Delete: 

        <!-- publish our component -->
        <component key="myPluginComponent" class="com.atlassian.jira.plugin.customfield.example.MyPluginComponentImpl" public="true">
            <interface>com.atlassian.jira.plugin.customfield.example.MyPluginComponent</interface>
        </component>
  10. Save and close the file. 

  View the entire descriptor file.

Here's how your atlassian-plugin.xml descriptor file should appear up to this point:

<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2">
    <plugin-info>
        <description>${project.description}</description>
        <version>${project.version}</version>
        <vendor name="${project.organization.name}" url="${project.organization.url}" />
        <param name="plugin-icon">images/pluginIcon.png</param>
        <param name="plugin-logo">images/pluginLogo.png</param>
    </plugin-info>
    <!-- add our i18n resource -->
    <resource type="i18n" name="i18n" location="jira-custom-field-example"/>
    
    <!-- add our web resources -->
    <web-resource key="jira-custom-field-example-resources" name="jira-custom-field-example Web Resources">
        <dependency>com.atlassian.auiplugin:ajs</dependency>
        
        <resource type="download" name="jira-custom-field-example.css" location="/css/jira-custom-field-example.css"/>
        <resource type="download" name="jira-custom-field-example.js" location="/js/jira-custom-field-example.js"/>
        <resource type="download" name="images/" location="/images"/>
        <context>jira-custom-field-example</context>
    </web-resource>
    
    <!-- import from the product container -->
    <component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties" />
    
</atlassian-plugin>

Import your project into your IDE

  Click here to see instructions for importing into Eclipse

  1.  Make your project available to Eclipse.

    atlas-mvn eclipse:eclipse
    

    You'll see a successful build message: 

    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 54 seconds
    [INFO] Finished at: Tue Jul 16 11:03:59 PDT 2013
    [INFO] Final Memory: 82M/224M
    [INFO] ------------------------------------------------------------------------
  2. Start Eclipse.
    You can open a new terminal window to perform this action.

    $ cd ~/eclipse
    $ ./eclipse
  3. Click File > Import
    Eclipse starts the Import wizard.

  4. Expand the General folder tree to choose Existing Projects into Workspace.

  5. Click Next. 

  6. Click Browse and enter the root directory of your workspace.
    Your Atlassian plugin folder should now appear under Projects.

  7. Ensure your plugin checkbox is ticked and click Finish
    Eclipse imports your project, and it's now visible in your Package Explorer view.

Step 2. Create your JiraCustomField.java class

Your custom field extends the JIRA GenericTextCFType class. GenericTextCFType is one of many custom field-specific Java classes and interfaces – other examples include DateCFType to set dates, UserCFType to pick users, and SelectCFType for picking a single option from a list. The GenericTextCFType class stores and retrieves field values as strings. Here you'll extend the class for your plugin, and in future steps you'll apply your field logic in your Velocity template so that admins alone can modify the string value.

These instructions are written for Eclipse, but you can use the equivalent steps for your own IDE.

  1. Open Eclipse.

  2. Locate the com.atlassian.jira.plugin.customfield.example package under src/main/java.

  3. Right-click the package and choose New Class.

  4. Name your class JiraCustomField.

  5. Choose com.atlassian.jira.issue.customfields.impl.GenericTextCFType as the superclass.

  6. Tick the checkboxes to include Constructors from superclass and Inherited abstract methods.

  7. Click Finish.
    Your class contains the following stub code to extend GenericTextCFType

    package com.atlassian.jira.plugin.customfield.example;
    
    import com.atlassian.jira.issue.customfields.impl.GenericTextCFType;
    import com.atlassian.jira.issue.customfields.manager.GenericConfigManager;
    import com.atlassian.jira.issue.customfields.persistence.CustomFieldValuePersister;
    
    
    public class JiraCustomField extends GenericTextCFType {
    
    	public JiraCustomField(CustomFieldValuePersister customFieldValuePersister,
    			GenericConfigManager genericConfigManager) {
    
    		super(customFieldValuePersister, genericConfigManager);
    	}
    
    
    }
  8. Save and close the class.

  9. Update your project changes.

    $ atlas-mvn eclipse:eclipse

Step 3. Create a Velocity template to format your custom field

In this step you'll write the logic for rendering your custom field in a Velocity template. You'll create a condition to check if the user's group name includes 'jira-administrators'. If users fit the criteria, they'll be able to edit the field value. All other users will be able to see the value entered, but be unable to change it. You'll also create an else condition that if no value has been set for the field, JIRA will display "N/A" as the default value. 

  1. Create a templates directory under src/main/resources.

    $ mkdir src/main/resources/templates
  2. Create a edit-jiraadminonlytext.vm file under your new templates directory: 

    $ cat > src/main/resources/templates/edit-jiraadminonlytext.vm
  3. Copy and paste the following onto the command line.

    Here you'll add the conditional check to see if the user is an admin. If no value exists, the user will see "N/A".

    #controlHeader ($action $customField.id $customField.name $fieldLayoutItem.required $displayParameters.noHeader)
    #if ($jiraUserUtils.getGroupNamesForUser($authcontext.loggedInUser.name).contains('jira-administrators'))
    	<input type="text"
    	name="$customField.id"
    	value="$!value" />
    #else
    #if($value && ! $value.equals(""))
    #set ($displayValue = ${value})
    #else
    #set ($displayValue = 'N/A')
    #end
    <span title="This field is editable only by JIRA administrators">$!displayValue</span>
    	<input type="hidden"
    	name="$customField.id"
    	value="$!value" />
    #end
    #controlFooter ($action $fieldLayoutItem.fieldDescription $displayParameters.noHeader)
    
    
  4. Hit CTRL + D  to save and exit the VM editor.

Step 4. Add a customfield-type plugin module to your descriptor file

In this step you'll complete your plugin code with the addition of a customfield-type plugin module. You'll add this module to the atlassian-plugin.xml descriptor file. The descriptor file was automatically generated when you built your plugin skeleton, and describes dependencies to the Atlassian system. Inserting a customfield-type plugin module lets you add your custom field to JIRA. This module requires a Java class for implementation and a unique key identifier. You'll also reference your Velocity template as a resource type element. There are four view types for any custom field, three of which are required: 

View type Required? Details
view (tick) Provides a basic read-only view of the field value.
column-view (error) Read-only view for displaying in the issue navigator. The issue navigator will display the view value if omitted.
edit (tick) Renders the edit widget in issue creation, editing issues, and editing defaults. This is the value you'll replace with your custom Velocity template.
xml (tick) Shows the value in XML format for RSS or XML exports.

You'll use two built-in Velocity templates in JIRA for the view and xml view types, and your custom template for the edit value. 

  1. Edit atlassian-plugin.xml under src/main/resources.

  2. Locate the closing </atlassian-plugin> tag. 

  3. Add the opening and closing tags for your customfield-type.

    Place the block before the end of the closing </atlassian-plugin> tag. You'll give your custom field a unique key, name, and define JiraCustomField as the implementing Java class.

    	<customfield-type key="admintextfield" name="Admin Editable Text Field" class="com.atlassian.jira.plugin.customfield.example.JiraCustomField">
    	</customfield-type>
  4. Add a description inside the first customfield-type tag. 
    This description appears in JIRA when you apply the custom field type from the admin pages. 

    		<description>A text field only editable by those with admin permissions</description>


  5. Define which Velocity templates to use for each view type: 

    		<resource type="velocity" name="view" location="templates/plugins/fields/view/view-basictext.vm"/>
    		<resource type="velocity" name="edit" location="templates/edit-jiraadminonlytext.vm"/>
    		<resource type="velocity" name="xml" location="templates/plugins/fields/xml/xml-basictext.vm"/>


  6. Save and close your descriptor file.

  7. Update your project changes.

    $ atlas-mvn eclipse:eclipse


  8. From your project root, issue the following command: 

    $ atlas-create-jira-plugin-module



  Click here to expand...

Here's the completed atlassian-plugin.xml descriptor file:

<?xml version="1.0" encoding="UTF-8"?>
<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2">
  <plugin-info>
    <description>${project.description}</description>
    <version>${project.version}</version>
    <vendor name="${project.organization.name}" url="${project.organization.url}"/>
    <param name="plugin-icon">images/pluginIcon.png</param>
    <param name="plugin-logo">images/pluginLogo.png</param>
  </plugin-info>
  <!-- add our i18n resource -->
  <resource type="i18n" name="i18n" location="jira-custom-field-example"/>
  <!-- add our web resources -->
  <web-resource key="jira-custom-field-example-resources" name="jira-custom-field-example Web Resources">
    <dependency>com.atlassian.auiplugin:ajs</dependency>
    <resource type="download" name="jira-custom-field-example.css" location="/css/jira-custom-field-example.css"/>
    <resource type="download" name="jira-custom-field-example.js" location="/js/jira-custom-field-example.js"/>
    <resource type="download" name="images/" location="/images"/>
    <context>jira-custom-field-example</context>
  </web-resource>
  <!-- import from the product container -->
  <component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties"/>
	<customfield-type key="admintextfield" name="Admin Editable Text Field" class="com.atlassian.jira.plugin.customfield.example.JiraCustomField">
		<description>A text field only editable by those with admin permissions</description>
		<resource type="velocity" name="view" location="templates/plugins/fields/view/view-basictext.vm"/>
		<resource type="velocity" name="edit" location="templates/edit-jiraadminonlytext.vm"/>
		<resource type="velocity" name="xml" location="templates/plugins/fields/xml/xml-basictext.vm"/>
	</customfield-type>
</atlassian-plugin>

Step 5. Build, install, and run your plugin

In this step you'll install your plugin and run JIRA. You'll log into your JIRA instance as an admin and configure visibility for your custom field. 

  1. Open a terminal and navigate to your project root. 

    $ cd jira-custom-field-example
  2. Start JIRA. 

    $ atlas-run

    This builds your plugin code, starts a JIRA instance, and installs your plugin. This could take a few minutes.

  3. Locate the URL for JIRA. 
    Your terminal outputs the location of your local JIRA instance, defaulted to http://localhost:2990/jira

    [INFO] jira started successfully in 194s at http://localhost:2990/jira
    [INFO] Type Ctrl-D to shutdown gracefully
    [INFO] Type Ctrl-C to exit
  4. Navigate to your JIRA instance in a browser window.
    We recommend using Google Chrome or Mozilla Firefox for consistency.

  5. Log in with admin / admin.
  6. Once logged in, navigate to the custom field options under cog icon > Issues > Custom Fields

  7. Click Add Custom Field and choose Advanced.

  8. Choose your plugin, Admin Editable Text Field from the list and click Next.
    Choose your plugin
  9. Enter details as prompted. 
    Choose Any issue type for Choose applicable issue types, and Global context to apply to all issues in JIRA. 
    Enter a field name and details

  10. Associate the field with all screens and click Next.
    Associate fields

Step 6. Create a test user and test your custom field type

Now that you've added your custom field, let's put it to the test. You'll create a new user without admin permissions so you can verify your field settings. 

  1. From any page in your local JIRA instance, click   > Users Management.

  2. Click Create User and enter details for a test user. 
    Keep it simple and use your own email address.
    Create a test user
  3. Next, create a project.
    Click Projects > Create Project.
    Now you'll be able to create an issue to test your field.

  4. Choose Bug Tracking > Next.

  5. Choose a name (like "Test") and click Submit.

  6. Create an issue for your project.
    Click Create Issue and verify you can enter text into your custom field type as an admin.
    Create an issue as an admin
  7. Log out and log in with your test user credentials.

  8. Create an issue as your test user. 
    Verify that you're unable to modify the field you customized. 
    Create issue as a non-admin
Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport