Appfuse and Quartz: a very quick tutorial

Source: Internet
Author: User
This article has been written by GFW. For more information, see Appfuse and Quartz: a very quick tutorial.

Quartz is an enterprise-class job schedwn for use in stand-alone and full-blown J2EE applications. it's very easy to implement, scalable and light-weight. I have used Quartz in a number of projects and it works a wonder, no matter if deployed in a complex Weblogic application or a light pojo-based one.
Integrating Quartz with AppFuse (and Spring) is a simple task. For basic scheduling it does not even require you to write a single line of code, everything is done inside the Spring configuration file.
In this tutorial, Quartz is used to invoke a dummy method on the service layer. things shouldn't be much different in a real life implementation, doesn't that your business logic will be probably using a "dao" implementation to access the persistence store.
During this tutorial I will use % APPFUSE % to reference the "HOME" folder of your Appfuse based application.

Configuration
  • Download and uncompress the latest release of Quartz (1.5.2 ).
  • Create a folder namedQuartz-1, 1.5.2In your % APPFUSE %/lib directory and copyQuartz-all-1.5.2.jarInto it.
  • Add the following entry to the lib. properties file, located in % APPFUSE %/lib:
    ## Quartz - http://www.opensymphony.com/quartz/#quartz.version=1.5.2quartz.dir=${lib.dir}/quartz-${quartz.version}quartz.jar=${quartz.dir}/quartz-all-${quartz.version}.jar
  • Add the Quartz library to the deployed webapp. add the entry <lib file = "$ {quartz. jar} "/> at the end of the" package-web "target in the % APPFUSE %/build. xml file.
Code
  • Add a dummy method to the service layer. The purpose of this method is to display how Quartz can call a method on your service layer.
  • Add the following method to UserManager. java
    public void checkLastLogin();
  • Add the following method to UserManagerImpl. java
    public void checkLastLogin() {    log.info("Congratulations! Quartz called the dummy method!");}
  • Add the following xml beans toApplicationContext-service.xmlFile located in % APPFUSE %/src/service/appfuse/service.
    <bean id="dummyJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject"><ref bean="userManager"/></property><property name="targetMethod"><value>checkLastLogin</value></property></bean><bean id="dummyTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  <property name="jobDetail"><ref bean="dummyJobDetail"/>  </property>  <property name="startDelay"><value>30000</value>  </property>  <property name="repeatInterval"><value>45000</value>  </property></bean><bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  <property name="triggers"><list>  <ref local="dummyTrigger"/></list>  </property></bean>

    The SchedulerFactoryBean servesA factory for a Quartz scheduler, Allowing the registering of scheduled jobs via <list> of <refs> to Trigger beans (either SimpleTriggerBean or CronTriggerBean ).

    A Spring SimpleTrigger bean is a wrapper for a Quartz SimpleTrigger that is"A concrete Trigger that is used to fire a JobDetail at a given moment in time, and optionally repeated at a specified interval"(From the Quartz documentation ). A Spring SimpleTrigger holds a reference to a JobDetail bean (the actual business logic that we want to schedule) and has a few more options, such as the "repeat interval" and the "start delay ". both properties are expressed inMilliseconds.

    The MethodInvokingJobDetailFactoryBean is the last bean in the xml snippet. as you can see in the Spring documentation, this bean extends a subclass of the Spring MethodInvoker helper class. the MethodInvoker bean dynamically invokes a method (even a static one) on an arbitrary class, in a declarative way. in a similar fashion, the MethodInvokingJobDetailFactoryBean allows us to specify which method of our service we want to schedule. in the example above, we set a <ref> to the UserManager bean and we set the "checkLastLogin" method as "targetMethod ".
    And so, the "checkLastLogin" method will be invoked every 45 seconds.

  • In case of more sophisticated scheduling needs, Quartz has a Cron based trigger, wrapped by a Spring bean.
    The CronTriggerBean triggers a JobDetail using a "cron" expression.
    <bean id="dummyCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"/>  <property name="jobDetail"/><ref bean="dummyJobDetail"//>  </property/>  <property name="cronExpression"/><!-- Fire every minute starting at 2pm and ending at 2:59pm, every day --/><value/>0 * 14 * * ?</value/>  </property/></bean/>

    The CronTriggerBean is very similar to a SimpleTriggerBean, counter t that a cron expression is required.

Quartz persistence

Quartz usesJobStoresTo persist information about triggers, jobs and calendars.The default Job Store is the "RAMJobStore". As indicated by the name, it keeps all the information in RAM, hence triggers and job information don't keep ve JVM restarts. actually, this can be the desired behavior for an application. on some occasions, it may be necessary to persist the scheduling information on some less volatile storage. that's when the "JDBCJobStore" comes in handy. this JobStore persists all the scheduling information in a database. it comes inTwo flavors:

  • JobStoreTX: used to control transactions or when operating in a non-application server environment
  • JobStoreCMT: used when operating within a managed environment and you want the container to manage the transactions (eg. Spring)

The default JobStore used by Spring is the JobStoreCMT, through a localperformancejobstore that delegates to a Spring-managed DataSource instead of using a Quartz-managed connection pool. Due toLack of serialization capability of the MethodInvokingJobDetailFactoryBean, It is not possible to activate the JDBCJobStore and invoke a method on the service layer using the previous example.
A QuartzJobBean must be used instead. A QuartzJobBean is a simple wrapper around a Quartz Job class.

public class DummyJob extends QuartzJobBean {  private ApplicationContext ctx;  <!-- Always expose this --/>  public void setApplicationContext(ApplicationContext applicationContext) {    this.ctx = applicationContext;  }  protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {    SomeManager sm = (SomeManager)ctx.getBean("someManager");    sm.doScheduledOperation();  }}

As you can see from the code above, it's not possible to inject a bean reference into the QuartzJobBean without incurring serialization issues. therefore the service bean has to be retrieved explicitly from the ApplicationContext. few additional changes have to be implemented to activate a JDBCJobStore and use a QuartzJobBean:

  • Add this entry to the properties. xml file located in % APPFUSE %
    <pathelement location="${quartz.jar}"/>

    The entry has to be added in the "service. compile. classpath" section of the file.

  • After having added the new QuartzJobBean implementation class that invokes some service method on the service layer, change the previous configuration xml:
    <bean id="dummyJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">  <property name="jobClass"><value>com.thetapenet.service.DummyJob</value>  </property>  <!-- This would be great, but doesnt work with JDBCJobStore -->  <!--<property name="jobDataAsMap">    <map>  <entry key="someManager">     <ref bean="someManager"/>  </entry></map>  </property>--></bean><bean id="dummyTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  ...</bean><bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  <property name="dataSource" ref="dataSource"/>  <property name="applicationContextSchedulerContextKey"><value>applicationContext</value>  </property>  <property name="triggers"><list>  <ref local="dummyTrigger"/></list>  </property></bean>

    The SchedulerFactoryBean now has two more properties: the "datasource" and the "applicationContextSchedulerContextKey ". "datasource" instructs the SchedulerFactoryBean to activate the JDBCJobStore and use the global datasource defined in the applicationContext-resources.xml configuration file. the second property is used to propagate the Spring ApplicationContext all the way to the JobDetailBean. please note that a JobDetailBean implementation must always expose

    public void setApplicationContext(ApplicationContext applicationContext) {

    In order for the ApplicationContext to be injected into the Job.

  • The final step requires the creation of the database tables used by Quartz for its own persistence. the Quartz distribution comes with ready-made db scripts that shoshould cover most of the available databases. they can be found in % QUARTZ %/docs/dbTables. I have used the MySQL version of the script and it worked perfectly.

      Copyright 2006 by Luciano Fiandesio.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.