Quartz with Spring not commiting

笑着哭i 提交于 2019-12-10 16:28:17

问题


I am using quartz, Spring with Hibernate as the JPA provider. Database is Oracle.

I've got a method which writes a file to the file system and update the database with the details. This method can be called in two ways:

  1. Using a web service
  2. Or, as a scheduled quatrz job.

I've set up quartz as:

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false" scope="singleton">
        <property name="autoStartup" value="true"/>
        <property name="waitForJobsToCompleteOnShutdown" value="true"/>
        <property name="overwriteExistingJobs" value="true"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="transactionManager" ref="transactionManager"/>
        <property name="quartzProperties">
            <props>
                <prop key="org.quartz.scheduler.instanceName">FileScheduler</prop>
                <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
                <prop key="org.quartz.jobStore.misfireThreshold">6000</prop>
                <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
                <prop key="org.quartz.jobStore.driverDelegateClass">${driverDelegateClass}</prop>
                <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
                <prop key="org.quartz.jobStore.isClustered">true</prop>
                <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
                <prop key="org.quartz.threadPool.threadCount">5</prop>
                <prop key="org.quartz.threadPool.threadPriority">5</prop>
            </props>
        </property>
    </bean>

This method is using spring managed transaction.

Problem is when this method is invoked by the quartz scheduler, the file gets created but the database is not updated (there should be two tables updated and one table insert).

I've enabled hibernate show_SQL as well, but in case of scheduler no update\insert statements are getting logged.

Though this works fine when this method is invoked by a web service request. Log shows update\insert statements as well.

UPDATE 1

To summarize my problem, this is what I am trying to achieve:

  1. Create a new record in the employee table.
  2. Save the employee_id in the job_store (quartz).
  3. When trigger is fired, quartz gives back the employee_id
  4. Retrieve (load) the employee record based on this key.
  5. Send Employee an email
  6. Update the Notification with status as 'Sent' (insert statement)

In the end, I expect all the tables to be updated.

When quartz triggers the job, all is working except point 6. Code is correct as when I invoke this method using a web service call, the table is getting updated.

UPDATE 2

I updated the code to use

<prop key="org.quartz.jobStore.class">org.springframework.scheduling.quartz.LocalDataSourceJobStore</prop>

but this also doest'nt help.

Please help. Thanks. Adi


回答1:


Quartz runs in its own context, even if started by the Spring convenience methods, so you actually don't end up getting your whole Spring application context, unless you explicitly at a JobDataMap to pass in beans (see http://forum.springsource.org/showthread.php?76974-Why-autowired-doesn-t-work-on-a-QuartzJobBean-bean). So, you can pass in Spring-managed beans, but it all seems kind of messy if you don't need the full capabilities of Quartz.

If your scheduling needs aren't that complex, you might want to consider using the @Scheduled Spring annotation (see here), as then the entire method call happens natively in the Spring context, and your transactions will then work as they do in the web service call.




回答2:


Here are two points to check:

  • The data source must be a non-XA data source. If you are using a connection pool from a Java EE application server, chances are high that you have a XA data source. Either configure that data source to be non-XA (if your application setup and server allow that) or create a second, non-XA data source and pass it into the nonTransactionalDataSource property. One little gotcha if you use the nonTransactionalDataSource property - remember to keep the dataSource property set. You cannot define a nonTransactionalDataSource without setting the (transactional) dataSource as well.

  • Make sure your code really runs in a Spring transaction. Have your beans injected into the Quartz job using the schedulerContextAsMap property of the SchedulerFactoryBean. If you run code that is annotated with @Transactional it needs to be autowired. If you hard-code the instantiation of that bean, Spring will not be able to apply the @Transactional annotation and silently ignore it.

Also, remove the org.quartz.jobStore.class property. The SchedulerFactoryBean will override that setting in any case. It puts a LocalDataSourceJobStore and it may get confusing if newer versions of the factory decide to put something else.

Last but not least I am wondering if you may have overlooked any exceptions being logged somewhere? Make sure you are monitoring all Spring log messages and all error messages from your application server.




回答3:


Try @Transactional Annotation. (see. http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/transaction/annotation/Transactional.html)



来源:https://stackoverflow.com/questions/10801048/quartz-with-spring-not-commiting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!