CommandQueue
Quartz Job クラスから参照している Spring シングルトンがあります。ジョブがトリガーされると、CommandQueue に Command をエンキューすることになっています (Command を呼び出す"write()"
と、Jackson を使用してシリアル化され、呼び出すと"Command.create(String)"
コマンドが逆シリアル化されます)。
私が抱えている問題は、Job が Spring ではなく Quartz によってインスタンス化されているため@Autowire
、Job で CommandQueue を作成したり、 への参照を取得したりできないことApplicationContext
です。CommandQueue をジョブのコンストラクターに渡してから、ジョブの JobDataMap で CommandQueue をシリアル化することもできません。これは、CommandQueue を逆シリアル化すると、シングルトンを参照する代わりに新しい CommandQueue インスタンスが作成されるためです。
現在、Job インスタンスから CommandQueue シングルトンを静的に参照する回避策を使用していますが、静的参照に頼らずに同じことを達成する方法があるかどうか疑問に思っています。
public abstract class CommandQueue {
protected static CommandQueue queue;
public static CommandQueue queue() { return queue; }
protected CommandQueue() {}
}
@Service("CommandQueue")
@Scope(value = "singleton")
@Profile({"test"})
public class TestQueue extends CommandQueue {
public TestQueue() { CommandQueue.queue = this; }
}
@Service("CommandQueue")
@Scope(value = "singleton")
@Profile({"production"})
public class ProductionQueue extends CommandQueue {
public ProductionQueue() { CommandQueue.queue = this; }
}
@Service
@Scope(value = "singleton")
public class CommandScheduler {
private final org.quartz.Scheduler scheduler;
public CommandScheduler() {
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
}
public JobKey scheduleRecurringSeconds(final Command command, final int seconds) {
JobDetail job = JobBuilder.newJob(CommandJob.class)
.withIdentity(command.getId()).build();
job.getJobDataMap().put("command", command.write());
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(command.getId()).startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(seconds).repeatForever())
.build();
scheduler.scheduleJob(job, trigger);
}
@DisallowConcurrentExecution
public static class CommandJob implements Job {
public void execute(JobExecutionContext context) {
String str = context.getJobDetail().getJobDataMap().get("command");
Command command = Command.create(str);
CommandQueue.queue().enqueue(command);
}
}
}