<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        HOW-TO:QuartzSchedulerwithClusteringinJEEapplication_MySQL

        來源:懂視網 責編:小采 時間:2020-11-09 19:18:00
        文檔

        HOW-TO:QuartzSchedulerwithClusteringinJEEapplication_MySQL

        HOW-TO:QuartzSchedulerwithClusteringinJEEapplication_MySQL:Quartz Scheduler is one of the most popular scheduling library in Java world. I had worked with Quartz mostly in Spring applications in the past. Recently, I have been investigating scheduling in JEE 6 application running on JBoss 7.1.1 tha
        推薦度:
        導讀HOW-TO:QuartzSchedulerwithClusteringinJEEapplication_MySQL:Quartz Scheduler is one of the most popular scheduling library in Java world. I had worked with Quartz mostly in Spring applications in the past. Recently, I have been investigating scheduling in JEE 6 application running on JBoss 7.1.1 tha
        Quartz Scheduler is one of the most popular scheduling library in Java world. I had worked with Quartz mostly in Spring applications in the past. Recently, I have been investigating scheduling in JEE 6 application running on JBoss 7.1.1 that is going to be deployed in the cloud. As one of the options I consider is Quartz Scheduler as it offers clustering with database. In this article I will show how easy is to configure Quartz in JEE application and run it either on JBoss 7.1.1 or WildFly 8.0.0, use MySQL as job store and utilize CDI to use dependency injection in jobs. All will be done in IntelliJ. Let’s get started.

        Create Maven project

        I usedorg.codehaus.mojo.archetypes:webapp-javaee6archetype to bootstrap the application and then I slightly modified thepom.xml. I also addedslf4Jdependency, so the resultingpom.xmllooks as following:

        	4.0.0	pl.codeleak	quartz-jee-demo	1.0	war	quartz-jee-demo		${project.build.directory}/endorsed	UTF-8				javax	javaee-api	6.0	provided			org.slf4j	slf4j-api	1.7.7			org.slf4j	slf4j-jdk14	1.7.7						org.apache.maven.plugins	maven-compiler-plugin	2.3.2		1.7	1.7		${endorsed.dir}					org.apache.maven.plugins	maven-war-plugin	2.1.1		false				org.apache.maven.plugins	maven-dependency-plugin	2.1			validate		copy			${endorsed.dir}	true	javax	javaee-endorsed-api	6.0	jar						

        The next thing was to import the project to IDE. In my case this is IntelliJ and create a run configuration with JBoss 7.1.1.

        One note, in the VM Options in run configuration I added two variables:

        -Djboss.server.default.config=standalone-custom.xml-Djboss.socket.binding.port-offset=100

        quartz-scheduler-with-clustering-img1

        standalone-custom.xmlis a copy of the standardstandalone.xml, as the configuration will need to be modified (see below).

        Configure JBoss server

        In my demo application I wanted to use MySQL database with Quartz, so I needed to add MySQL data source to my configuration. This can be quickly done with two steps.

        Add Driver Module

        I created a folderJBOSS_HOME/modules/com/mysql/main. In this folder I added two files:module.xmlandmysql-connector-java-5.1.23.jar. The module file looks as follows:

        Configure Data Source

        In thestandalone-custom.xmlfile in thedatasourcessubsystem I added a new data source:

         jdbc:mysql://localhost:3306/javaee com.mysql jeeuserpass 

        And the driver:

         

        Note: For the purpose of this demo, the data source is not JTA managed to simplify the configuration.

        Configure Quartz with Clustering

        I used official tutorial to configure Quarts with Clustering:http://quartz-scheduler.org/documentation/quartz-2.2.x/configuration/ConfigJDBCJobStoreClustering

        Add Quartz dependencies topom.xml

        	org.quartz-scheduler	quartz	2.2.1	org.quartz-scheduler	quartz-jobs	2.2.1

        Addquartz.propertiestosrc/main/resources

        #============================================================================# Configure Main Scheduler Properties#============================================================================org.quartz.scheduler.instanceName = MySchedulerorg.quartz.scheduler.instanceId = AUTO#============================================================================# Configure ThreadPool#============================================================================org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount = 1#============================================================================# Configure JobStore#============================================================================org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegateorg.quartz.jobStore.useProperties = falseorg.quartz.jobStore.dataSource=MySqlDSorg.quartz.jobStore.isClustered = trueorg.quartz.jobStore.clusterCheckinInterval = 5000org.quartz.dataSource.MySqlDS.jndiURL=java:jboss/datasources/MySqlDS

        Create MySQL tables to be used by Quartz

        The schema file can be found in the Quartz distribution:quartz-2.2.1/docs/dbTables.

        Demo code

        Having the configuration in place, I wanted to check if Quartz works, so I created a scheduler, with no jobs and triggers.

        package pl.codeleak.quartzdemo;import org.quartz.JobKey;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.TriggerKey;import org.quartz.impl.StdSchedulerFactory;import org.quartz.impl.matchers.GroupMatcher;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import javax.ejb.Singleton;import javax.ejb.Startup;@Startup@Singletonpublic class SchedulerBean {	private Logger LOG = LoggerFactory.getLogger(SchedulerBean.class);	private Scheduler scheduler;	@PostConstruct	public void scheduleJobs() {	try {	scheduler = new StdSchedulerFactory().getScheduler();	scheduler.start();	printJobsAndTriggers(scheduler);	} catch (SchedulerException e) {	 LOG.error("Error while creating scheduler", e);	}	}	private void printJobsAndTriggers(Scheduler scheduler) throws SchedulerException {	LOG.info("Quartz Scheduler: {}", scheduler.getSchedulerName());	for(String group: scheduler.getJobGroupNames()) {	for(JobKey jobKey : scheduler.getJobKeys(GroupMatcher.groupEquals(group))) {	LOG.info("Found job identified by {}", jobKey);	}	}	for(String group: scheduler.getTriggerGroupNames()) {	for(TriggerKey triggerKey : scheduler.getTriggerKeys(GroupMatcher.groupEquals(group))) {	LOG.info("Found trigger identified by {}", triggerKey);	}	}	}	@PreDestroy	public void stopJobs() {	if (scheduler != null) {	try {	scheduler.shutdown(false);	} catch (SchedulerException e) {	LOG.error("Error while closing scheduler", e);	}	}	}}

        When you run the application you should be able to see some debugging information from Quartz:

        Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.NOT STARTED.Currently in standby mode.Number of jobs executed: 0Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 1 threads.Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is clustered.

        Let Quartz utilize CDI

        In Quartz, jobs must implementorg.quartz.Jobinterface.

        package pl.codeleak.quartzdemo;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;public class SimpleJob implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {// do something}}

        Then to create a Job we use JobBuilder:

        JobKey job1Key = JobKey.jobKey("job1", "my-jobs");JobDetail job1 = JobBuilder.newJob(SimpleJob.class).withIdentity(job1Key).build();

        In my example, I needed to inject EJBs to my jobs in order to re-use existing application logic. So in fact, I needed to inject a EJB reference. How this can be done with Quartz? Easy. Quartz Scheduler has a method to provide JobFactory to that will be responsible for creating Job instances.

        package pl.codeleak.quartzdemo;import org.quartz.Job;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.spi.JobFactory;import org.quartz.spi.TriggerFiredBundle;import javax.enterprise.inject.Any;import javax.enterprise.inject.Instance;import javax.inject.Inject;import javax.inject.Named;public class CdiJobFactory implements JobFactory {	@Inject	@Any	private Instance jobs;	@Override	public Job newJob(TriggerFiredBundle triggerFiredBundle, Scheduler scheduler) throws SchedulerException {	final JobDetail jobDetail = triggerFiredBundle.getJobDetail();	final Class jobClass = jobDetail.getJobClass();	for (Job job : jobs) {	if (job.getClass().isAssignableFrom(jobClass)) {	return job;	}	}	throw new RuntimeException("Cannot create a Job of type " + jobClass);	}}

        As of now, all jobs can use dependency injection and inject other dependencies, including EJBs.

        package pl.codeleak.quartzdemo.ejb;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.ejb.Stateless;@Statelesspublic class SimpleEjb {	private static final Logger LOG = LoggerFactory.getLogger(SimpleEjb.class);	public void doSomething() {	LOG.info("Inside an EJB");	}}package pl.codeleak.quartzdemo;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import pl.codeleak.quartzdemo.ejb.SimpleEjb;import javax.ejb.EJB;import javax.inject.Named;public class SimpleJob implements Job {	@EJB // @Inject will work too	private SimpleEjb simpleEjb;	@Override	public void execute(JobExecutionContext context) throws JobExecutionException {	simpleEjb.doSomething();	}}

        The last step is to modify SchedulerBean:

        package pl.codeleak.quartzdemo;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import org.quartz.impl.matchers.GroupMatcher;import org.quartz.spi.JobFactory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import javax.ejb.Singleton;import javax.ejb.Startup;import javax.inject.Inject;@Startup@Singletonpublic class SchedulerBean {	private Logger LOG = LoggerFactory.getLogger(SchedulerBean.class);	private Scheduler scheduler;	@Inject	private JobFactory cdiJobFactory;	@PostConstruct	public void scheduleJobs() {	try {	scheduler = new StdSchedulerFactory().getScheduler();	scheduler.setJobFactory(cdiJobFactory);	JobKey job1Key = JobKey.jobKey("job1", "my-jobs");	JobDetail job1 = JobBuilder	.newJob(SimpleJob.class)	.withIdentity(job1Key)	.build();	TriggerKey tk1 = TriggerKey.triggerKey("trigger1", "my-jobs");	Trigger trigger1 = TriggerBuilder	.newTrigger()	.withIdentity(tk1)	.startNow()	.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(10))	.build();	scheduler.scheduleJob(job1, trigger1);	scheduler.start();	printJobsAndTriggers(scheduler);	} catch (SchedulerException e) {	LOG.error("Error while creating scheduler", e);	}	}	private void printJobsAndTriggers(Scheduler scheduler) throws SchedulerException {	// not changed	}	@PreDestroy	public void stopJobs() {	// not changed	}}

        Note: Before running the application add beans.xml file to WEB-INF directory.

        You can now start the server and observe the results. Firstly, job and trigger was created:

        12:08:19,592 INFO (MSC service thread 1-3) Quartz Scheduler: MyScheduler12:08:19,612 INFO (MSC service thread 1-3) Found job identified by my-jobs.job112:08:19,616 INFO (MSC service thread 1-3) Found trigger identified by m

        Our job is running (at about every 10 seconds):

        12:08:29,148 INFO (MyScheduler_Worker-1) Inside an EJB12:08:39,165 INFO (MyScheduler_Worker-1) Inside an EJB

        Look also inside the Quartz tables, and you will see it is filled in with the data.

        Test the application

        The last thing I wanted to check was how the jobs are triggered in multiple instances. For my test, I just cloned the server configuration twice in IntelliJ and assigned different port offset to each new copy.

        quartz-scheduler-with-clustering-img2
        Additional change I needed to do is to modify the creation of jobs and triggers. Since all Quartz objects are stored in the database, creating the same job and trigger (with the same keys) will cause an exception to be raised:

        Error while creating scheduler: org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'my-jobs.job1', because one already exists with this identification.

        I needed to change the code, to make sure that if the job/trigger exists I update it. The final code of the scheduleJobs method for this test registers three triggers for the same job.

        @PostConstructpublic void scheduleJobs() {try {	scheduler = new StdSchedulerFactory().getScheduler();	scheduler.setJobFactory(cdiJobFactory);	JobKey job1Key = JobKey.jobKey("job1", "my-jobs");	JobDetail job1 = JobBuilder	.newJob(SimpleJob.class)	.withIdentity(job1Key)	.build();	TriggerKey tk1 = TriggerKey.triggerKey("trigger1", "my-jobs");	Trigger trigger1 = TriggerBuilder	.newTrigger()	.withIdentity(tk1)	.startNow()	.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(10))	.build();	TriggerKey tk2 = TriggerKey.triggerKey("trigger2", "my-jobs");	Trigger trigger2 = TriggerBuilder	.newTrigger()	.withIdentity(tk2)	.startNow()	.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(10))	.build();	TriggerKey tk3 = TriggerKey.triggerKey("trigger3", "my-jobs");	Trigger trigger3 = TriggerBuilder	.newTrigger()	.withIdentity(tk3)	.startNow()	.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(10))	.build();	scheduler.scheduleJob(job1, newHashSet(trigger1, trigger2, trigger3), true);	scheduler.start();	printJobsAndTriggers(scheduler);} catch (SchedulerException e) {	LOG.error("Error while creating scheduler", e);}}

        In addition to the above, I added logging the JobExecutionContext in SimpleJob, so I could better analyze the outcome.

        @Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {try {	LOG.info("Instance: {}, Trigger: {}, Fired at: {}",	context.getScheduler().getSchedulerInstanceId(),	context.getTrigger().getKey(),	sdf.format(context.getFireTime()));} catch (SchedulerException e) {}simpleEjb.doSomething();}

        After running all three server instances I observed the results.

        quartz-scheduler-with-clustering-img3

        Job execution

        I observed trigger2 execution on all three nodes, and it was executed on three of them like this:

        Instance: kolorobot1399805959393 (instance1), Trigger: my-jobs.trigger2, Fired at: 13:00:09Instance: kolorobot1399805989333 (instance3), Trigger: my-jobs.trigger2, Fired at: 13:00:19Instance: kolorobot1399805963359 (instance2), Trigger: my-jobs.trigger2, Fired at: 13:00:29Instance: kolorobot1399805959393 (instance1), Trigger: my-jobs.trigger2, Fired at: 13:00:39Instance: kolorobot1399805959393 (instance1), Trigger: my-jobs.trigger2, Fired at: 13:00:59

        Similarly for other triggers.

        Recovery

        After I disconnected kolorobot1399805989333 (instance3), after some time I saw the following in the logs:

        ClusterManager: detected 1 failed or restarted instances.ClusterManager: Scanning for instance "kolorobot1399805989333"'s failed in-progress jobs.

        Then I disconnected kolorobot1399805963359 (instance2) and again this is what I saw in the logs:

        ClusterManager: detected 1 failed or restarted instances.ClusterManager: Scanning for instance "kolorobot1399805963359"'s failed in-progress jobs.ClusterManager: ......Freed 1 acquired trigger(s).

        As of now all triggers where executed by kolorobot1399805959393 (instance1)

        Running on Wildfly 8

        Without any change I could deploy the same application on WildFly 8.0.0. Similarly to JBoss 7.1.1 I added MySQL module (the location of modules folder is different on WildFly 8 –modules/system/layers/base/com/mysql/main. The datasource and the driver was defined exactly the same as shown above. I created a run configuration for WildFly 8:

        quartz-scheduler-with-clustering-img4
        And I ran the application getting the same results as with JBoss 7.

        I found out the WildFly seem to offer adatabase based store for persistent EJB timers, but I did not investigate it yet. Maybe something for another blog post.

        Source code

      1. Please find the source code for this blog post on GitHub:https://github.com/kolorobot/quartz-jee-demo
      2. Reference:HOW-TO: Quartz Scheduler with Clustering in JEE application with MySQLfrom ourJCG partnerRafal Borowiec at theCodeleak.plblog.

        You might also like:
      3. Getting started with Quartz Scheduler on MySQL database
      4. Quartz 2 Scheduler example
      5. Quartz scheduler plugins – hidden treasure
      6. Related Whitepaper:

        Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

        Get ready to program in a whole new way!

        Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

        Get it Now!

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        HOW-TO:QuartzSchedulerwithClusteringinJEEapplication_MySQL

        HOW-TO:QuartzSchedulerwithClusteringinJEEapplication_MySQL:Quartz Scheduler is one of the most popular scheduling library in Java world. I had worked with Quartz mostly in Spring applications in the past. Recently, I have been investigating scheduling in JEE 6 application running on JBoss 7.1.1 tha
        推薦度:
        標簽: in to mysql
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 日本黄页网址在线看免费不卡| 亚洲第一页中文字幕| 小日子的在线观看免费| 最近中文字幕电影大全免费版| 亚洲伊人久久成综合人影院| 美女又黄又免费的视频| 国产jizzjizz免费视频| 免费福利在线观看| 亚洲裸男gv网站| 国产成人无码区免费网站| 亚洲AV第一页国产精品| 67pao强力打造高清免费| 亚洲国产成人精品无码区在线秒播 | 岛国av无码免费无禁网站| 亚洲第一男人天堂| 国产免费av一区二区三区| 国产免费A∨在线播放| 国产亚洲精久久久久久无码| 欧美激情综合亚洲一二区| 波多野结衣免费视频观看| 人成电影网在线观看免费| 日本免费人成视频播放| 在线观看亚洲视频| 亚洲精品乱码久久久久久| 18禁成人网站免费观看| 亚洲va精品中文字幕| 国产成人精品免费视频软件| 三级黄色片免费看| 亚洲自偷自拍另类12p| 国产卡二卡三卡四卡免费网址| 亚洲Aⅴ在线无码播放毛片一线天| 亚洲AⅤ永久无码精品AA | 美女18毛片免费视频| 亚洲中文字幕无码爆乳AV| 中文字幕免费在线| 无套内射无矿码免费看黄| 亚洲av无码国产精品夜色午夜 | 久久国产精品亚洲综合| 男人的好看免费观看在线视频| 四虎影视久久久免费| 亚洲男人电影天堂|