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.