• Community
  • Products
  • Jira
  • Questions
  • How can I override DateCompare jql function? Or, how can I validate that first parameter of this function must not be empty?

How can I override DateCompare jql function? Or, how can I validate that first parameter of this function must not be empty?

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

1 answer

This widget could not be displayed.

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.

@Thanos Batagiannis [Adaptavist], I need your help!

Suggest an answer

Log in or Sign up to answer
Community showcase
Posted Tuesday in Jira

What modern development practices are at the heart of how your team delivers software?

Hey Community mates! Claire here from the Software Product Marketing team. We all know software development changes rapidly, and it's often tough to keep up. But from our research, we've found the h...

202 views 1 3
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you