Hi,
we have a lot of issues in our JIRA, so we have a problems with DateCompare jql function when user use an empty first parameter.. How can I override or extend DateCompare jql function? Or, how can I validate that first parameter of this function must not be empty? ScriptRunner 3.0.16
Hi Vladimir,
There is a relevant section in the Script Runner documentation - Custom JQL Functions, please let me know if you need further assistance.
regards, Thanos
Hi Thanos,
I took as a basis the function DateCompare.groovy, and add my validation method MessageSet nonEmptyValidate(String s), so, result:
package com.onresolve.jira.groovy.jql import com.atlassian.core.util.DateUtils import com.atlassian.core.util.InvalidDurationException import com.atlassian.crowd.embedded.api.User import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.datetime.LocalDate import com.atlassian.jira.issue.DocumentIssueImpl import com.atlassian.jira.issue.customfields.impl.DateCFType import com.atlassian.jira.issue.customfields.impl.DateTimeCFType import com.atlassian.jira.issue.fields.CustomField import com.atlassian.jira.issue.index.DocumentConstants import com.atlassian.jira.issue.search.filters.IssueIdFilter import com.atlassian.jira.jql.query.QueryCreationContext import com.atlassian.jira.jql.util.JqlLocalDateSupport import com.atlassian.jira.jql.validator.NumberOfArgumentsValidator import com.atlassian.jira.util.LuceneUtils import com.atlassian.jira.util.MessageSet import com.atlassian.jira.util.MessageSetImpl import com.atlassian.query.clause.TerminalClause import com.atlassian.query.operand.FunctionOperand import org.apache.log4j.Category import org.apache.lucene.index.Term import org.apache.lucene.search.* import java.sql.Timestamp class StcDateCompare extends AbstractScriptedJqlFunction implements JqlQueryFunction{ private def String subquery private def log = Category.getInstance(StcDateCompare.class) static def GREATER_THAN = ">" static def LESS_THAN = "<" private def List dateParams private def op, lhs, rhs private def String leftField, rightField def customFieldManager = ComponentAccessor.getCustomFieldManager() def jqlLocalDateSupport = ComponentAccessor.getComponent(JqlLocalDateSupport.class) private def Map<String,CustomField> cfMap = [:] @Override MessageSet validate(User user, FunctionOperand operand, TerminalClause terminalClause) { def messageSet = new NumberOfArgumentsValidator(2, 2, getI18n()).validate(operand) subquery = operand.args[0] def dateStr = operand.args[1] messageSet.addMessageSet validateDateComparison(dateStr) messageSet.addMessageSet nonEmptyValidate(subquery) if (messageSet.hasAnyErrors()) { messageSet.addErrorMessage("Use a comparison like: \"dueDate > resolutionDate\", or \"dueDate > resolutionDate + 2w\"," + " or \"My Date Custom Field > My Other Date Custom Field\"") return messageSet } // dateParams = dateCompareParser(dateStr) (op, lhs, rhs) = dateParams leftField = lhs[0] rightField = rhs[0] if (subquery) { messageSet.addMessageSet (validateSubquery(user, subquery)) } messageSet } @Override String getDescription() { "Compare dates" } @Override List<Map> getArguments() { [ ["description": "subquery", "optional": false], ["description": "comparison", "optional": false] ] } @Override String getFunctionName() { "altDateCompare" } MessageSet validateDateComparison(String dateString) { def messageSet = new MessageSetImpl() try { dateParams = dateCompareParser(dateString) } catch (Exception e) { messageSet.addErrorMessage(e.message) } messageSet } MessageSet nonEmptyValidate(String s){ def messageSet = new MessageSetImpl() if(s == null || s.equals("") || s == ""){ messageSet.addErrorMessage("KOSYAK") } messageSet } Calendar getFieldCalendar(DocumentIssueImpl issue, String field, Long adjustment) { def cal = Calendar.getInstance() def timestamp if (field.startsWith("customfield_")) { if (! cfMap.containsKey(field)) { cfMap.put(field, customFieldManager.getCustomFieldObject(field)) } timestamp = issue.getCustomFieldValue(cfMap.get(field)) as Timestamp } else if (isIndexOnlyField(field)) { def document = issue.document LocalDate localDate = (LocalDate) LuceneUtils.stringToLocalDate(document.get(field)) timestamp = new Timestamp(jqlLocalDateSupport.convertToDate(localDate).getTime()); } // need to disambiguated getCreated from isCreated else if (field == "created") { timestamp = issue.getCreated() } else { timestamp = issue[field as String] as Timestamp } // log.debug("timestamp (${field}): " + timestamp cal.setTime(new Date(timestamp.getTime())) cal.add(Calendar.SECOND, adjustment as Integer) cal } Query getQuery(QueryCreationContext queryCreationContext, FunctionOperand operand, TerminalClause terminalClause) { validate(queryCreationContext.user, operand, terminalClause) Set issueIds = new HashSet() def nonEmpyQuery = new BooleanQuery() nonEmpyQuery.add(new TermQuery(new Term(DocumentConstants.ISSUE_NON_EMPTY_FIELD_IDS, leftField.toLowerCase())), BooleanClause.Occur.MUST) nonEmpyQuery.add(new TermQuery(new Term(DocumentConstants.ISSUE_NON_EMPTY_FIELD_IDS, rightField.toLowerCase())), BooleanClause.Occur.MUST) //log.debug("nonEmpyQuery: ${nonEmpyQuery}") def filterCollector = [apply: {DocumentIssueImpl issue -> // if (! (issue[leftField] && issue[rightField])) { // return // } def lhsCal = getFieldCalendar(issue, leftField, lhs[1] as Long) def rhsCal = getFieldCalendar(issue, rightField, rhs[1] as Long) def match // log.debug("dates") // log.debug("lhs dae: field: ${lhs[0]}, adjustment ${lhs[1]}: " + lhsCal.getTime()) // log.debug("rhs date: field: ${rhs[0]}, adjustment ${rhs[1]}: " + rhsCal.getTime()) // log.debug("Comparison: ${lhs[0]} " + (lhsCal.compareTo(rhsCal) < 0 ? "BEFORE" : "AFTER") + " ${rhs[0]}") if (op == LESS_THAN) { match = lhsCal.compareTo(rhsCal) < 1 } else { match = (lhsCal.compareTo(rhsCal) > 0) } if (match) { issueIds << (issue.id as String) } }] as FilterCollector getIssues(subquery, queryCreationContext.applicationUser, nonEmpyQuery, filterCollector as FilterCollector) new ConstantScoreQuery(new IssueIdFilter(issueIds)) } // todo: maybe shd be static public List dateWindowParser(String param) throws InvalidDurationException { param = param.trim() // if we don't have +- then just returned the trimmed field na if (! (param =~ /[+-]/)) { return [resolveField(param), 0] } // todo: add custom fields // else split on +- and trim def m = param =~ /(.*)([+-])(.*)/ def (String fieldname, String op, String timeInterval) = m[0][1..3].collect {it.toString().trim()} // log.debug("$fieldname, $op, $timeInterval") fieldname = resolveField(fieldname) def Long duration try { duration = DateUtils.getDuration(timeInterval as String) } catch (InvalidDurationException e) { throw new InvalidDurationException("${timeInterval}: ${e.message}.") } if (op == "-") { duration = duration.unaryMinus() } [fieldname, duration] } public static isIndexOnlyField(String fieldname) { return ["sr_first_cmmt_dt", "sr_last_cmmt_dt"].contains(fieldname) } /** * Resolve a fieldname like duedate to dueDate, suitable for looking up in the index * @return name of field as found in the index * @throws Exception field name not supported */ public String resolveField(String fieldname) throws Exception { // validate acceptable fields. Map lowercase to case of the property def dateSystemFields = [ created: "created", updated: "updated", resolutiondate: "resolutionDate", resolved: "resolutionDate", duedate: "dueDate", firstcommented: "sr_first_cmmt_dt", lastcommented: "sr_last_cmmt_dt", ] if (dateSystemFields.containsKey(fieldname.toLowerCase())) { return dateSystemFields.get(fieldname.toLowerCase()) } // check custom fields by name def fields = customFieldManager.getCustomFieldObjectsByName(fieldname) def dateTimeCf = fields.find { it.customFieldType instanceof DateCFType || it.customFieldType instanceof DateTimeCFType } if (! dateTimeCf) { throw new Exception ("Field name: ${fieldname} not found or not a date or datetime.") } else { return dateTimeCf.id } } public List dateCompareParser(String param) { if (! (param =~ /[<>]/)) { throw new Exception("The comparison must contain a either > or < .") } def m = param =~ /(.*)([<>])(.*)/ def (lhs, op, rhs) = m[0][1..3].collect {it.toString().trim()} // parse each side separately // support duedate, created, lastcommented, resolutionDate and date custom fields [op, dateWindowParser(lhs), dateWindowParser(rhs)] } }
I put my function to /var/atlassian/application-data/jira/scripts/com/onresolve/jira/groovy/jql/.
So, validation works, but when I pass a valid JQL to the first parameter, I get an exception:
No signature of method: com.onresolve.jira.groovy.jql.StcDateCompare.getIssues() is applicable for argument types: (java.lang.String, com.atlassian.jira.user.DelegatingApplicationUser, org.apache.lucene.search.BooleanQuery, com.sun.proxy.$Proxy3467) values: [project = SmartLoggerII and type = Reclamation, alekhin(alekhin), ...] Possible solutions: getIssues(), getIssues(java.lang.String, com.atlassian.jira.user.ApplicationUser), getIssues(java.lang.String, com.atlassian.jira.user.ApplicationUser, org.apache.lucene.search.Query), getIssues(java.lang.String, com.atlassian.jira.user.ApplicationUser, org.apache.lucene.search.Query, com.onresolve.jira.groovy.jql.FilterCollector), setIssues(java.util.List) groovy.lang.MissingMethodException: No signature of method: com.onresolve.jira.groovy.jql.StcDateCompare.getIssues() is applicable for argument types: (java.lang.String, com.atlassian.jira.user.DelegatingApplicationUser, org.apache.lucene.search.BooleanQuery, com.sun.proxy.$Proxy3467) values: [project = SmartLoggerII and type = Reclamation, alekhin(alekhin), ...] Possible solutions: getIssues(), getIssues(java.lang.String, com.atlassian.jira.user.ApplicationUser), getIssues(java.lang.String, com.atlassian.jira.user.ApplicationUser, org.apache.lucene.search.Query), getIssues(java.lang.String, com.atlassian.jira.user.ApplicationUser, org.apache.lucene.search.Query, com.onresolve.jira.groovy.jql.FilterCollector), setIssues(java.util.List) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:56) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:151) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:187) at com.onresolve.jira.groovy.jql.StcDateCompare.getQuery(StcDateCompare.groovy:174) at com.onresolve.jira.groovy.jql.JqlQueryFunction$getQuery.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45) at com.onresolve.jira.groovy.jql.DateCompare$getQuery$1.call(Unknown Source) at com.onresolve.jira.groovy.jql.ScriptedJqlFunction.getQuery(ScriptedJqlFunction.groovy:99) at com.onresolve.jira.groovy.jql.ScriptedJqlFunction$getQuery.call(Unknown Source) at com.onresolve.jira.groovy.jql.ScriptedFunctionClauseFactory.getQuery(ScriptedFunctionClauseFactory.groovy:57) at com.atlassian.jira.jql.query.QueryVisitor.visit(QueryVisitor.java:155) at com.atlassian.jira.jql.query.QueryVisitor.visit(QueryVisitor.java:25) at com.atlassian.query.clause.TerminalClauseImpl.accept(TerminalClauseImpl.java:162) at com.atlassian.jira.jql.query.QueryVisitor.createQuery(QueryVisitor.java:72) at com.atlassian.jira.jql.query.DefaultLuceneQueryBuilder.createLuceneQuery(DefaultLuceneQueryBuilder.java:39) at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.createLuceneQuery(LuceneSearchProvider.java:364) at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.getHits(LuceneSearchProvider.java:284) at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.searchAndSort(LuceneSearchProvider.java:464) at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.searchAndSort(LuceneSearchProvider.java:179) <+2> (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.atlassian.plugin.osgi.hostcomponents.impl.DefaultComponentRegistrar$ContextClassLoaderSettingInvocationHandler.invoke(DefaultComponentRegistrar.java:129) at com.sun.proxy.$Proxy73.searchAndSort(Unknown Source) <+2> (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58) at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:56) at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:39) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy2538.searchAndSort(Unknown Source) at com.atlassian.jira.plugin.issuenav.service.issuetable.AbstractIssueTableCreator.collectIssues(AbstractIssueTableCreator.java:166) at com.atlassian.jira.plugin.issuenav.service.issuetable.AbstractIssueTableCreator.executeNormalSearch(AbstractIssueTableCreator.java:236) at com.atlassian.jira.plugin.issuenav.service.issuetable.AbstractIssueTableCreator.create(AbstractIssueTableCreator.java:202) at com.atlassian.jira.plugin.issuenav.service.issuetable.DefaultIssueTableService.createIssueTableFromCreator(DefaultIssueTableService.java:188) at com.atlassian.jira.plugin.issuenav.service.issuetable.DefaultIssueTableService.getIssueTable(DefaultIssueTableService.java:302) at com.atlassian.jira.plugin.issuenav.service.issuetable.DefaultIssueTableService.getIssueTableFromFilterWithJql(DefaultIssueTableService.java:124) at com.atlassian.jira.plugin.issuenav.rest.IssueTableResource.getIssueTableHtml(IssueTableResource.java:99) <+3> (NativeMethodAccessorImpl.java:57) (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) <+12> (AbstractResourceMethodDispatchProvider.java:205) (ResourceJavaMethodDispatcher.java:75) (HttpMethodRule.java:288) (ResourceClassRule.java:108) (RightHandPathRule.java:147) (RootResourceClassesRule.java:84) (WebApplicationImpl.java:1469) (WebApplicationImpl.java:1400) (WebApplicationImpl.java:1349) (WebApplicationImpl.java:1339) (WebComponent.java:416) (ServletContainer.java:537) at com.atlassian.plugins.rest.module.RestDelegatingServletFilter$JerseyOsgiServletContainer.doFilter(RestDelegatingServletFilter.java:178) <+1> (ServletContainer.java:795) at com.atlassian.plugins.rest.module.RestDelegatingServletFilter.doFilter(RestDelegatingServletFilter.java:73) <+16> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) (RestServletUtilsUpdaterFilter.java:26) (RestServletUtilsUpdaterFilter.java:40) (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) (ContextFilter.java:25) (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.mywork.client.filter.ServingRequestsFilter.doFilter(ServingRequestsFilter.java:37) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.plugins.cors.CorsFilter.doFilter(CorsFilter.java:65) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.prettyurls.filter.PrettyUrlsDispatcherFilter.doFilter(PrettyUrlsDispatcherFilter.java:60) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.prettyurls.filter.PrettyUrlsSiteMeshFilter.doFilter(PrettyUrlsSiteMeshFilter.java:92) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.prettyurls.filter.PrettyUrlsMatcherFilter.doFilter(PrettyUrlsMatcherFilter.java:56) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.labs.botkiller.BotKillerFilter.doFilter(BotKillerFilter.java:36) <+18> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (AccessLogFilter.java:103) (AccessLogFilter.java:87) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (XsrfTokenAdditionRequestFilter.java:54) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (ChainedFilterStepRunner.java:87) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (IteratingFilterChain.java:46) (DelegatingPluginFilter.java:66) at com.atlassian.prettyurls.filter.PrettyUrlsCombinedMatchDispatcherFilter.doFilter(PrettyUrlsCombinedMatchDispatcherFilter.java:61) <+22> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (SecurityFilter.java:234) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (TrustedApplicationsFilter.java:100) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (BaseLoginFilter.java:169) (JiraLoginFilter.java:70) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (IteratingFilterChain.java:46) (DelegatingPluginFilter.java:66) (OAuthFilter.java:61) (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.plugins.rest.module.servlet.RestSeraphFilter.doFilter(RestSeraphFilter.java:40) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.prettyurls.filter.PrettyUrlsCombinedMatchDispatcherFilter.doFilter(PrettyUrlsCombinedMatchDispatcherFilter.java:61) <+9> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (AbstractJohnsonFilter.java:71) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176) at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145) at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92) <+10> (UrlRewriteFilter.java:394) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (GzipFilter.java:74) (GzipFilter.java:51) (JiraGzipFilter.java:55) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (IteratingFilterChain.java:46) (DelegatingPluginFilter.java:66) at com.atlassian.prettyurls.filter.PrettyUrlsCombinedMatchDispatcherFilter.doFilter(PrettyUrlsCombinedMatchDispatcherFilter.java:61) <+40> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (ChainedFilterStepRunner.java:87) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (AbstractCachingFilter.java:33) (AbstractHttpFilter.java:31) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (AbstractEncodingFilter.java:41) (AbstractHttpFilter.java:31) (PathMatchingEncodingFilter.java:45) (AbstractHttpFilter.java:31) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (JiraStartupChecklistFilter.java:78) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (MultipartBoundaryCheckFilter.java:41) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (ChainedFilterStepRunner.java:87) (JiraFirstFilter.java:57) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (StandardWrapperValve.java:222) (StandardContextValve.java:123) (AuthenticatorBase.java:502) (StandardHostValve.java:171) (ErrorReportValve.java:100) (StandardEngineValve.java:118) (AccessLogValve.java:953) (CoyoteAdapter.java:408) (AbstractHttp11Processor.java:1041) (AbstractProtocol.java:603) (JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745)
Exception indicates that there is no method getIssues(...), which would correspond to the fact that we are passing it. I tried to override getIssues(...) method, cast parameters on it and try to call super.getIssues(...), but in this way I get exception, that super-class and child class has different classloaders..
Did I do something wrong?
I also tried to add validation in to DateCompare.groovy, pack it into .JAR and install to JIRA, but this way validation is not work. As if I did not change anything.. why?
I'll be very grateful if you can help. Regards, Vladimir.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.