We have seen how to write a custom field in one of the previous tutorials. Writing the field is one thing but making it available to one of the JIRA's most powerful functionality, i.e. Search, is another!
So how do we do that? In most cases, you wouldn't need a custom searcher. Instead you can use the built in custom field searchers in JIRA itself. The list includes, but not restricted to, Text Field Searcher, Date Searcher, Number Searcher, User Searcher etc. The first step of course is to determine what is the kind of Searcher your new field needs. For example, a Select field can easily be searched with Text Searcher or an Exact Text Searcher! A User Picker field can be searched with a User Searcher or a Text Searcher. You might even want to extend one of these Searchers to add some extra functionality. Some special conditions or hacks you want to introduce! Yeah, you know what I mean!! Now, we have the custom field ready and the Searcher decided. Let us , in this example, consider using a TextSearcher puerly because the customfield we created in the other tutorial is extending a TextCFType. Here is how JIRA has defined the text searcher for its system custom fields:
<customfield-searcher key="textsearcher" name="Free Text Searcher" i18n-name-key="admin.customfield.searcher.textsearcher.name" class="com.atlassian.jira.issue.customfields.searchers.TextSearcher"> <description key="admin.customfield.searcher.textsearcher.desc">Search for values using a free text search.</description> <resource type="velocity" name="search" location="templates/plugins/fields/edit-searcher/search-basictext.vm"/> <resource type="velocity" name="view" location="templates/plugins/fields/view-searcher/view-searcher-basictext.vm"/> <valid-customfield-type package="com.atlassian.jira.plugin.system.customfieldtypes" key="textfield"/> <valid-customfield-type package="com.atlassian.jira.plugin.system.customfieldtypes" key="textarea"/> <valid-customfield-type package="com.atlassian.jira.plugin.system.customfieldtypes" key="readonlyfield"/> </customfield-searcher>
We are going to do the same thing in our Atlassian-plugin.xml for our custom field. It will look like this:
<customfield-searcher key="readonly-user-searcher" name="Read Only User Searcher" class="com.atlassian.jira.issue.customfields.searchers.TextSearcher"> <description key="admin.customfield.searcher.textsearcher.desc">Search for Read Only User using a free text search.</description> <resource type="velocity" name="search" location="templates/plugins/fields/edit-searcher/search-basictext.vm"/> <resource type="velocity" name="view" location="templates/plugins/fields/view-searcher/view-searcher-basictext.vm"/> <valid-customfield-type package="com.jtricks" key="readonly-user"/> </customfield-searcher>
I am sure you would have noticed the changes made. Just to elaborate a bit, there should be a unique key like for everything else and the class should refer to the Searcher you want to point to. It could be your custom Searcher class as we mentioned before but in this case we have chosen JIRA's TextSearcher. Then you can define your own velocity templates for the Search and view for Edit and View 'views' respectively.
And then comes the most important part where you mention your customfield within the valid-customfield-type tag. There can be multiple entries for different custom fields as you saw in the first snippet from Atlassian. In our case we have the read-only user custom field added. There is basic but very common error you might make here. The package attribute here refers to the atlassian-plugin key where the custom field resides in and not the Java package where the Searcher class resides in! Just to make it clear, the Atlassian plugin key is the key in the first line of your atlassian-plugin.xml which is 'com.jtricks' in our case.
<atlassian-plugin key="com.jtricks" name="J-Tricks Customfields Plugin" plugins-version="2">
This package (plugin key) along with the customfield key (readonly-user in this case) will point to the right custom field. This would also mean that you can have the same 'readonly-user' in another plugin with a different plugin key!
Now all these works fine pre 4.x or pre OSGI! With the introduction of v2 plugins, courtesy OSGI bundles, referring the JIRA classes directly in the atlassian-plugin.xml will fail sometimes because it can't resolve all the dependencies (the notorious Unsatisfied dependency errors!). This is because some of the classes are not available for dependency injection in the version 2 plugins as they were in version 1 plugins. But don't worry, there is an easy hack to do it. Just create a dummy custom Searcher class with the constructor that does the dependency injection for you. So you will endup doing something what Leonids suggest in the forums:
public class MySearcher extends SomeJiraSearcher { public MySearcher(PluginComponent ioc) { super(ioc, ComponentManager.getInstanceOfType(anotherType)); } }
Have a look at this thread and this for more details and a sample for this issue.
If nothing works, you always have the option of adding the field to the system-customfield-types.xml under WEB-INF/classes along with the JIRA system custom fields. i.e. one more valid-customfield-type entry into the relevant customfield-searcher element. Phew! So we have the searcher defined and the stage is set to create your first filter with the new custom field. Happy coding.
24 Comments
Joe Caputo
1/9/2012 07:49:27 am
Hi there!
Reply
Joe Caputo
1/9/2012 07:52:38 am
My custom field is simple. It just extends the text type and I modify one velocity file so that it's read-only:
Reply
J-Tricks
1/9/2012 01:36:24 pm
I think you are having the same OSGI issue mentioned above. Are you seeing any error in the logs when the plugin is loaded?
Reply
Joe Caputo
1/9/2012 02:44:20 pm
Ok, I'll give that a shot Mr. Tricks. Is this the proper way of doing this now?
J-Tricks
1/10/2012 12:41:58 am
@Joe, Yes that is the only way you can do it. It is a known issue ever since OSGi Plugins came into picture. JRA hasn't made all the classes available to OSGi Bundles.
Reply
7/20/2012 06:19:20 am
We had the problem where our plugin would run in production for a long time, then somehow JIRA disabled it. I figured out that by going to Custom Fields, JIRA was having this problem with 2 classes, so it disabled my plugin. When I rewrote the constructor, I can click on Custom Fields and not have the plugin go disabled. My constructor now:
Reply
J-Tricks
7/20/2012 12:23:40 pm
Tom,
Reply
Bertrand
9/28/2012 08:44:56 am
Hi,
Reply
J-Tricks
9/28/2012 09:21:59 am
Unfortunately, the easy option for you is to add the jira-core dependency and extend the MultiSelectSearcher.
Reply
Nabil Sayegh
2/17/2013 11:21:42 pm
Thanks for pointing out the meaning of the package field
Reply
7/1/2013 12:51:55 am
I am using custom versionsearcher as below in jira 5.0.x .It works fine.
Reply
Dale Miller
6/16/2015 11:59:13 am
That seems to work for the dependency issues. I want to change the data that gets stored in the index. Can I use this method and change what gets stored in lucene? I looked at overriding the init method but can't seems to get it to work properly.
Reply
J-Tricks
6/17/2015 12:32:27 am
You will have to override the FieldIndexer used by your searcher, if you want to manipulate lucene.
Dale Miller
6/17/2015 09:52:49 am
I am trying to use the following to accompish this but some of the variables are not defined as the values are never saved in the call to the constructor. Any ideas what I am doing wrong? I always get errors at run time that fieldFlagOperandRegistry is null as well as the other values in the super constructor that just send in new objects. Examples are new VersionResolver(versionManager), new DefaultFieldFlagOperandRegistry() and new VersionClauseContextFactory(operandResolver, new VersionResolver(versionManager),permissionManager). Each of these error out. If I try to store a variable I get the dependency errors back. I think I am not understanding something here. I have tried it with and without the super.init() in the overwridden int function. Any pointers would be appreciated. I just want to override the line below and leave the rest the same as the standard one. Is that possible? I can't seem to get this code to work properly.
Holger Schimanski
7/24/2013 11:41:58 pm
I have a problem with my custom field text searcher in Basic search where JIRA shows the error "not valid". Any idea, what to do? https://answers.atlassian.com/questions/191643/problem-with-custom-field-not-valid-in-basic-search-in-jira-6-0
Reply
Prameesha
6/23/2014 10:38:04 pm
Hi,
Reply
J-Tricks
6/24/2014 04:19:25 am
Most of this will be done as Javascript. i.e. the values in the table will be stored as a concatenated String or as a JSON (which is even better). In the template, you have to construct the JSON as the user enters the values.
Reply
Prameesha
6/24/2014 09:41:26 pm
I have followed the tutorial of adding a custom field displaying the current user, if I want to save this value in the database would overriding the 'updateValue' method be sufficient or is there more to be done? and as for the JSON how would I post this value back. Could you please explain the concept of how custom field values get updated on an issue update event.
J-Tricks
6/25/2014 12:59:03 am
As long as you have the controlHeader correctly defined in the "Edit" template and has the customfield ID as the name of the field, the value will be saved in database correctly. Checkout the sample read only customfield example in the custom field tutorial. 10/13/2014 01:27:18 am
Hi,
Reply
Pavan
4/27/2015 07:55:55 pm
Hi JTrick
Reply
Guy Rouillier
5/29/2015 09:11:22 am
I'm using JRJC to get custom fields:
Reply
Pavan
6/29/2015 11:15:41 pm
Hi again,
Reply
Ludovic
7/13/2017 08:45:27 am
Hello,
Reply
Your comment will be posted after it is approved.
Leave a Reply. |
AuthorJobin Kuruvilla - Works in Adaptavist as Head of DevOps Professional Services. Categories
All
Archives
October 2016
|