项目使用Spring Quartz,声明如下schedule:
<beans default-autowire="byName">
...
<bean id="schedulerBackend" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="schedulerName">
<value>quartz_backend</value>
</property>
<property name="triggers">
<list>
<!-- 自定义Cron trigger bean -->
<ref local="Customer_CronTriggerBean"/>
</list>
</property>
</bean>
</beans>
OAS环境下部署应用抛出如下异常:
[ERROR][2010-03-02 15:06:25,549] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'backEndService' defined in class path resource [service-appContext.xml]: Cannot resolve reference to bean 'schedulerBackend' while setting bean property 'scheduler'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerBackend' defined in class path resource [service-appContext.xml]: Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: ORA-00942: table or view does not exist
[See nested exception: java.sql.SQLException: ORA-00942: table or view does not exist
]]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:275)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1210)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:978)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:462)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:404)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:375)
... ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerBackend' defined in class path resource [service-appContext.xml]: Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: ORA-00942: table or view does not exist
[See nested exception: java.sql.SQLException: ORA-00942: table or view does not exist
]]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1302)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:463)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:404)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:375)
... 35 more
Caused by: org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: ORA-00942: table or view does not exist
[See nested exception: java.sql.SQLException: ORA-00942: table or view does not exist
]]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.initialize(JobStoreSupport.java:493)
at org.quartz.impl.jdbcjobstore.JobStoreCMT.initialize(JobStoreCMT.java:144)
... 45 more
本身定义的Quartz部分的应用根本涉及不到DB, 怎么会抛出SQL Exception呢,
查看一下出问题的源码
org.springframework.scheduling.quartz.SchedulerFactoryBean
if(dataSource != null)mergedProps.put("org.quartz.jobStore.class", (org.springframework.scheduling.quartz.LocalDataSourceJobStore.class).getName());
看来异常就抛出在这个地方,但是SchedulerFactoryBean的dataSource属性并没有指定啊,为什么不为空呢?
上网搜了一下,原来问题出在Spring配置文件的autowire上。
spring提供了一个通过配置文件进行注入的很简便的功能,就是<beans default-autowire="byName">这段,翻了一下Spring的官方文档,autowire可以配置5个值:
no -- (Default) No autowiring. Bean references must be defined via a ref element. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system.
默认值,不自动装配,给Bean注入属性必须通过<ref />标签,基于较大的spring配置文件,推荐使用这个默认值而不是其他的值,对每一个bean的注入都单独指定,这样比较清晰切易读,一个bean被注入了哪些属性,每个属性都注入的是什么值 都明确指定,一定程度上体现了一个系统的层次结构。
byName -- Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired.
按照属性的名称装配,spring根据bean的属性名自动在指定范围内搜索,如果找到名称匹配的的bean描述,就自动注入给定义的bean。而之前启动quartz失败,也正是因为spring的配置文件指定了default-autowire="byName",而项目中其他部分用的datasource正好命名成通用的“dataSource”,这样spring就“自作聪明”把项目里用的dataSource也注入给了本不想要它的SchedulerFactoryBean。
byType -- Allows a property to be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens; the property is not set. If this is not desirable, setting the dependency-check="objects" attribute value specifies that an error should be thrown in this case.
按照类型装配,按照文档的描述,还是不用它为妙,举例:一个bean1有一个属性是A类型的,而上下文中有一个bean2是A类型的,这样spring就自动把bean2的实例赋值给bean1的这个属性。当上下文中有多个A类型的bean时,这个配置会导致抛出致命异常,而那个A类型的属性也不会set值。
constructor -- Analogous to byType, but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised.
byType的一个变通,只是把byType情况的属性替换为构造函数的参数。相当于上例中的这个bean1的属性改成bean1的构造方法的一个参数。spring把相同类型的bean赋值给这个参数。同类型的参数多于一个时也会抛出致命异常
autodetect -- Chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode is applied.
自动指定,按照类型和按照构造器的一个折衷,如果bean1有默认构造器(无参),则按照byType处理,否则,按照constructor处理。
理解了上面的描述,再回头来看这个问题,解决方案就明朗了:
方法一:去掉default-autowire="byName"配置,也就是用默认配置,这样spring就不会隐式的注入值给属性
方法二:如果想保留byName配置,可以显式的注入null给bean,这样spring也不会把不期望的值再注入给属性,比如上面的配置文件可以改成如下
<beans default-autowire="byName">
...
<bean id="schedulerBackend" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource">
<null /><!-- null 标签,强制把dataSource属性设置为空-->
</property>
<property name="schedulerName">
<value>quartz_backend</value>
</property>
<property name="triggers">
<list>
<!-- 自定义Cron trigger bean -->
<ref local="Customer_CronTriggerBean"/>
</list>
</property>
</bean>
</beans>
这里要注意,如果设置成<value><null/></value>,是不对的,<null />标签直接配置给<property>标签。
方法三: 使byName的配置对这个bean失效,这就有好多实现方式了,例如官方文档上说
Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false ..
也就是把这个bean的autowire-candidate设置为false
<beans default-autowire="byName">
...
<bean id="schedulerBackend" autowire-candidate="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="schedulerName">
<value>quartz_backend</value>
</property>
<property name="triggers">
<list>
<!-- 自定义Cron trigger bean -->
<ref local="Customer_CronTriggerBean"/>
</list>
</property>
</bean>
</beans>
分享到:
相关推荐
Spring整合Quartz是一款常见的任务调度解决方案,它允许开发者在应用程序中安排定时任务的执行。Quartz是一个开源的作业调度框架,而Spring通过...在实际项目中,合理使用Quartz可以极大地提高系统的自动化程度和效率。
现在,Spring启动时会自动初始化Quartz Scheduler并根据配置的Trigger和JobDetail执行任务。在运行应用后,你可以看到每5分钟`SimpleJob`的`execute`方法会被调用一次,打印出"SimpleJob正在执行..."。 以上就是...
SpringQuartz是一个强大的任务调度框架,它在Java应用程序中用于自动化执行特定任务,如定时生成文件、统计数据或执行后台清理工作。Quartz是开源的,具有高度灵活的调度功能,能够根据预定义的时间表触发任务,同时...
这包括自动初始化Scheduler,以及通过Spring的依赖注入(DI)来管理Job的生命周期。 3. **创建Job类**:在Spring-Quartz中,你需要创建一个实现了`org.springframework.scheduling.quartz.JobDetailBean`接口的类,...
标题中的“Spring Quartz 表达式在线生成器”是指一个工具,它可以帮助开发者方便地创建和测试Spring集成Quartz库时所需的定时任务表达式。Quartz是一个强大的、完全开源的作业调度框架,常用于Java应用中执行定时...
Spring Quartz是Spring框架与Quartz任务调度库的集成,它为开发者提供了在Spring应用中进行任务调度的强大功能。Quartz是一个开源的作业调度框架,能够处理执行周期性任务的需求。在Java环境中,Spring Quartz使得...
标题 "Spring + Quartz配置实例(转载)" 暗示了我们将讨论如何在Java环境中整合Spring框架与Quartz作业调度库的使用。Quartz是一个开源的作业调度库,它允许开发者安排任务以在特定时间执行,而Spring框架则是一个...
在 Spring 的配置文件(如 `applicationContext.xml`)中,我们需要引入 Quartz 的配置,并声明一个 `SchedulerFactoryBean` 来实例化和配置 Quartz Scheduler。这通常包括定义数据源、JobDetail 和 Trigger。 2. ...
本文将详细解析“spring quartz定时任务demo”这个项目,它提供了实现Java定时任务的实例,便于快速理解和应用。 首先,Quartz是一个开源的作业调度框架,支持复杂的调度策略,可以创建、调度和执行重复或一次性...
5. **异常处理**: Spring-Quartz可以通过Spring的异常处理机制来捕获和处理Job执行时抛出的异常。 学习Quartz和Spring-Quartz,不仅需要理解它们的基本概念,还要掌握如何在实际项目中进行配置和使用。例如,创建一...
Spring可以自动管理和实例化这些Job,使得任务的生命周期管理更加容易。 5. **CRON Trigger**:在描述中提到的定时任务触发器,可能是指使用了CRON表达式来定义触发规则。CRON表达式是一种字符串格式,用于定义时间...
这个项目展示了如何配置Spring来管理和执行定时任务,利用Quartz的强大功能来实现应用程序的自动化作业调度。 **Spring与Quartz的集成** 1. **Quartz简介**:Quartz是Java平台上的开源作业调度库,它可以用来按...
在Quartz 2.2.3版本中,初始化数据库是使用Quartz的关键步骤,因为Quartz依赖于一个持久化存储来保存作业和触发器的信息。这个过程通常涉及执行一系列SQL语句来创建必要的表结构。 Quartz的初始化SQL语句主要用于...
在多应用服务器负载均衡环境下,Spring Quartz定时任务的重复执行问题是一个常见的挑战。Spring Quartz是一个强大的、开源的作业调度框架,允许开发者定义和执行复杂的定时任务。然而,当多个服务器实例并行运行时,...
在上述实例中,我们看到如何配置和使用Spring Quartz来创建一个简单的定时任务。主要涉及以下几个关键点: 1. **依赖引入**:首先,我们需要引入必要的库,包括quartz.jar(Quartz核心库),spring.jar(Spring核心...
8. **扩展性**:Spring Quartz允许自定义JobFactory和TriggerFactory,以便在创建Job实例和Trigger时添加自定义逻辑,增强了框架的灵活性。 9. **Spring Boot集成**:如果你使用的是Spring Boot,那么Spring Boot...
在Spring中,我们可以使用`SchedulerFactoryBean`来创建和管理Scheduler实例。 4. **JobDetail**:JobDetail存储了Job的详细信息,如Job类、组名和相关的数据。它并不直接触发Job的执行,而是与Trigger一起工作,...
在“quartz实例sqlserver数据库连接”这个主题中,我们主要讨论如何配置Quartz与SQL Server数据库进行交互,以存储和管理调度信息。 首先,Quartz需要一个持久化存储来保存作业(Jobs)和触发器(Triggers)的信息...
Spring Quartz定时任务是Java开发中常见的一种任务调度框架,它结合了Spring的优秀...理解Spring Quartz的工作机制以及如何配置和使用Log4j,对于Java开发者来说是非常重要的技能,能够提升应用的自动化和监控能力。
现在,当Spring容器启动时,Quartz Scheduler也会自动启动,并根据配置的Trigger定时执行Job。如果需要手动调用,可以在main方法中获取Scheduler并触发Job: ```java ApplicationContext context = new ...