Calculated custom field - using of searchService java class

Vladimir Voitechovic January 12, 2016

Hello,

In JIRA I have a calculated custom field with formula which do SJQL (Structure JQL) search. To do this search I use searchService java class. I also use Structure plugin. Then I open project's structure and have a view with this calculated custom field, the Structure loads very slowly (particularly, when this structure has a lot of issues). As I know, this happens due to the calculated custom field as it uses SJQL. Is it possible to optimize the formula using another methods or java classes to achieve the same result in this calculated custom field?

Thanks a lot in advance for any advises and suggestions!

 

Vladimir

 

3 answers

1 accepted

1 vote
Answer accepted
Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 13, 2016

Hi Vladimir, 

Thanks for the clarification. You can speed up the calculation a bit by bypassing query parsing and probably execution. It would require making your code import Structure Java API, as explained here: https://wiki.almworks.com/x/x4J7

Option 1. Use S-JQL but avoid query parsing

Check out StructureQueryBuilder class in the javadoc. It has some examples.

Option 2. Do not use S-JQL and traverse the structure manually

Use StructureManager service to retrieve Forest, locate your target issue, then walk upwards with getParentIndex() method, checking each issue. If you have only a few issues of type "Specific type", it would be a good idea to cache issue IDs or Issue objects for those to avoid costly getIssue() calls.

Javadocs: http://almworks.com/structure/javadoc/latest/

Additionally, I'm happy to say that Structure 3.0 will have a new "attributes engine", which would allow you to define an attribute of "propagate" kind – similar to aggregate, but in another direction – which is exactly what you need in this situation. You'll be able to display propagate attribute in Structure Widget, or re-implement your calculated field in a way to use the propagate. It will be very fast, because the system will implement correct caching based on the nature of the attribute. Unfortunately, the API will not be finalized with the upcoming release of Structure 3.0, it hopefully will be ready by Structure 3.1.

Hope this helps!
Igor 

Vladimir Voitechovic January 13, 2016

Hi Igor, Thank you once more for explicit answer! I think I should to implement Option 2, because, typically, there can be no more than one ancestor issue which is of this Specific type1 (in our project management model we have such restriction). If there is no such ancestor of this Specific type1, I have to search for ancestor of Specific type2 (and again in our model we have restriction that there can be only one ancestor issue which is of this Specific type2). One more question - to implement Option 2, do I have to import StructureServices, that is: import com.almworks.jira.structure.api.StructureServices; import com.almworks.jira.structure.api.StructureManager; StructureManager strucMan = structureServices.getStructureManager() ? Best regard, Vladimir

Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 13, 2016

Yes, that should work

Vladimir Voitechovic January 14, 2016

