- 浏览: 506363 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (200)
- java基础 (30)
- ajax (19)
- 乱写 (5)
- groovy (2)
- db (8)
- gwt (0)
- jee (2)
- 我关注的开源 (1)
- RIA AIR (1)
- spring (11)
- lucene (0)
- 工具 (10)
- 百科 (2)
- linux (6)
- android (40)
- 移动开发 (21)
- 代码片断 (15)
- tomcat (1)
- css (1)
- html5 (2)
- jquery (2)
- playframework (3)
- web (2)
- nio (3)
- design (1)
- nosql (3)
- 日志 (12)
- mysql (4)
- 图表 (1)
- python (3)
- ruby (1)
- git (0)
- hibernate (1)
- springboot (1)
- guava (1)
- mybatis (0)
- 工作问题 (3)
- php (1)
最新评论
-
linzm1990:
踩了很多坑啊。。。。
hibernate @Nofound 与@ManyToOne fetch lazy的问题 -
Ccccrrrrrr:
...
转: Spring boot 文件上传 -
rmzdb:
兄弟,你这个东西,在ie内核的浏览器,貌似不识别 文件名
工作问题:http下载文件,中文文件名在firefox下乱码问题 -
107x:
问题解决了,谢谢!
工作问题:http下载文件,中文文件名在firefox下乱码问题 -
klxqljq:
额鹅鹅鹅
android布局实现头尾固定, 中间多余内容可以滚动
I am starting a little series about Quartz scheduler internals, tips and tricks, this is a chapter 0 - how to configure persistent job store. In Quartz you essentially have a choice between storing jobs and triggers in memory and in a relation database ( Terracotta is a recent addition to the mix). I would say in 90% of the cases when you use RAMJobStore with Quartz you don't really need Quartz at all. Obviously this storage backend is transient and all your pending jobs and triggers are lost between restarts. If you are fine with that, much simpler and more lightweight solutions are available, including ScheduledExecutorService built into JDK and @Scheduled(cron="*/5 * * * * MON-FRI") in Spring. Can you justify using extra 0,5MiB JAR in this scenario?
This changes dramatically when you need clustering, fail-over, load-balancing and few other buzz-words. There are several use-cases for that:
In all cases above we need some sort of non-transient global storage to keep track which jobs were executed, so that they are run exactly ones by one machine. Relational database as a shared memory works good in this scenario.
So if you think you need to schedule jobs and have some of the requirements above, keep reading. I will show you how to configure Quartz with Spring and fully integrate them. First of all we need a DataSource:
As you might have guessed, Quartz needs some database tables to work with. It does not create them automatically, but SQL scripts for several databases are provided, including H2 which as you can see I am using. I think Flyway is the easiest way to run database scripts on startup:
BTW in case you haven't noticed: no, there is no XML in our sample application and yes, we are using Spring.
Let's move on to Quartz:
It is nice to know you can inject instance of @Configuration annotated classes into another such class for convenience. Except that - nothing fancy. Note that we need @DependsOn(Array("flyway")) on Quartz scheduler factory - otherwise the scheduler might start before Flyway fired the migration script with Quartz database tables causing unpleasant errors on startup. The essential bits are SpringBeanJobFactory and schedulerContextAsMap. The special factory makes Spring responsible for creating Job instances. Unfortunately this factory is quite limited which we will see shortly in the following example. First we need a Spring bean and a Quartz job:
First unexpected input is @BeanProperty instead of @Autowired or @Resource. Turns out that Job is not really a Spring bean, even though Spring creates an instance of it. Instead Spring discovers required dependencies using available setters. So where does the msg string come from? Keep going:
Quartz 2.0 ships with a nice internal DSL for creating jobs and triggers in a readable manner. As you can see I am passing an extra "Hello, world!" parameter to the job. This parameter is stored in so called JobData in the database per job or per trigger. It will be provided to the job when it is executed. This way you can parametrize your jobs. However when executed our job throws NullPointerException... Apparently printer reference was not set and silently ignored. Turns out Spring won't simply look through all the beans available in the ApplicationContext. The SpringBeanJobFactory only looks into Jobs' and Triggers' JobData and into so called scheduler context (already mentioned). If you want to inject any Spring bean into Job you must explicitly place a reference to that bean in schedulerContext:
Unfortunately each and every Spring bean you want to inject to job has to be explicitly referenced in schedulerContextMap. Even worse, if you forget about it, Quartz will silently log NPE at runtime. In the future we will write more robust job factory. But for starters we have a working Spring + Quartz application ready for further experiments, sources as always available under my GitHub account.
You might ask yourself way can't we simply use MethodInvokingJobDetailFactoryBean? Well, first of all because it does not work with persistent job stores. Secondly - because it is unable to pass JobData to Job - so we can no longer distinguish between different job runs. For instance our job printing message would have to always print the same message hard-coded in the class.
This changes dramatically when you need clustering, fail-over, load-balancing and few other buzz-words. There are several use-cases for that:
- single server cannot handle required number of concurrent, long running jobs and the executions need to be split into several machines - but each task must be executed exactly ones
- we cannot afford to run jobs too late - if one server is down, another should run the job on time
- ...or less strictly - the job needs to run eventually - even if the one and only server was down for maintenance, delayed jobs need to be run as soon as possible after restart
In all cases above we need some sort of non-transient global storage to keep track which jobs were executed, so that they are run exactly ones by one machine. Relational database as a shared memory works good in this scenario.
So if you think you need to schedule jobs and have some of the requirements above, keep reading. I will show you how to configure Quartz with Spring and fully integrate them. First of all we need a DataSource:
import org.apache.commons.dbcp.BasicDataSource import com.googlecode.flyway.core.Flyway import org.jdbcdslog.DataSourceProxy import org.springframework.jdbc.datasource.{DataSourceTransactionManager, LazyConnectionDataSourceProxy} import org.h2.Driver @Configuration @EnableTransactionManagement class Persistence { @Bean def transactionManager() = new DataSourceTransactionManager(dataSource()) @Bean @Primary def dataSource() = { val proxy = new DataSourceProxy() proxy.setTargetDSDirect(dbcpDataSource()) new LazyConnectionDataSourceProxy(proxy) } @Bean(destroyMethod = "close") def dbcpDataSource() = { val dataSource = new BasicDataSource dataSource.setDriverClassName(classOf[Driver].getName) dataSource.setUrl("jdbc:h2:mem:quartz-demo;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MVCC=TRUE") dataSource.setUsername("sa") dataSource.setPassword("") dataSource.setMaxActive(20) dataSource.setMaxIdle(20) dataSource.setMaxWait(10000) dataSource.setInitialSize(5) dataSource.setValidationQuery("SELECT 1") dataSource } }
As you might have guessed, Quartz needs some database tables to work with. It does not create them automatically, but SQL scripts for several databases are provided, including H2 which as you can see I am using. I think Flyway is the easiest way to run database scripts on startup:
@Bean(initMethod = "migrate") def flyway() = { val fly = new Flyway() fly.setDataSource(dataSource()) fly }
BTW in case you haven't noticed: no, there is no XML in our sample application and yes, we are using Spring.
Let's move on to Quartz:
@Configuration class Scheduling { @Resource val persistence: Persistence = null @Bean @DependsOn(Array("flyway")) def schedulerFactory() = { val schedulerFactoryBean = new SchedulerFactoryBean() schedulerFactoryBean.setDataSource(persistence.dataSource()) schedulerFactoryBean.setTransactionManager(persistence.transactionManager()) schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties")) schedulerFactoryBean.setJobFactory(jobFactory()) schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext") schedulerFactoryBean.setSchedulerContextAsMap(Map().asJava) schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(true) schedulerFactoryBean } @Bean def jobFactory() = new SpringBeanJobFactory }
It is nice to know you can inject instance of @Configuration annotated classes into another such class for convenience. Except that - nothing fancy. Note that we need @DependsOn(Array("flyway")) on Quartz scheduler factory - otherwise the scheduler might start before Flyway fired the migration script with Quartz database tables causing unpleasant errors on startup. The essential bits are SpringBeanJobFactory and schedulerContextAsMap. The special factory makes Spring responsible for creating Job instances. Unfortunately this factory is quite limited which we will see shortly in the following example. First we need a Spring bean and a Quartz job:
@Service class Printer extends Logging { def print(msg: String) { logger.info(msg) } } class PrintMessageJob extends Job with Logging { @BeanProperty var printer: Printer = _ @BeanProperty var msg = "" def execute(context: JobExecutionContext) { printer print msg } }
First unexpected input is @BeanProperty instead of @Autowired or @Resource. Turns out that Job is not really a Spring bean, even though Spring creates an instance of it. Instead Spring discovers required dependencies using available setters. So where does the msg string come from? Keep going:
val trigger = newTrigger(). withIdentity("Every-few-seconds", "Demo"). withSchedule( simpleSchedule(). withIntervalInSeconds(4). repeatForever() ). build() val job = newJob(classOf[PrintMessageJob]). withIdentity("Print-message", "Demo"). usingJobData("msg", "Hello, world!"). build() scheduler.scheduleJob(job, trigger)
Quartz 2.0 ships with a nice internal DSL for creating jobs and triggers in a readable manner. As you can see I am passing an extra "Hello, world!" parameter to the job. This parameter is stored in so called JobData in the database per job or per trigger. It will be provided to the job when it is executed. This way you can parametrize your jobs. However when executed our job throws NullPointerException... Apparently printer reference was not set and silently ignored. Turns out Spring won't simply look through all the beans available in the ApplicationContext. The SpringBeanJobFactory only looks into Jobs' and Triggers' JobData and into so called scheduler context (already mentioned). If you want to inject any Spring bean into Job you must explicitly place a reference to that bean in schedulerContext:
@Configuration class Scheduling { @Resource val printer: Printer = null @Bean def schedulerFactory() = { val schedulerFactoryBean = new SchedulerFactoryBean() //... schedulerFactoryBean.setSchedulerContextAsMap(schedulerContextMap().asJava) //... schedulerFactoryBean } def schedulerContextMap() = Map( "printer" -> printer ) }
Unfortunately each and every Spring bean you want to inject to job has to be explicitly referenced in schedulerContextMap. Even worse, if you forget about it, Quartz will silently log NPE at runtime. In the future we will write more robust job factory. But for starters we have a working Spring + Quartz application ready for further experiments, sources as always available under my GitHub account.
You might ask yourself way can't we simply use MethodInvokingJobDetailFactoryBean? Well, first of all because it does not work with persistent job stores. Secondly - because it is unable to pass JobData to Job - so we can no longer distinguish between different job runs. For instance our job printing message would have to always print the same message hard-coded in the class.
发表评论
-
浅谈 SpringMVC 数据绑定
2014-10-16 17:20 1114转自: http://senton.iteye.com/blo ... -
转: 当spring 容器初始化完成后执行某个方法
2014-05-05 14:09 1807转自: http://www.cnblogs.com/roll ... -
Quartz scheduler plugins – hidden treasure
2014-02-21 11:10 1745Although briefly described in t ... -
quatrz 任务监控管理 (2)
2009-11-04 12:53 1831转自:http://sundoctor.iteye.com/b ... -
Quartz任务监控管理
2009-11-04 12:18 5883转自 http://sundoctor.iteye.com/b ... -
Quartz 在 Spring 中如何动态配置时间
2009-11-04 12:06 3206转自: http://www.iteye.com/topic/ ... -
Quartz在Spring中动态设置cronExpression(自己写类从数据库里读取)
2009-11-04 11:39 4993什么是动态定时任务? 是由客户制定生成的,服务端只知道该去 ... -
Spring邮件发送
2009-11-04 08:21 37001、单例模式(单发,群 ... -
spring源码解读系列(收集)
2009-09-22 09:04 1463对org.springframework.beans.Cach ... -
如何在基于注解风格的Spring-MVC中使用拦截器
2009-09-22 08:27 4798转自 http://www.blogjava.net/ate ...
相关推荐
You can download the examples (consisting of 60 sample projects) described in this book from the following Google Code project: code.google.com/p/getting-started-with-spring-framework-2edition/ ...
8.3.3.5 Packet Tracer - Configuring Basic OSPFv3 in a Single Area Cisco Packet Tracer 思科模拟器 正确答案文件 可直接上交正确答案文件 本答案版权归mewhaku所有,严禁再次转载!!! Copyright @mewhaku ...
8.1. Configuring Web Flow in Spring 8.1.1. Wiring a flow executor 8.1.2. Configuring a flow registry 8.1.3. Handling flow requests 8.2. The components of a flow 8.2.1. States 8.2.2. Transitions 8.2.3....
Installing and Configuring Openfiler with DRBD and Heartbeat
Table of Contents Configuring a Spring Development Environment Spring Framework Fundamentals Web Application Architecture Spring MVC Architecture Implementing Controllers Implementing Controllers ...
Developers who use Spring Boot often say that they can't imagine going back to hand configuring their applications. About the Book Spring Boot in Action is a developer-focused guide to writing ...
标题 "Configuring Sequences with SFC.ppt" 涉及的是使用西门子SIMATIC PCS 7系统配置顺序控制(Sequential Function Chart,SFC)的相关知识。这是一份技术培训材料,主要介绍了如何在自动化和驱动领域运用SFC来...
本文档《Configuring Sequences with SFC.pdf》来自西门子,主要介绍如何使用顺序功能图(SFC)在SIMATIC PCS 7系统中配置序列。SFC是一种用于描述过程控制序列和程序的图形化编程语言,特别适用于复杂的自动化应用...
Configuring Sales and Distribution in SAP ERP
Oracle GoldenGate Best Practices: Configuring Oracle GoldenGate with Oracle Grid Infrastructure Bundled Agents (XAG)
Lab 07 - Configuring Call Admission Control in Lync
Lab 10 - Configuring Monitoring and Archiving in LS 2010.pdf
西门子 plc Hans Berger Automating with 系列丛书 Automating with SIMATICS 7-1500 Configuring, Programming and Testingwith STEP 7 Professional 2017.pdf
这本书《Configuring and Managing Printing in Oracle Solaris 11.3》详细阐述了如何在Oracle Solaris 11.3操作系统中设置和维护打印环境。出版于2017年12月,此书涵盖了从基础概念到高级技巧的多个层面,旨在确保...
4. Working with Spring Boot 5. Learning about Spring Boot Features 6. Moving to Production 7. Advanced Topics II. Getting Started 8. Introducing Spring Boot 9. System Requirements 9.1. Servlet ...
10. **Configuration**: Configuring MyBatis-Spring typically involves defining the SqlSessionFactoryBean and MapperFactoryBean in your Spring XML configuration, along with the necessary dependencies ...