quarkus: Quartz cannot find bean instances of jobs

Describe the bug

Hello there,

we have an issue that is present with quarkus 1.13 - 2.0.2, in 1.12 the issue is not yet present.

In our setup we are using quartz to schedule the execution of jobs. Here is a simple implementation example of one of our jobs:

@Startup
@Singleton
class HouseKeepingJob(
  scheduler: Scheduler,
  jobRepository: JobRepository,
  @ConfigProperty(name = "job.timeout") private val timeout: Long,
) : BaseJob(
  jobRepository = jobRepository,
  scheduler = scheduler,
) {

  override fun execute() {
    // implementation details
  }

  override fun getCron() {
    // implementation details
  }
}

class BaseJob(
  scheduler: Scheduler,
  jobRepository: JobRepository,
) {
  init {
    val job = JobBuilder.newJob(this::class.java).build()
    val trigger: Trigger = TriggerBuilder.newTrigger()
      .withSchedule(CronScheduleBuilder.cronSchedule(getCron()))
      .build()

    scheduler.scheduleJob(job, trigger)
  }

  abstract fun getCron(): String
}

As you can see in the above example, we are creating a Singleton instance of our job which should be used by quartz. With quarkus 1.12.x, this is working perfectly fine. From 1.13.x above, we have the issue that in the InvokerJobFactory deep inside quarkus-quartz, the singleton instance of our job cannot be resolved anymore, therefore a fallback is used (SimpleJobFactory) which fails due to a missing no-args constructor on our job. We have found that the jobClass used for bean resolving differs between 1.12 and 1.13 - while in 1.12 the jobClass would be HouseKeepingJob in 1.13 it is HouseKeepingJob_SubClass, which is the only major difference we were able to spot. In the migration guide we cannot find any info concerning such a change. Can you please help us understand what changed and what the best course of action is for us right now?

Thanks

Expected behavior

the singleton instance of our job should still be discoverable in 1.13

Actual behavior

the singleton instance of our job is not discoverable anymore since 1.13

How to Reproduce?

No response

Output of uname -a or ver

Darwin 20.3.0 Darwin Kernel Version 20.3.0: Thu Jan 21 00:06:51 PST 2021; root:xnu-7195.81.3~1/RELEASE_ARM64_T8101 arm64

Output of java -version

openjdk version “11.0.9.1” 2020-11-04 LTS OpenJDK Runtime Environment Zulu11.43+1021-CA (build 11.0.9.1+1-LTS) OpenJDK 64-Bit Server VM Zulu11.43+1021-CA (build 11.0.9.1+1-LTS, mixed mode)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

1.13.7

Build tool (ie. output of mvnw --version or gradlew --version)

gradle 6.7.1

Additional information

No response

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (13 by maintainers)

Commits related to this issue

Most upvoted comments

hey guys, thank you so much for the quick fix and great work in general on this issue, it is much appreciated 😃

I’ve just sent a PR - you can mimic this logic as a workaround.

In 13.x however, the jobName changed to HouseKeepingJob_Subclass, which is not found anymore in the jobs injected into the QuartzScheduler - however, when debugging, I’ve used HouseKeepingJob as the jobName, which successfully retrieved the job instance.

I see. Well, the problem is that the job class is determined using the this::class.java which is really HouseKeepingJob_Subclass (and will be an subclass instance for any intercepted bean). One way to fix this problem is to detect an ArC subclass via io.quarkus.arc.Subclass.isAssignableFrom(jobClass) and if so, then simply use the result of java.lang.Class.getSuperclass().

Also, I dont understand what changed from 12.x -> 13.x that caused this issue to arise.

This is happening for the reason I explained above about the moniroting functionality Arc added.

Exactly, but keep in mind that you would get the same error if the bean that represents the job is intercepted by any interceptor (logging, transactions, etc.).

So from my POV, I am not sure if I have communicated the issue successfully in my posts earlier since the solutions do not really match to the issue, but maybe I just dont understand the answer well enough.

@mkouba the issue is that if monitoring is disabled, everything works as expected. If not, Arc is not resolving the job this leading to the failure of the default implementation

Yes, now fully understand the problem and I tried to describe the solution above ^^. Note that quarkus.arc.dev-mode.monitoring-enabled=false will only work until another interceptor comes into play…

I don’t know much about Quarkus, but I’ll have a look anyway…

@geoand sure you do 😃

Anyway, thanks for having a look at the issue.

Haha, I meant Quartz 😛

I don’t know much about Quarkus, but I’ll have a look anyway…

@geoand sure you do 😃

Anyway, thanks for having a look at the issue.

It looks like Arc should not be trying to create a proxy in this case (as there is no default constructor), but in any case that’s one for @mkouba