David Moreno García
David Moreno García

Reputation: 4523

Run Spring class asynchronously

I'm working in an Spring application that downloads data from different APIs. For that purpose I need a class Fetcher that interacts with an API to fetch the needed data. One of the requirements of this class is that it has to have a method to start the fetching and a method to stop it. Also, it must download all asynchronously because users must be able to interact with a dashboard while fetching data.

Which is the best way to accomplish this? I've been reading about task executors and the different annotations of Spring to schedule tasks and execute them asynchronously but this solutions don't seem to solve my problem.

Upvotes: 1

Views: 2483

Answers (3)

EM-Creations
EM-Creations

Reputation: 4301

You might only need certain methods to run on a separate thread rather than the entire class. If so, the @Async annotation is so simple and easy to use.

Simply add it to any method you want to run asynchronously, you can also use it on methods with return types thanks to Java's Future library.

Check out this page: http://www.baeldung.com/spring-async

Upvotes: 0

dimitrisli
dimitrisli

Reputation: 21381

Asynchronous task execution is what you're after and since Spring 3.0 you can achieve this using annotations too directly on the method you want to run asyncrhonously.

There are two ways of implementing this depending whether you are interested in getting a result from the async process:

@Async
public Future<ReturnPOJO> asyncTaskWithReturn(){
    //..
    return new AsyncResult<ReturnPOJO>(yourReturnPOJOInstance);
}

or not:

@Async
public void asyncTaskNoReturn() {
    //..
}

In the former method the result of your computation conveyed by yourReturnPOJOInstance object instance, is stored in an instance of org.springframework.scheduling.annotation.AsyncResult<V> which in return implements the java.util.concurrent.Future<V> that the caller can use to retrieve the result of the computation later on.

To activate the above functionality in Spring you have to add in your XML config file:

<task: annotation-driven />

along with the needed task namespace.

Upvotes: 3

Chris Thompson
Chris Thompson

Reputation: 35598

The simplest way to do this is to use the Thread class. You supply a Runnable object that performs the fetching functionality in the run() method and when the Thread is started, it invokes the run method in a separate thread of execution.

So something like this:

public class Fetcher implements Runnable{
    public void run(){
      //do fetching stuff
    }
}

//in your code
Thread fetchThread = new Thread(new Fetcher());
fetchThread.start();

Now, if you want to be able to cancel, you can do that a couple of ways. The easiest (albeit most violent and nonadvisable way to do it is to interrupt the thread:

fetchThread.interrupt();

The correct way to do it would be to implement logic in your Fetcher class that periodically checks a variable to see whether it should stop doing whatever it's doing or not.

Edit To your question about getting Spring to run it automatically, if you wanted it to run periodically, you'll need to use a scheduling framework like Quartz. However, if you just want it to run once what you could do is use the @PostConstruct annotation. The method annotated with @PostConstruct will be executed after the bean is created. So you could do something like this

@Service
public class Fetcher implements Runnable{
    public void run(){
      //do stuff
    }

    @PostConstruct
    public void goDoIt(){
      Thread trd = new Thread(this);
      trd.start();
    }
}

Edit 2 I actually didn't know about this, but check out the @Async discussion in the Spring documentation if you haven't already. Might also be what you want to do.

Upvotes: 1

Related Questions