Migrating DeadlineManager Quartz to DbScheduler

I have been wanting to get rid of Quartz for a while. As Axon now has support for DbScheduler for deadlines, is there any guidance how it would be possible to migrate existing Quartz triggers to Db-Scheduler. I have over ~3000 active deadlines all the time and I need these migrated.

Would appreciate if anyone has tried to do it or has some advice.

I don’t if anyone tried. The easiest would probably to deploy the updated app using Db-scheduler first. Then run a ‘job migration app’ that get the active jobs from Quartz and put them in Db-scheduler. For that to work it does need to be in the correct format, so you need to use some classes used for serialization from the framework.

I can imagine more people that want to migrate. So maybe we can build something with the Framework team, but there are no plans for that currently.

Of course if you build such a tool we would like to here it.

I managed to successfully migrate as I was looking for. Might as well share the code:

  1. Added db-scheduler spring autoconfiguration dependency
  2. Remove beans:
QuartzEventSchedulerFactoryBean
QuartzDeadlineManager
  1. Apply following configuration changes:
db-scheduler.delay-startup-until-context-ready: true
spring.quartz.auto-startup: false
  1. Execute following migration code (converting from xstream deadline events to jackson):
    Inject:
    org.springframework.scheduling.quartz.SchedulerFactoryBean
    com.github.kagkarlsson.scheduler.Scheduler
    org.axonframework.serialization.Serializer (defaultSerializer)
    org.axonframework.serialization.Serializer (eventSerializer)
fun migrate() {
    val binaryTaskDescriptor = TaskWithDataDescriptor("AxonDeadline", DbSchedulerBinaryDeadlineDetails::class.java)

    schedulerFactoryBean.scheduler.getJobKeys(GroupMatcher.anyJobGroup())
      .filter { it.group != "DEFAULT" }
      .forEach {
        val quartzJobToMigrate = schedulerFactoryBean.scheduler.getJobDetail(it)
        val deadlineMessageFromQuartz = DeadlineJob.DeadlineJobDataBinder.deadlineMessage(this.defaultEventSerializer, quartzJobToMigrate.jobDataMap)
        val deadlineScopeFromQuartz = DeadlineJob.DeadlineJobDataBinder.deadlineScope(this.defaultEventSerializer, quartzJobToMigrate.jobDataMap)

        val taskInstanceId = DbSchedulerDeadlineToken(deadlineMessageFromQuartz.identifier)
        val serializedDescriptor = this.eventSerializer.serialize(deadlineScopeFromQuartz, ByteArray::class.java)
        val serializedPayload = this.eventSerializer.serialize(deadlineMessageFromQuartz.payload, ByteArray::class.java)
        val serializedMetaData = this.eventSerializer.serialize(deadlineMessageFromQuartz.metaData, ByteArray::class.java)
        val details = DbSchedulerBinaryDeadlineDetails(
          deadlineMessageFromQuartz.deadlineName,
          serializedDescriptor.data,
          serializedDescriptor.type.name,
          serializedPayload.data,
          serializedPayload.type.name,
          serializedPayload.type.revision,
          serializedMetaData.data
        )

        val taskInstance = binaryTaskDescriptor.instance(taskInstanceId.id, details)
        dbScheduler.schedule(taskInstance, deadlineMessageFromQuartz.timestamp)
      }
  }
  1. Validate scheduled tasks
  2. Remove Spring Boot Quartz Starter and delete quartz tables