Details
-
Bug
-
Resolution: Fixed
-
Low
-
7.0.2, 7.0.0
-
7
-
Description
Summary
When upgrading to JIRA 7 from an older version, it can fail with a CronSyntaxException, and the upgrade will not continue.
Steps to Reproduce
- Start up JIRA 5.2.x (tested with 5.2.6).
- Setup a filter subscription with an invalid cron expression, such as the one below:
- Export the XML backup.
- Start up JIRA 7.0.x (tested with 7.0.2) and import the XML backup.
Expected Results
The UpgradeTask_Build70010 repairs the malformed cron expression, as per the example below, and the upgrade proceeds without error:
870x1167x1 1mka07y 172.22.48.200 /secure/admin/XmlRestore.jspa [c.a.j.upgrade.tasks.UpgradeTask_Build70010] Repairing malformed cron expression for scheduled job 'com.atlassian.jira.issue.subscription.DefaultSubscriptionManager:10000': '0 0/60 * * * ? *' => '0 0 * * * ? *'
h3. Actual Results
The below exception is thrown, and the upgrade is no longer able to proceed:
015-12-02 15:19:09,057 JiraImportTaskExecutionThread-1 ERROR admin 917x1250x1 n8nftt 172.22.48.200 /secure/admin/XmlRestore.jspa [c.a.jira.upgrade.UpgradeManagerImpl] Exception thrown during upgrade: The step interval for second or minute must be less than 60: 60 com.atlassian.scheduler.cron.CronSyntaxException: The step interval for second or minute must be less than 60: 60 at com.atlassian.scheduler.cron.CronSyntaxException$Builder.build(CronSyntaxException.java:171) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseStep(CronExpressionParser.java:975) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseSlashInterval(CronExpressionParser.java:255) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseNumberExpression(CronExpressionParser.java:321) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseSimpleExpression(CronExpressionParser.java:349) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseSimpleField(CronExpressionParser.java:373) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseSimpleFieldToRule(CronExpressionParser.java:394) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseMinuteField(CronExpressionParser.java:619) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseSecondMinuteHour(CronExpressionParser.java:701) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parseCronExpression(CronExpressionParser.java:745) at com.atlassian.scheduler.caesium.cron.parser.CronExpressionParser.parse(CronExpressionParser.java:167) at com.atlassian.scheduler.caesium.impl.RunTimeCalculator.nextRunTime(RunTimeCalculator.java:110) at com.atlassian.scheduler.caesium.impl.RunTimeCalculator.nextRunTime(RunTimeCalculator.java:79) at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService.calculateNextRunTime(CaesiumSchedulerService.java:255) at com.atlassian.scheduler.core.DelegatingSchedulerService.calculateNextRunTime(DelegatingSchedulerService.java:90) at com.atlassian.jira.upgrade.tasks.UpgradeTask_Build70011.createFilterSubscriptionSchedule(UpgradeTask_Build70011.java:122) at com.atlassian.jira.upgrade.tasks.UpgradeTask_Build70011.upgradeFilterSubscriptionSchedules(UpgradeTask_Build70011.java:114) at com.atlassian.jira.upgrade.tasks.UpgradeTask_Build70011.doUpgrade(UpgradeTask_Build70011.java:86) at com.atlassian.jira.upgrade.UpgradeManagerImpl.doUpgradeTaskSuccess(UpgradeManagerImpl.java:698) at com.atlassian.jira.upgrade.UpgradeManagerImpl.runUpgradeTasks(UpgradeManagerImpl.java:589) at com.atlassian.jira.upgrade.UpgradeManagerImpl.doUpgrade(UpgradeManagerImpl.java:473) at com.atlassian.jira.upgrade.UpgradeManagerImpl.doUpgradeIfNeeded(UpgradeManagerImpl.java:415) at com.atlassian.jira.upgrade.UpgradeManagerImpl.doUpgradeIfNeededAndAllowed(UpgradeManagerImpl.java:359) at com.atlassian.jira.bc.dataimport.DefaultDataImportService.upgradeJira(DefaultDataImportService.java:826) at com.atlassian.jira.bc.dataimport.DefaultDataImportService.performImport(DefaultDataImportService.java:732) at com.atlassian.jira.bc.dataimport.DefaultDataImportService.doImport(DefaultDataImportService.java:312) at com.atlassian.jira.web.action.setup.DataImportAsyncCommand.call(DataImportAsyncCommand.java:60) at com.atlassian.jira.web.action.setup.DataImportAsyncCommand.call(DataImportAsyncCommand.java:28) at com.atlassian.jira.task.ImportTaskManagerImpl$TaskCallableDecorator.call(ImportTaskManagerImpl.java:157) at com.atlassian.jira.task.ImportTaskManagerImpl$TaskCallableDecorator.call(ImportTaskManagerImpl.java:133) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
h3. Workaround
There are several available workarounds for this issue, any of the below can be applied.
Multiple Upgrades
Edit the problematic cron expression(s) in the XML backup. This can be done with the below:
- Locate the problematic cron expression by searching the entities.xml:
- Identify which are problematic by reviewing the exception and corresponding that to the cronExpression. This only applies to elements belonging to QRTZCronTriggers.
- Edit the expression, zip up the entities.xml and the activeobjects.xml.
- Re-import.
Edit the Database
After the upgrade task fails, and throws the above exception, the upgrade can no longer proceed. However you can edit the database and restart JIRA and it will pick up where it failed and proceed without error.
- Stop JIRA.
- Identify the problematic expression, using the exception error message as guidance.
- And then update it, using the results from the SQL above.
- Restart JIRA - the upgrade task will be attempted again, if the cron is a valid expression it will proceed successfully.
Notes
It looks like this occurs as the upgrade task UpgradeTask_Build70010 only checks for the JQRTZCronTriggers entity, and not QRTZCronTriggers which is used in older versions.