4

Quartz JobDataMapには次の問題があります。単純な Quartz Jobを使用し、プリミティブでないオブジェクト ( StringBuilderのインスタンスなど) をJobDateMapに渡す場合、メソッドexecute (私のジョブから) は常に、入れたオブジェクトの別のコピーで呼び出される必要があります。残念ながら、 JobDateMapに入れたオブジェクトのインスタンスを常に取得します(StatefulJob のように)。

次の例では、呼び出しごとに単一の「*」を取得することを期待していますが、毎回「*」をもう 1 つ取得します。

public class MyJob implements Job {

    public static void main(String[] args) throws SchedulerException {

        SchedulerFactory schedFact = new StdSchedulerFactory();
        Scheduler sched = schedFact.getScheduler();

        JobDetail jobDetail = new JobDetail("job", Scheduler.DEFAULT_GROUP, MyJob.class);
        jobDetail.getJobDataMap().put("param", new StringBuilder());

        Trigger trigger = TriggerUtils.makeImmediateTrigger("trigger", 10, 100);
        trigger.setGroup(Scheduler.DEFAULT_GROUP);

        sched.scheduleJob(jobDetail, trigger);
        sched.start();

        try {
            Thread.sleep(1000L);
        } catch (Exception e) {}

        sched.shutdown(true);

    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        StringBuilder sb = (StringBuilder) context.getMergedJobDataMap().get("param");
        sb.append("*");
        System.out.println(sb.toString());

    }
}

Quartz がどのように機能しているかについて、何かが欠けていると思います。誰でも何を知っていますか?

4

5 に答える 5

7

Quartz には、より最適化された方法で非プリミティブを渡すことができる機能が他にもあります。SchedulerContext クラスの機能を確認してください。

using System;
using System.Text;
using Quartz;
using Quartz.Impl;

namespace QuartzNET.Samples
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create RAMJobStore instance
            DirectSchedulerFactory.Instance.CreateVolatileScheduler(1);
            ISchedulerFactory factory = DirectSchedulerFactory.Instance;

            // Get scheduler and add object
            IScheduler scheduler = factory.GetScheduler();
            scheduler.Context.Add("History", new StringBuilder("Runtime History: "));

            // Create job and trigger
            IJobDetail job = JobBuilder.Create<MyJob>()
                                       .WithIdentity("MyJob")
                                       .Build();
            ITrigger trigger = TriggerBuilder.Create()
                                             .WithIdentity("Trigger")
                                             .StartNow()
                                             .WithSimpleSchedule(x => x
                                                .WithInterval(TimeSpan.FromMinutes(1))
                                                .RepeatForever())
                                             .Build();

            // Run it all
            scheduler.Start();
            scheduler.ScheduleJob(job, trigger);
        }
    }

    class MyJob : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            var history = context.Scheduler.Context["History"] as StringBuilder;
            history.AppendLine(context.NextFireTimeUtc.ToString());
            Console.WriteLine(context.NextFireTimeUtc);
        }
    }
}
于 2014-10-20T18:23:39.807 に答える
6

「短期的および長期的なデータのシリアル化の問題を回避するために、プリミティブ データ型 (文字列を含む) のみを JobDataMap に格納します。」

ソース: http://www.quartz-scheduler.org/documentation/2.3.1-SNAPSHOT/best-practices.html#jobdatamap-tips

于 2013-02-01T19:07:23.670 に答える
1

プロジェクトで同じエラーが発生していましたが、それをブロックしている別の設定があることに気付きました。構成する場合は、「プロパティに関連しない」オブジェクトを使用できます。Quartz 設定の構成ファイルでこの値を探しています。

<add key="quartz.jobStore.useProperties" value="false" />

False を指定すると、プロパティ以外のオブジェクトを使用できます。これを変更すると(私のものは本当でした)、それは私のために働き始めました。

于 2017-05-15T17:17:44.903 に答える
0

JSON を使用して複雑なオブジェクトをジョブに送信しました。あまりスマートではありませんが、私の目的には適しています。

アプリケーションで:

jobDetail.getJobDataMap().put("YOUR_PARAM_NAME", yourObject.toJson());

あなたの仕事で:

JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String jsonObject = dataMap.getString("YOUR_PARAM_NAME");
YourClass yourObject = YourClass.fromJson(jsonObject);
于 2015-04-09T20:01:38.070 に答える