Hi Igor, I have one more question, but firstly about the problem. In our company we have structure for each project, then we have structure for each department (this structures consists of projects' structures that belong to that particular department) and finally, we have company's structure (consists of departments' structures). Is it better to retrieve Forest of company's structure (in this way I know its ID and it would be the same for all issues, but the Forest is huge because almost all issue are in it), or, firstly, to search for project's structure (in which the issue exists) and retrieve the Forest of this project's structure (in this case, the Forest is much smaller, but I have to search)? Thanks for the advice! Vladimir

Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 14, 2016

Hi Vladimir, good question. I cannot tell you with 100% confidence that one way would be better than the other. I would try searching smaller structures first. How would you search for a per-project structure? You can use StructureManager.getStructuresWithIssue() to find all structures that contain given issue. Or maintain a cached map of Project => structure ID. Igor

Vladimir Voitechovic January 14, 2016

Hi Igor,

I try to implement the formula by using StructureServices and StructureManager. Unfortunately, the following code doesn't run:

import com.almworks.jira.structure.api.StructureServices;

import com.almworks.jira.structure.api.StructureManager;

StructureManager strucMan = structureServices.getStructureManager()

 

I tried to implement very simple calculated text custom field in order to test various scenarios. In the following code I try just to check if issue is in a specific structure or not. Also, I use ComponentAccessor to get StructureServices class:

   import com.atlassian.jira.component.ComponentAccessor;

   import com.almworks.jira.structure.api.StructureServices;  

   import com.almworks.jira.structure.api.StructureManager;   

 

   Long issueID = issueObject.getId();

   StructureServices strucServices = ComponentAccessor.getComponent(StructureServices.class);

   StructureManager strucManager = strucServices.getStructureManager(); //error in this place

 

   if (strucManager.isIssueInStructure(issueID, 162)) {

      return "YES";

   } else return "NO";

And again it throws an error: CalculatedTextField: error evaluating formula of field "Test" of issue HX191-121: Sourced file: inline evaluation of: import com.atlassian.jira.component.Compone . . . '' : Typed variable declaration : at Line: 9 : in file: inline evaluation of: import com.atlassian.jira.component.Compone . . . '' : strucServices .getStructureManager ( ) Target exception: java.lang.NullPointerException: Null Pointer in Method Invocation

And here I stop because I don't understand, why it throws this error. Maybe you know?

Thanks a lot,

Vladimir

Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 14, 2016

Vladimir, you need to inject the services, you cannot get them with `getComponent()`. Please read documentation here: https://wiki.almworks.com/x/x4J7 Also, there are some examples: https://wiki.almworks.com/x/y4J7

Kind regards,
Igor 

Vladimir Voitechovic January 15, 2016

Igor,

I think the difficulty is that I do not create any JIRA plugin, but instead I use JIRA Misc Custom Fields plugin. Does it mean, that I have to change pom.xml and atlassian-plugin.xml files of this plugin?

Vladimir

Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 15, 2016

Ah, I see. You can try ComponentAccessor.getOSGiComponentInstanceOfType() then, instead of getComponent()

Vladimir Voitechovic January 18, 2016

Hi, Igor,

The method ComponentAccessor.getOSGiComponentInstanceOfType() worked, but it is seems that this does not speed up the calculations. Again I got in some troubles:

Firstly, when I define a new variable "Forest forest = structManager.getForest(DEFAULT_STRUCTURE_ID, user, true)" and re-index the JIRA I got an error "Class: Forest not found in namespace : at Line: 26 : in file: inline evaluation of: `` // category import com.almworks.jira.structure.api.Structure . . . '' : Forest" (even if I did import com.almworks.jira.structure.api.forest.Forest). So, each time when I want to know the issuetype of issue's parent, I have to use "ComponentAccessor.getIssueManager().getIssueObject(strucManager.getForest(DEFAULT_STRUCTURE_ID, user, true).getParent(issueID)).getIssueTypeId()".

Secondly, even if I could define a new variable from the Forest class, I do not think this would help because for 20.000 issues to retrieve the Forest is time-consuming. Is it possible only once to retrieve the Forest of DEFAULT_STRUCTURE and then for each issue to find its parent and look for parent's issuetype? 

Thanks in advance,

Vladimir

Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 27, 2016

Hi Vladimir, sorry for late reply. You're right, extracting Forest once and reuse would make things work faster. I don't have an immediate solution to offer, sorry, this requires extended work and analysis of your task. As I mentioned, Structure 3 should make this task easier. 

Kind regards,
Igor 

Vladimir Voitechovic January 27, 2016

Hi Igor,

Thanks a lot. Sorry for disturbing you!

By this time, I think it is most efficient just to use IssueLinkManager() and find parent of an issue by using Issue links.

Best regards,

Vladimir

0 votes
Vladimir Voitechovic January 12, 2016

Hi, Igor, Thanks for your reply. In the calculated custom field formula for a certain group of issue types I search their ancestor of a specific issue type and look for a field's value of that ancestor. Here are a few fragments from the code: String jqlSearch1 = "issue in structure(\"ancestor of (" + issueObject.getKey() + ") and [type = \'Speciific type\']\")"; ... parseResult = searchService.parseQuery(user, jqlSearch1); ... searchResult = searchService.search(user, parseResult.getQuery(), PagerFilter.getUnlimitedFilter()); Is it possible to somehow optimize the search by using another procedures or java classes? I have found some information about jiraRestClient class, but I don't know, if using it will give a better result. Best regards, Vladimir

0 votes
Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 12, 2016

Hi Vladimir, Could you please specify what SJQL are you using and what else does the calculated field calculate? Typically, yes, calculated fields are very slow. Igor

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events