I am trying to refactor a Scriptrunner listener to work with the new Jira 8 updates. The listener should copy a custom field value from parent to all children on update. It was previously working w/ Jira 7.
Specifically, having trouble implementing searchProvider.search() method. Code block below...I have loads of new type check errors and don't know where to begin!!
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.issuetype.IssueType
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.bc.issue.*
import static com.atlassian.jira.workflow.TransitionOptions.Builder;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLink
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.issue.index.IssueIndexingService;
import com.atlassian.jira.issue.search.IssueSearchResultsFactory;
import com.atlassian.jira.issue.search.DocumentSearchResultsFactory;
def log = Logger.getLogger("com.acme.debug")
log.setLevel(Level.DEBUG)
Issue issue = event.issue
def key = issue.getKey()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issueManager = ComponentAccessor.getIssueManager();
def field = customFieldManager.getCustomFieldObjects(event.issue).find { it.name == "Priority Number" }
def issueService = ComponentAccessor.getIssueService()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchProvider = ComponentAccessor.getComponent(SearchProvider)
def parentLink = customFieldManager.getCustomFieldObjectsByName('Parent Link') // getting the Parent Link custom field
def customFieldValue = issue.getCustomFieldValue(parentLink) // Parent Link field value
def parentKey = (String) customFieldValue
def parentIssue = issueManager.getIssueObject(parentKey) // Parent issue object
def parentValue = issue.getCustomFieldValue(field)
def jqlSearch = "issuetype in (Feature,'Forecasting Placeholder',Epic,Story)and status not in (Done,'Feature Post-Implementation','Feature Released') and issuekey in childIssuesOf(" + key + ")";
def query = jqlQueryParser.parseQuery(jqlSearch)
def results = searchProvider.search(query, user, PagerFilter.getUnlimitedFilter())
results.getResults().each {documentIssue ->;
def childIssue = issueManager.getIssueObject(documentIssue.id)
def changeHolder = new DefaultIssueChangeHolder()
def childValue = childIssue.getCustomFieldValue(field)
def issueIndexManager = ComponentAccessor.getComponent(IssueIndexingService)
field.updateValue(null, documentIssue, new ModifiedValue(childValue, parentValue), changeHolder)
issueIndexManager.reIndex(documentIssue)
}
I have found my way here https://confluence.atlassian.com/jiracore/lucene-upgrade-975041047.html but I am so far, unable to translate these updates...
Any advice is appreciated!
Logs:
2019-09-24 12:36:25,462 ERROR [runner.AbstractScriptListener]: ************************************************************************************* 2019-09-24 12:36:25,462 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: <inline script> groovy.lang.MissingMethodException: No signature of method: com.atlassian.jira.issue.search.providers.LuceneSearchProvider.search() is applicable for argument types: (com.atlassian.query.QueryImpl, com.atlassian.jira.user.DelegatingApplicationUser, com.atlassian.jira.web.bean.PagerFilter) values: [{issuetype in ("Feature", "Forecasting Placeholder", "Epic", "Story")} AND {status not in ("Done", "Feature Post-Implementation", "Feature Released")} AND {issuekey in childIssuesOf(ZSMBT-10)}, ...] Possible solutions: search(com.atlassian.jira.issue.search.SearchQuery, com.atlassian.jira.web.bean.PagerFilter), search(com.atlassian.jira.issue.search.SearchQuery, com.atlassian.jira.web.bean.PagerFilter, java.util.Set), search(com.atlassian.jira.issue.search.SearchQuery, org.apache.lucene.search.Collector), each(groovy.lang.Closure) at Script402.run(Script402.groovy:49)
I've found 2 ways.
1) change to use com.atlassian.jira.bc.issue.search.SearchService instead of SearchProvider
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.issue.search.SearchQuery
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchService = ComponentAccessor.getComponent(SearchService)
def jqlSearch = "project=JSP and assignee=p6s and resolution is empty"
def query = jqlQueryParser.parseQuery(jqlSearch)
//note different order of parameters compared to searchprovider
def results = searchService .search(user,query, PagerFilter.getUnlimitedFilter())
results.getResults()
2) Continue to use the searchProvider but wrap some parameters in a SearchQuery (and get issue_id from the lucene document)
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.issue.search.SearchQuery
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchProvider = ComponentAccessor.getComponent(SearchProvider)
def jqlSearch = "project=JSP and assignee=p6s and resolution is empty"
def query = jqlQueryParser.parseQuery(jqlSearch)
def searchQuery = SearchQuery.create(query, user)
def results = searchProvider.search(searchQuery, PagerFilter.getUnlimitedFilter())
results.getResults()*.document.collect{ComponentAccessor.issueManager.getIssueObject(it.getField('issue_id').stringValue())}
@Peter-Dave Sheehan The first method you provided worked perfectly thank you!
Curiosity...Any idea why I'm still getting a static type-check error on line 45? Everything is working but it is showing that error: Cannot find matching method getCustomFieldValue:
def customFieldValue = issue.getCustomFieldValue(parentLink) // Parent Link field value
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I see you've updated from the deprecated getCustomFieldObjectByName (singular) to use the new "getCustomFieldObjectsByName" (plural). This new method returns a list, not a single custom field. So maybe try:
def parentLink = customFieldManager.getCustomFieldObjectsByName('Parent Link')[0]
def customFieldValue = issue.getCustomFieldValue(parentLink)
To get the first (and presumably only) field in the list.
Or change to getCustomFieldObject(id) using the internal id (long) of the Parent Link field
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I'm not sure if anybody could use the 2) method described here. But I found out that the last row:
def results = searchProvider.search(searchQuery, PagerFilter.getUnlimitedFilter())
results.getResults()*.document.collect{ComponentAccessor.issueManager.getIssueObject(it.getField('issue_id').stringValue())}
does not work for me, and I had to change the id from String to Long to make it run
def results = searchProvider.search(searchQuery, PagerFilter.getUnlimitedFilter())
results.getResults()*.document.collect{ComponentAccessor.issueManager.getIssueObject(it.getField('issue_id').stringValue().toLong())}
Is that the correct way, or we could have better function to retrieve Issue from these docId results?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I think I was working on 8.3 at the time of my answer.
I saw that with 8.5.1, you are correct, toLong() is required.
I also found this works:
results.getResults()*.document.collect{
ComponentAccessor.issueManager.getIssueObject(it.getValues('issue_id').first() as Long)
}
I can't think of why one would be better than the other. Either way, we now have to use native Lucene method to extract values from the document.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
:+1: for solution 1) this fixes our issue after migration from Jira 7.13 to Jira 8.5.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Solution 1 Fixed the problem. But the "result" line should be like below
def results = searchService .search(user,query, PagerFilter.getUnlimitedFilter()).getResults()
def results = searchService .search(user,query, PagerFilter.getUnlimitedFilter())
results = results.getResults()
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Item #2 above prints the issues with their key.
Thanks to all above!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you soooo much!!! #1 Solved my Issue I was working on for ages!!! :D Super happy :D
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.