Reputation: 4523
I'm developing a simple Spring MVC application to download tweets from the streaming API and show them in a webpage. Users of the application can submit a Task
with the keywords of the tweets that they want to download. This tasks are shared so everyone can start, stop, modify, change or cancel a task.
TwitterFetcher
is the class responsible of download tweets. This class receives a Task and persists all tweets downloaded in a database.
@Service
public class TwitterFetcher {
@Autowired
private OAuthService oAuthService;
@Autowired
private TweetService tweetService;
private Task task;
private TwitterStream twitterStream;
public void start(Task task) {
/* Stop previous stream */
stop();
/* Get OAuth credentials */
OAuth oAuth = oAuthService.findOneEnabled();
if (oAuth == null) {
} else {
this.task = task;
Configuration oAuthConfiguration = getOAuthConfiguration(oAuth);
twitterStream = new TwitterStreamFactory(oAuthConfiguration).getInstance();
twitterStream.addListener(new TwitterListener());
String keywords = task.getBaseKeywords() + ", " + task.getExpandedKeywords();
FilterQuery filterQuery = new FilterQuery();
filterQuery.track(keywords.split(", "));
twitterStream.filter(filterQuery);
}
}
public void stop() {
if (twitterStream != null) {
twitterStream.shutdown();
}
}
private Configuration getOAuthConfiguration(OAuth oAuth) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(false);
cb.setJSONStoreEnabled(true);
cb.setOAuthAccessToken(oAuth.getAccessToken());
cb.setOAuthAccessTokenSecret(oAuth.getAccessTokenSecret());
cb.setOAuthConsumerKey(oAuth.getConsumerKey());
cb.setOAuthConsumerSecret(oAuth.getConsumerSecret());
return cb.build();
}
private class TwitterListener implements StatusListener {
@Override
public void onStatus(Status status) {
/* Persist new tweet */
Tweet tweet = new Tweet();
tweet.setJson(DataObjectFactory.getRawJSON(status));
tweetService.save(tweet);
}
[Omitted code]
}
}
The basic functionality would be the next one:
The application has a dashboard to control the fetchers and the tasks and the users must be able to interact with it while the fetcher is downloading.
My question is, Would the fetcher block the app or will be executed in a different thread? In the worst case, what I have to change to solve this? I'm still far from an usable app so I can't test it. Even so, I want to fix it right now if possible.
Upvotes: 1
Views: 1409
Reputation: 3666
Annotate your start() method with @Async.
@Async
public void start(Task task)
This will make the start method asynchronous and will not block the application.
You can check out a simple example here.
Upvotes: 1
Reputation: 41123
You can use ExecutorService to run the fetcher in a separate thread. I'd recommend using ThreadPool so you don't blow performance if too many users running the fetcher:
ExecutorService executor = Executors.newFixedThreadPool(maxThreads)
When a task is submitted through the executor it will return a Future
object from which you can check for job completion
Future f = executor.submit(myTask);
boolean isDone = f.isDone();
Please read more about Java concurrency if you're not familiar: http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
Upvotes: 1