Posts Tagged Jira

Jira Plugin: Unique Issue ID with Search Capability

In a previous post I've explained how to create a Jira plugin for a unique issue ID across the projects. I'd recommend reading that post before this one. The issue ID, a unique one is useful (if that is your requirement, of course) but would be even more useful if you could search for that.

According to the documentation the CustomFieldSearcher interface defines IssueSearcher that's usable by the custom field objects. IssueSearcher in turn is responsible for all search related activities in the Issue Navigator.

Like pre-configured custom field implementations, you will find several implementations packaged out of the box for searchers. More often than not you may have to just pick which searcher implementation suits the data type of your custom field. In this case, our unique issue ID custom field is a number, and so we can pick either ExactNumberSearcher or a NumberRangeSearcher. I picked the latter.

So to add the search functionality there are two pieces to it:
- define it in the the descriptor
- add views so that search fields show up for searching, and also for viewing the search criteria.

Plugin Descriptor

Only the additions made for the search functionality is displayed below, for the actual custom field definition please refer to the previous post.

<atlassian-plugin>
...
...  
    <customfield-searcher key="uniqueIssueIdSearcher" name="Unique Issue Id Searcher"
	class="com.atlassian.jira.issue.customfields.searchers.NumberRangeSearcher">
       <description>Allows search for unique issue ID.</description>
       <resource type="velocity" name="view"
   		location="templates/plugins/fields/view-searcher/view-searcher-number-range.vm" />
       <resource type="velocity" name="search"
   		location="templates/plugins/fields/edit-searcher/search-number-range.vm" />
       <valid-customfield-type package="com.suryasuravarapu.jira.plugins" key="uniqueIssueId" />
    </customfield-searcher>   
</atlassian-plugin>

A searcher is defined with NumberRangeSearcher. Resources locations are provided for view and search. The last line specifies what are the valid custom field types for this searcher. You may add one ore more types here.

Velocity Templates

The two velocity templates needed for search and view are provided below. They are self-explanatory.

search-number-range.vm

#searcherEditHeader (${customField.id} ${customField.name})

<span class="lead">$i18n.getText('common.words.between')</span>

<input type="text"
       name="${customField.id}:greaterThan"
       id="${customField.id}:greaterThan"
       class="smallInputField"
       value="$!value.getFirstValueForKey('greaterThan')" 
/>

$i18n.getText('common.words.and')

<input type="text"
       name="${customField.id}:lessThan"
       id="${customField.id}:lessThan"
       class="smallInputField"
       value="$!value.getFirstValueForKey('lessThan')" 
/>

#searcherEditFooter (${customField.id} $customField.description)

view-searcher-number.vm

#searcherHeader ($customField)
    <span class="lead">$i18n.getText('common.words.between')</span> 
    #if ($value.getFirstValueForKey('greaterThan')) 
    	$value.getFirstValueForKey('greaterThan') 
    #else 
    	${i18n.getText("common.filters.any.value")} 
    #end
    
    ${i18n.getText("common.words.and")}
    #if ($value.getFirstValueForKey('lessThan'))  
    	$value.getFirstValueForKey('lessThan') 
    #else 
    	${i18n.getText("common.filters.any.value")} 
    #end
#searcherFooter ($customField)

Note: Just make sure that you select your new searcher template in the custom field you defined in the Jira Administration section.

Tags:

Jira Plugin: Unique Issue ID Across the Projects

Overview

Jira is an excellent issue tracking tool, and that needs no further introduction. Jira has a concept of Projects and each issue that is logged under a project has a pattern -- [project_key]-[id], e.g: ABC-202. The id is unique only for that project, that is ABC-202 and DEF-202 are two issues which have an id of 202, unique within their own project context. If you have a requirement of displaying a unique issue Id across all the projects then that involves some work, writing a plugin, that I try to explain in this post.

JRA-7777 is an issue that was logged a while ago on Atlassian's issue tracking site for this specific purpose.

Prerequisite

