自定义Jfinal Quartz插件报错org.quartz.CronScheduleBuilder cannot be cast to [Ljava.lang.Object

冰小块 发布于 2016/07/07 17:39
阅读 1K+
收藏 0

因为项目需要动态管理quartz的任务调度,所以参考了http://my.oschina.net/u/147181/blog/664223文章里的内容,自定义了一个quartz的插件类,但是在程序启动的时候,总是提示如下错误:

后来发现即便我把原来quartz插件代码拷贝过来用一样会报错,直接使用jfinal-ext2包中的插件就不会报错,这到底是什么情况啊,郁闷死了,求大神们,帮忙看看。

开发环境:jfinal2.2,jfinal-ext2 2.0.5,quartz 2.2.1


2016-07-07 15:46:27
[ERROR]-[Thread: main]-[com.jfinal.core.Config.startPlugins()]: Plugin start error: apache_app.core.MyQuartzPlugin. 
org.quartz.CronScheduleBuilder cannot be cast to [Ljava.lang.Object;
java.lang.ClassCastException: org.quartz.CronScheduleBuilder cannot be cast to [Ljava.lang.Object;
  at apache_app.core.MyQuartzPlugin.startJobs(MyQuartzPlugin.java:90)
  at apache_app.core.MyQuartzPlugin.start(MyQuartzPlugin.java:56)
  at com.jfinal.core.Config.startPlugins(Config.java:88)
  at com.jfinal.core.Config.configJFinal(Config.java:49)
  at com.jfinal.core.JFinal.init(JFinal.java:62)
  at com.jfinal.core.JFinalFilter.init(JFinalFilter.java:49)
  at org.eclipse.jetty.servlet.FilterHolder.doStart(FilterHolder.java:119)
  at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
  at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:724)
  at org.eclipse.jetty.servlet.ServletContextHandler.startContext(Servl




加载中
0
JFinal
JFinal

用一下cron4j 插件,Cron4jPlugin 代码如下:

public class Cron4jPlugin implements IPlugin {
	
	private List<TaskInfo> taskInfoList = new ArrayList<TaskInfo>();
	public static final String defaultConfigName = "cron4j";

	public Cron4jPlugin() {

	}
	
	public Cron4jPlugin(String configFile) {
		this(new Prop(configFile), defaultConfigName);
	}
	
	public Cron4jPlugin(Prop configProp) {
		this(configProp, defaultConfigName);
	}

	public Cron4jPlugin(String configFile, String configName) {
		this(new Prop(configFile), configName);
	}
	
	public Cron4jPlugin(Prop configProp, String configName) {
		try {
			addTask(configProp, configName);
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private void addTask(Prop configProp, String configName) throws Exception {
		String configNameValue = configProp.get(configName);
		if (StrKit.isBlank(configNameValue)) {
			throw new IllegalArgumentException("The value of configName: " + configName + " can not be blank.");
		}
		String[] taskNameArray = configNameValue.trim().split(",");
		for (String taskName : taskNameArray) {
			if (StrKit.isBlank(taskName)) {
				throw new IllegalArgumentException("taskName can not be blank.");
			}
			taskName = taskName.trim();

			String taskCron = configProp.get(taskName + ".cron");
			if (StrKit.isBlank(taskCron)) {
				throw new IllegalArgumentException(taskName + ".cron" + " not found.");
			}
			taskCron = taskCron.trim();

			String taskClass = configProp.get(taskName + ".class");
			if (StrKit.isBlank(taskClass)) {
				throw new IllegalArgumentException(taskName + ".class" + " not found.");
			}
			taskClass = taskClass.trim();

			Object taskObj = Class.forName(taskClass).newInstance();
			if ( !(taskObj instanceof Runnable) && !(taskObj instanceof Task) ) {
				throw new IllegalArgumentException("Task 必须是 Runnable、ITask、ProcessTask 或者 Task 类型");
			}

			boolean taskDaemon  = configProp.getBoolean(taskName + ".daemon", true);
			boolean taskEnable  = configProp.getBoolean(taskName + ".enable", true);
			taskInfoList.add(new TaskInfo(taskCron, taskObj, taskDaemon, taskEnable));
		}
	}

	public Cron4jPlugin addTask(String cron, Runnable task, boolean daemon, boolean enable) {
		taskInfoList.add(new TaskInfo(cron, task, daemon, enable));
		return this;
	}

	public Cron4jPlugin addTask(String cron, Runnable task, boolean daemon) {
		return addTask(cron, task, daemon, true);
	}

	public Cron4jPlugin addTask(String cron, Runnable task) {
		return addTask(cron, task, true, true);
	}

	public Cron4jPlugin addTask(String cron, ProcessTask processTask, boolean daemon, boolean enable) {
		taskInfoList.add(new TaskInfo(cron, processTask, daemon, enable));
		return this;
	}

	public Cron4jPlugin addTask(String cron, ProcessTask processTask, boolean daemon) {
		return addTask(cron, processTask, daemon, true);
	}

	public Cron4jPlugin addTask(String cron, ProcessTask processTask) {
		return addTask(cron, processTask, true, true);
	}

	public Cron4jPlugin addTask(String cron, Task task, boolean daemon, boolean enable) {
		taskInfoList.add(new TaskInfo(cron, task, daemon, enable));
		return this;
	}

	public Cron4jPlugin addTask(String cron, Task task, boolean daemon) {
		return addTask(cron, task, daemon, true);
	}

	public Cron4jPlugin addTask(String cron, Task task) {
		return addTask(cron, task, true, true);
	}
	
	public boolean start() {
		for (TaskInfo taskInfo : taskInfoList) {
			taskInfo.schedule();
		}
		for (TaskInfo taskInfo : taskInfoList) {
			taskInfo.start();
		}
		return true;
	}
	
	public boolean stop() {
		for (TaskInfo taskInfo : taskInfoList) {
			taskInfo.stop();
		}
		return true;
	}
	
	private static class TaskInfo {
		Scheduler scheduler;

		String cron;
		Object task;
		boolean daemon;
		boolean enable;

		TaskInfo(String cron, Object task, boolean daemon, boolean enable) {
			if (StrKit.isBlank(cron)) {
				throw new IllegalArgumentException("cron 不能为空.");
			}
			if (task == null) {
				throw new IllegalArgumentException("task 不能为 null.");
			}

			this.cron = cron.trim();
			this.task = task;
			this.daemon = daemon;
			this.enable = enable;
		}

		void schedule() {
			if (enable) {
				scheduler = new Scheduler();
				if (task instanceof Runnable) {
					scheduler.schedule(cron, (Runnable) task);
				} else if (task instanceof Task) {
					scheduler.schedule(cron, (Task) task);
				} else {
					scheduler = null;
					throw new IllegalStateException("Task 必须是 Runnable、ITask、ProcessTask 或者 Task 类型");
				}
				scheduler.setDaemon(daemon);
			}
		}

		void start() {
			if (enable) {
				scheduler.start();
			}
		}

		void stop() {
			if (enable) {
				if (task instanceof ITask) {
					((ITask)task).stop();
				}
				scheduler.stop();
			}
		}
	}
}

    ITask 文件内容如下:

/**
 * 实现 ITask 接口的 Task,多了一个 stop 方法,插件在停止时会进行回调
 */
public interface ITask extends Runnable {
	abstract void stop();
}

  使用方法:

1:添加依赖

<dependency>
  <groupId>it.sauronsoftware.cron4j</groupId>
  <artifactId>cron4j</artifactId>
  <version>2.2.5</version>
</dependency>

2:在 YourJFinal 中添加插件

me.add(new Cron4jPlugin("cron4jConfig.txt"));

3:在 cron4jConfig.txt 中添加配置

# cron4j 任务调度配置
cron4j=myTask
myTask.cron=0 * * * *
myTask.class=xxx.com.XxxTask
myTask.enable=true
4:让 xxx.com.XxxTask 实现 Runnable 接口,或者ITask 接口也可以,cron 表达式可以精确指定调度规则,记住 cron4j 的cron 表达式只有五部分:分(0-59)、小时(0-23)、天(1-31)、月(1-12)、周(0-6)其中0表示周日,6表示周六
JFinal
JFinal
回复 @冰小块 : 你参考写了一个插件,然后报了一个类型转换异常,并没有贴出任何源代码,相当于让回答者蒙上眼猜孕妇肚子里孩子的性别,所以我给出另一个方案来得实际点,你参考这个方案应该 不会出错 ^_^
冰小块
冰小块
波总,你这个方案只是让我换一个插件用啊,并没有解决我实际上的困惑。我如果直接使用jfinal-ext2扩展包中quartz插件是完全没有问题,只是在自己写插件的时候报错了,并且就算把扩展包中插件的源码原封不动的拷贝到我自己的类里一样会报错。
冰小块
冰小块
感谢波总的回答,一会儿去试一下。
0
冰小块
冰小块

引用来自“JFinal”的评论

用一下cron4j 插件,Cron4jPlugin 代码如下:

public class Cron4jPlugin implements IPlugin {
	
	private List<TaskInfo> taskInfoList = new ArrayList<TaskInfo>();
	public static final String defaultConfigName = "cron4j";

	public Cron4jPlugin() {

	}
	
	public Cron4jPlugin(String configFile) {
		this(new Prop(configFile), defaultConfigName);
	}
	
	public Cron4jPlugin(Prop configProp) {
		this(configProp, defaultConfigName);
	}

	public Cron4jPlugin(String configFile, String configName) {
		this(new Prop(configFile), configName);
	}
	
	public Cron4jPlugin(Prop configProp, String configName) {
		try {
			addTask(configProp, configName);
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private void addTask(Prop configProp, String configName) throws Exception {
		String configNameValue = configProp.get(configName);
		if (StrKit.isBlank(configNameValue)) {
			throw new IllegalArgumentException("The value of configName: " + configName + " can not be blank.");
		}
		String[] taskNameArray = configNameValue.trim().split(",");
		for (String taskName : taskNameArray) {
			if (StrKit.isBlank(taskName)) {
				throw new IllegalArgumentException("taskName can not be blank.");
			}
			taskName = taskName.trim();

			String taskCron = configProp.get(taskName + ".cron");
			if (StrKit.isBlank(taskCron)) {
				throw new IllegalArgumentException(taskName + ".cron" + " not found.");
			}
			taskCron = taskCron.trim();

			String taskClass = configProp.get(taskName + ".class");
			if (StrKit.isBlank(taskClass)) {
				throw new IllegalArgumentException(taskName + ".class" + " not found.");
			}
			taskClass = taskClass.trim();

			Object taskObj = Class.forName(taskClass).newInstance();
			if ( !(taskObj instanceof Runnable) && !(taskObj instanceof Task) ) {
				throw new IllegalArgumentException("Task 必须是 Runnable、ITask、ProcessTask 或者 Task 类型");
			}

			boolean taskDaemon  = configProp.getBoolean(taskName + ".daemon", true);
			boolean taskEnable  = configProp.getBoolean(taskName + ".enable", true);
			taskInfoList.add(new TaskInfo(taskCron, taskObj, taskDaemon, taskEnable));
		}
	}

	public Cron4jPlugin addTask(String cron, Runnable task, boolean daemon, boolean enable) {
		taskInfoList.add(new TaskInfo(cron, task, daemon, enable));
		return this;
	}

	public Cron4jPlugin addTask(String cron, Runnable task, boolean daemon) {
		return addTask(cron, task, daemon, true);
	}

	public Cron4jPlugin addTask(String cron, Runnable task) {
		return addTask(cron, task, true, true);
	}

	public Cron4jPlugin addTask(String cron, ProcessTask processTask, boolean daemon, boolean enable) {
		taskInfoList.add(new TaskInfo(cron, processTask, daemon, enable));
		return this;
	}

	public Cron4jPlugin addTask(String cron, ProcessTask processTask, boolean daemon) {
		return addTask(cron, processTask, daemon, true);
	}

	public Cron4jPlugin addTask(String cron, ProcessTask processTask) {
		return addTask(cron, processTask, true, true);
	}

	public Cron4jPlugin addTask(String cron, Task task, boolean daemon, boolean enable) {
		taskInfoList.add(new TaskInfo(cron, task, daemon, enable));
		return this;
	}

	public Cron4jPlugin addTask(String cron, Task task, boolean daemon) {
		return addTask(cron, task, daemon, true);
	}

	public Cron4jPlugin addTask(String cron, Task task) {
		return addTask(cron, task, true, true);
	}
	
	public boolean start() {
		for (TaskInfo taskInfo : taskInfoList) {
			taskInfo.schedule();
		}
		for (TaskInfo taskInfo : taskInfoList) {
			taskInfo.start();
		}
		return true;
	}
	
	public boolean stop() {
		for (TaskInfo taskInfo : taskInfoList) {
			taskInfo.stop();
		}
		return true;
	}
	
	private static class TaskInfo {
		Scheduler scheduler;

		String cron;
		Object task;
		boolean daemon;
		boolean enable;

		TaskInfo(String cron, Object task, boolean daemon, boolean enable) {
			if (StrKit.isBlank(cron)) {
				throw new IllegalArgumentException("cron 不能为空.");
			}
			if (task == null) {
				throw new IllegalArgumentException("task 不能为 null.");
			}

			this.cron = cron.trim();
			this.task = task;
			this.daemon = daemon;
			this.enable = enable;
		}

		void schedule() {
			if (enable) {
				scheduler = new Scheduler();
				if (task instanceof Runnable) {
					scheduler.schedule(cron, (Runnable) task);
				} else if (task instanceof Task) {
					scheduler.schedule(cron, (Task) task);
				} else {
					scheduler = null;
					throw new IllegalStateException("Task 必须是 Runnable、ITask、ProcessTask 或者 Task 类型");
				}
				scheduler.setDaemon(daemon);
			}
		}

		void start() {
			if (enable) {
				scheduler.start();
			}
		}

		void stop() {
			if (enable) {
				if (task instanceof ITask) {
					((ITask)task).stop();
				}
				scheduler.stop();
			}
		}
	}
}

    ITask 文件内容如下:

/**
 * 实现 ITask 接口的 Task,多了一个 stop 方法,插件在停止时会进行回调
 */
public interface ITask extends Runnable {
	abstract void stop();
}

  使用方法:

1:添加依赖

<dependency>
  <groupId>it.sauronsoftware.cron4j</groupId>
  <artifactId>cron4j</artifactId>
  <version>2.2.5</version>
</dependency>

2:在 YourJFinal 中添加插件

me.add(new Cron4jPlugin("cron4jConfig.txt"));

3:在 cron4jConfig.txt 中添加配置

# cron4j 任务调度配置
cron4j=myTask
myTask.cron=0 * * * *
myTask.class=xxx.com.XxxTask
myTask.enable=true
4:让 xxx.com.XxxTask 实现 Runnable 接口,或者ITask 接口也可以,cron 表达式可以精确指定调度规则,记住 cron4j 的cron 表达式只有五部分:分(0-59)、小时(0-23)、天(1-31)、月(1-12)、周(0-6)其中0表示周日,6表示周六

我以为jfinal-ext插件很有知名度呢,原来波总都布吉岛这个东西,代码如下:(这个代码如果拷贝到我的项目中运行也会报那个类型转换的错误,但是直接从jfinal-ext扩展包中引用就可以正确执行,所以我才会这么苦恼啊)


/**
 * Copyright (c) 2011-2013, kidzhou 周磊 (zhouleib1412@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jfinal.ext.plugin.quartz;

import java.util.Date;
import java.util.Map;
import java.util.Set;

import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import com.jfinal.ext.kit.Reflect;
import com.jfinal.ext.kit.ResourceKit;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.IPlugin;

public class QuartzPlugin implements IPlugin {
    public static final String VERSION_1 = "1";
    private static final String JOB = "job";
    private final Log logger = Log.getLog(getClass());
    private Map<Job, String> jobs = Maps.newLinkedHashMap();
    private String version;
    private SchedulerFactory sf;
    private Scheduler scheduler;
    private String jobConfig;
    private String confConfig;
    private Map<String, String> jobProp;

    public QuartzPlugin(String jobConfig, String confConfig) {
        this.jobConfig = jobConfig;
        this.confConfig = confConfig;
    }

    public QuartzPlugin(String jobConfig) {
        this.jobConfig = jobConfig;
    }

    public QuartzPlugin() {
    }

    public QuartzPlugin add(String jobCronExp, Job job) {
        jobs.put(job, jobCronExp);
        return this;
    }

    @Override
    public boolean start() {
        loadJobsFromProperties();
        startJobs();
        return true;
    }

    private void startJobs() {
        try {
            if (StrKit.notBlank(confConfig)) {
                sf = new StdSchedulerFactory(confConfig);
            } else {
                sf = new StdSchedulerFactory();
            }
            scheduler = sf.getScheduler();
        } catch (SchedulerException e) {
            Throwables.propagate(e);
        }
        Set<Map.Entry<Job, String>> set = jobs.entrySet();
        for (Map.Entry<Job, String> entry : set) {
            Job job = entry.getKey();
            String jobClassName = job.getClass().getName();
            String jobCronExp = entry.getValue();
            JobDetail jobDetail;
            CronTrigger trigger;
            //JobDetail and CornTrigger are classes in 1.x version,but are interfaces in 2.X version.
            if (VERSION_1.equals(version)) {
                jobDetail = Reflect.on("org.quartz.JobDetail").create(jobClassName, jobClassName, job.getClass()).get();
                trigger = Reflect.on("org.quartz.CronTrigger").create(jobClassName, jobClassName, jobCronExp).get();
            } else {
                jobDetail = Reflect.on("org.quartz.JobBuilder").call("newJob", job.getClass()).call("withIdentity", jobClassName, jobClassName)
                        .call("build").get();
                Object temp = Reflect.on("org.quartz.TriggerBuilder").call("newTrigger").get();
                temp = Reflect.on(temp).call("withIdentity", jobClassName, jobClassName).get();
                temp = Reflect.on(temp).call("withSchedule",
                        Reflect.on("org.quartz.CronScheduleBuilder").call("cronSchedule", jobCronExp).get())
                        .get();
                trigger = Reflect.on(temp).call("build").get();
            }
            Date ft = Reflect.on(scheduler).call("scheduleJob", jobDetail, trigger).get();
            logger.debug(Reflect.on(jobDetail).call("getKey") + " has been scheduled to run at: " + ft + " " +
                    "and repeat based on expression: " + Reflect.on(trigger).call("getCronExpression"));
        }
        try {
            scheduler.start();
        } catch (SchedulerException e) {
            Throwables.propagate(e);
        }
    }

    private void loadJobsFromProperties() {
        if (StrKit.isBlank(jobConfig)) {
            return;
        }
        jobProp = ResourceKit.readProperties(jobConfig);
        Set<Map.Entry<String, String>> entries = jobProp.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            if (!key.endsWith(JOB) || !isEnableJob(enable(key))) {
                continue;
            }
            String jobClassName = jobProp.get(key) + "";
            String jobCronExp = jobProp.get(cronKey(key)) + "";
            Class<Job> job = Reflect.on(jobClassName).get();
            try {
                jobs.put(job.newInstance(), jobCronExp);
            } catch (Exception e) {
                Throwables.propagate(e);
            }
        }
    }

    private String enable(String key) {
        return key.substring(0, key.lastIndexOf(JOB)) + "enable";
    }

    private String cronKey(String key) {
        return key.substring(0, key.lastIndexOf(JOB)) + "cron";
    }

    public QuartzPlugin version(String version) {
        this.version = version;
        return this;
    }

    private boolean isEnableJob(String enableKey) {
        Object enable = jobProp.get(enableKey);
        if (enable != null && "false".equalsIgnoreCase((enable + "").trim())) {
            return false;
        }
        return true;
    }

    @Override
    public boolean stop() {
        try {
            scheduler.shutdown();
        } catch (SchedulerException e) {
            Throwables.propagate(e);
        }
        return true;
    }

    public QuartzPlugin confConfig(String confConfig) {
        this.confConfig = confConfig;
        return this;
    }

    public QuartzPlugin jobConfig(String jobConfig) {
        this.jobConfig = jobConfig;
        return this;
    }
}




返回顶部
顶部