@Service
public class SomeServiceImpl implements SomeService, InitializingBean {
@Autowired
private MyTask myTask;
@Override
public void afterPropertiesSet() {
myTask.doSomethingAfterTenMinutes();
}
}
@Component
public class MyTaskImpl implements MyTask {
@Async
@Override
public void doSomethingAfterTenMinutes() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
//error handling
}
//do your task
}
This starts a asynchronous task after a particular bean initialized. That asynchronous task just waits 10 minutes and than runs whatever it needs to do. When all that worked fine and good, I ran into unexpected troubles.I started to notice deployments on our test servers sporadically stopped working. After some investing I noticed tomcat didn't stop properly, resulting in multiple running tomcat processes. I started searching for the origin of this problem and ran into this task. It happened only when deploying within that 10 minute window after a deploy.
The task is initialized during spring's initializing phase of the context, but before tomcat is started. Normally the container will know when you are done starting and marks it done. Apparently this didn't happen anymore when starting a new Thread during the initialization phase. Tomcat wouldn't stop after giving it the command because it was thinking it is still starting up.
A better solution was found quickly in just using the xml based scheduling api:
Lessons learned;<bean id="myTask" class="nl.peecho.task.MyTaskImpl" /> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="myTask" /> <property name="targetMethod" value="doSomethingAfterTenMinutes" /><property name="concurrent" value="false" /> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="jobDetail" /> <property name="startDelay" value="600000" /> <!-- 10 minutes --> <property name="repeatCount" value="0"/> </bean> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simpleTrigger" /> </list> </property> </bean>
- Thread.sleep is evil; always.
- When running a single run task, use the xml based schedulers.