Atlassian's Developer Network site has detailed steps on setting up your environment and more. Good resource, and no need to duplicate that here.

Approach

If you look at the Jira database schema, JiraIssue table has a unique identifier column (ID). The value of that field is unique across the system. So for ABC-202 this ID could be 14500 and DEF-202 it could be 15202. So the goal is to expose this value as a read-only custom field on the Jira UI.

Other characteristics of this ID that I have observed are --
- the value starts at 10000, and
- if you restart the servlet container hosting Jira the ID (for the next row) jumps to next 10's. If the last value was 10256 before restart, after restart the ID for the subsequent row is 10260 (instead of 10257, that one may usually expect). Still unique, and serves the purpose.

Update: Matt Doar provided an explanation for this behavior in his comments:
According to Jira's documentation it’s Ofbiz that allocates IDs in batches of 10, so the SEQ_ID is the next available ID rounded up to the nearest 10. So I would expect that restarting the servlet would just round it up, not increment it on every restart.

Plugin Development

Plugin Descriptor (atlassian-plugin descriptor)

An XML file that describes about the plugin and the modules contained in it. It is placed right under the root folder of the project. In this file the new custom field type is defined. atlassian-plugin-key is the name of the Java package under which the plugin class is placed. key of the custom-field-type is the unique name of the plugin, and provide the associated fully qualified plugin Class name.

< ?xml version="1.0" encoding="UTF-8"?>
<!-- the plugin key must be unique, think of it as the 'package' of the plugin -->
<atlassian-plugin key="com.suryasuravarapu.jira.plugins" name="Unique Id Plugin">
    <!-- a short block describing the plugin itself -->
    <plugin-info>
        <description>A unique issue id for the Jira issue</description>
        <!-- the version of the plugin -->
        <version>1.0</version>
        <!-- the versions of the application this plugin is for -->
        <application-version min="3.13" max="3.13"/>
        <!-- details of the plugin vendor -->
        <vendor name="SPS" url="http://suryasuravarapu.com"/>
    </plugin-info>

    <customfield-type key="uniqueIssueId" name="Jira Internal Id"
        class="com.suryasuravarapu.jira.plugins.UniqueIssueId">
        <description>
        Unique issue id correlates to the ID in the JIRAISSUE table
        </description>

        <!-- this template is used on the view issue page -->
        <resource type="velocity" name="view"
            location="templates/plugins/fields/view/view-uniqueIssueId.vm" />
    </customfield-type>

</atlassian-plugin>

Plugin Java Code
Fortunately, you don't have to write this plugin from the scratch. Jira ships with quite a few concrete implementations. A custom field class extends CustomFieldType, but we can extend a more concrete implementation for numeric fields NumberCFType.

getValueFromIssue is the only method that you need to implement and return the auto-increment Id.

public class UniqueIssueId extends NumberCFType {
	public UniqueIssueId(CustomFieldValuePersister customFieldValuePersister,
			DoubleConverter doubleConverter,
			GenericConfigManager genericConfigManager) {
		super(customFieldValuePersister, doubleConverter, genericConfigManager);
	}
	
	public Object getValueFromIssue(CustomField field, Issue issue) {
            return issue.getId();
	}
}

Velocity Templates
view-uniqueIssueId.vm that we have described above in the plugin descriptor takes care of displaying the field value. One notable item below is we are displaying the value.longValue() as the value that is being returned by the NumberCFType is of type java.lang.Double. Without that conversion you would see values like 10380.0 instead of 10380, little annoyance!

#if($value &amp;amp;&amp;amp; !$value.equals(""))
	#set ($displayValue = ${value.longValue()})
#else
	#set ($displayValue = 'N/A')
#end
$!displayValue

Deployment

From Eclipse, export the JAR or use the Maven build scripts to generate one. Place that JAR under application's WEB-INF/lib folder, and restart the container. You should be able to see your Plugin under Jira's Administration -> Plugins.

All the hard work is done! Display the field value. For that, create a custom field using the type defined above and add it to the desired screens for display.

Tags: