What is the simplest way to execute a Java class every 30 seconds?

11,709

Solution 1

I wouldn't bother with Quartz, it's overkill for something this simple. Java5 comes with its own scheduler, and it's good enough.

Pre-Spring 3, this is was the easiest approach:

<bean class="org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean">
    <property name="scheduledExecutorTasks">
        <list>
            <bean class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
                <property name="period" value="30000"/>
                <property name="runnable">
                    <bean class="org.springframework.scheduling.support.MethodInvokingRunnable">
                        <property name="targetObject" ref="pitcher"/>
                        <property name="targetMethod" value="voice"/>
                    </bean>
                </property>
            </bean>
        </list>
    </property>
</bean>

With Spring 3, it can be ridiculously easy:

@Scheduled(fixedRate=30000)
public void voice() {
    System.out.println(getShout());
}

and

<beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:task="http://www.springframework.org/schema/task"
           xsi:schemaLocation="
                http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
           "> 

  <bean id="pitcher" class="spring.com.practice.Pitcher">
     <property name="shout" value="I started executing..."></property>
  </bean>

  <task:annotation-driven/>

</beans>

Solution 2

With Spring 3, you can quickly use @Scheduled and @Async !

Check this out: Implement @Scheduled in Spring Application

Solution 3

It looks complicated, but that really is the best way to do that. You can configure it external to the application, and let spring/quartz handle execution.

This is especially useful when the method you need to call is a transaction-enabled service call.

Solution 4

I have something similar but using the QuartzConnector class in mule, which runs every 20 seconds. See example. The other way would be to use the cron type time entry see Quartz Cron

    <endpoint name="poller" address="quartz://poller1" type="sender" connector="QuartzConnector">
      <properties>
        <property name="repeatInterval" value="20000"/>
        <property name="payloadClassName" value="org.jdom.Document" />
        <property name="startDelay" value="10000"/>                
      </properties>
    </endpoint>  
Share:
11,709
Mrical Singhal
Author by

Mrical Singhal

Updated on June 06, 2022

Comments

  • Mrical Singhal
    Mrical Singhal almost 2 years

    I've been reading about java/spring/hibernate and worked trough a "dummy" examples so I told my friend to recommend something a bit harder for me, and now I'm stuck.. here is the simplest class I could think of

    package spring.com.practice;
    
    public class Pitcher {
    
        private String shout;
    
        public String getShout() {
            return shout;
        }
    
        public void setShout(String shout) {
            this.shout = shout;
        }
    
        public void voice()
        {
            System.out.println(getShout());
        }
    
    }
    

    What is the most simple way to print out something by calling metod voice() from spring beans, and do it repeadatly every 30 seconds lets say, here is what I've got so far :

    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="jobSchedulerDetail" />
        <property name="startDelay" value="0" />
        <property name="repeatInterval" value="30" />
    </bean>
    
    
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="schedulerName" value="pitcherScheduler" />
        <property name="triggers">
            <list>
                <ref bean="simpleTrigger" />
            </list>
        </property>
    </bean>
     <bean id="pitcher" class="spring.com.practice.Pitcher">
     <property name="shout" value="I started executing..."></property>
     </bean>
    

    And yes I'm trying to run this on Jboss 5, I'm building a project with maven.

    I got some suggestions and my application context now looks like :

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sched="http://www.springinaction.com/schema/sched"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springinaction.com/schema/sched
           http://www.springinaction.com/schema/sched-1.0.xsd"
           default-lazy-init="true">
    
       <bean id="stuffDoer" class="spring.com.practice">
       <property name="shout" value="I'm executing"/>
       </bean>
    
      <sched:timer-job
           target-bean="stuffDoer"
           target-method="voice"
           interval="5000" 
           start-delay="1000"
           repeat-count="10" />
    
    </beans>
    

    Here is my web.xml :

    <web-app id="simple-webapp" version="2.4"
        xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <display-name>spring app</display-name>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/conf/applicationContext.xml
    </param-value>
        </context-param>
        <context-param>
            <param-name>log4jConfigLocation</param-name>
            <param-value>/WEB-INF/log4j.properties</param-value>
        </context-param>
        <listener>
            <listener-class>
                org.springframework.web.util.Log4jConfigListener
    </listener-class>
        </listener>
        <listener>
            <listener-class>
                org.springframework.web.context.ContextLoaderListener
    </listener-class>
        </listener>
    </web-app>
    

    Now I get this exeption :

    12:35:51,657 ERROR [01-SNAPSHOT]] Error configuring application listener of class org.springframework.web.context.ContextLoaderListener
    java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
    

    I didn't realize executing something like hello world every 30 sec would be this complicated

  • Mrical Singhal
    Mrical Singhal about 14 years
    @Reverend Gonzo obviously there is something wrong with this .. I get no exeptions, and yet the quartz doesn't execute, copied war to jboss dir .. and still nothing, I created simple webapp hello world to chk is my jboss configured properly, yes it is.
  • Mrical Singhal
    Mrical Singhal about 14 years
    @Wiretap thank you I'm really trying to learn spring and as much as possible about it, so I'd like to use springs quartz
  • Wiretap
    Wiretap about 14 years
    Looks like this may be useful, as sounds like similar situation jroller.com/habuma/entry/a_funny_thing_happened_while
  • Mrical Singhal
    Mrical Singhal about 14 years
    It appears that up to now I didn't link my application context with web.xml here is the error I get now 12:35:51,657 ERROR [01-SNAPSHOT]] Error configuring application listener of class org.springframework.web.context.ContextLoaderListener java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener I'll update my question with appcontext
  • BalusC
    BalusC about 14 years
    That @Scheduled annotation looks really nice.
  • Mrical Singhal
    Mrical Singhal about 14 years
    @skaffman thank you for your response, I'll try that now, the thing is I want to do something more complicated so I want to start from bottom up. I want to create 2 objects that send messages to each other, one to greet other to respond trough JMS messaging on JBOSS 5, and I want this done every 30 seconds. So first thing to consider would be the executing task every 30 seconds and then onwards ..
  • Mrical Singhal
    Mrical Singhal about 14 years
    @skaffman Great answer, I tried it both ways and its working .. w00w tnx
  • skaffman
    skaffman about 14 years
    @BalusC: It is quite tasty, I agree, but in practice you want to make the period configurable, and that's where the annotation doesn't work.
  • lisak
    lisak almost 14 years
    Hello skaffman, could you please explain how ScheduledExecutorFactoryBean is used then ? Or please take a look at this question I can't figure out stackoverflow.com/questions/3021766/… ... You seem to have a strong grasp of this