2

I'm using Spring and have created a web application. In my web app I've a rest service. I have one rest method called process which takes in a user's details (from an angular ui) and saves the users details to a database (SQLite)

Basically what I want to do is that when a user initiates a rest call. I want to start a separate thread (of only which one will exist). This thread will poll a database for certain values and emails an administrator if certain values are found. I need the class to be thread safe. See the below. Am I correct in using something like this ?. Do I need an @Async annotation ? Or should i use a TimerTask instead ?

@EnableScheduling
public class DBPoller {

    @Scheduled(fixedRate = 5000)
    public void checkDatabase() {
        //checks the db for certain values
    }
}
JamesENL
  • 6,400
  • 6
  • 39
  • 64
Silmarillion
  • 207
  • 4
  • 12

2 Answers2

3

You must write

@EnableScheduling

in the Main Class of the Application and the DBPoller class must be an Component of the Spring Framework.

So you must add the Annotation @Component (or @Service) to the Head of the DBPoller Class

Alf
  • 31
  • 4
-1

It sounds like you do want to use an @Async annotation. @Scheduled won't really achieve the effect you are trying to achieve. @Scheduled would work if you were trying to run this check/email scenario on fixed time intervals, rather than on user request. Luckily the config for both is the same.

<task:annotation-driven scheduler="scheduler"
    executor="asyncMethodTaskExecutor" />

<task:scheduler id="scheduler" pool-size="x" />

<bean id="asyncMethodTaskExecutor"
    class="org.springframework.scheduling.quartz.SimpleThreadPoolTaskExecutor">
    <property name="threadCount" value="y"/>
    <property name="threadNamePrefix" value="AsyncMethodWorkerThread"/>
</bean>

If you have the @EnableScheduling annotation, you don't need to define <task:scheduler id="scheduler" pool-size="x" />, but personally I prefer the XML configuration because if you want to change your thread pool size you only have to edit the XML values and restart your application, not recompile and redeploy the whole thing.

Make sure you change x and y to suitable values. This will depend on how many concurrent users you may have on your system.

You also need to make sure that your class is discoverable to the Spring context, and that this method is implementing an interface so that Spring can generate a proxy of it to actually invoke asynchronously like the below example

public interface AsyncService {
    public void checkDatabase();
}

@Service
public class AsyncServiceImpl implements AsyncService {
    @Override
    @Async
    public void checkDatabase(){
        //Do your database check here.
    }
}

You also need to make sure that the package your service is in can be found by Spring, double check your <context:component-scan> value.

Happy asynchronous execution.

JamesENL
  • 6,400
  • 6
  • 39
  • 64