Reputation: 125
I am attempting to create a SpringBoot application that will consume data from a 3rd party REST API and push Websocket notifications to my own clients based on events/changes to that data. The data I am consuming changes frequently, sometimes dozens of times a second (crypto currency price fluctuations behave similarly to this data). I want to repeatedly call the API on a fixed interval (every 1-10 seconds for example), watch for certain events/changes and trigger a Websocket push when those events occur.
I've been able to build a simple Spring Boot app that can push Websocket Notifications and consume the API by following these guides:
The Problem: I can only get the Application to request the data from the API once. I've spent hours searching every variation of "Spring RestTemplate multiple/repeated/persistent calls" I can think of, but I cannot find a solution that addresses my specific use. The closest examples I've found use retries but even those will eventually give up. I want my application to continually request this data until I shut the application down. I know I could wrap it in a while(true)
statement or something like that, but that really doesn't seem right for a framework like SpringBoot and still has problems when trying to instantiate the RestTemplate.
How can I implement persistent querying of a RESTful API resource?
Below is what I have in my Application class
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableScheduling
public class Application {
private static final String API_URL = "http://hostname.com/api/v1/endpoint";
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
RestTemplate restTemplate(RestTemplateBuilder builder){
return builder.build();
}
@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
return args -> {
Response response= restTemplate.getForObject(API_URL, Response.class);
System.out.println(response.toString());
};
}
}
Upvotes: 4
Views: 5405
Reputation: 1906
Add @EnableScheduling
annotation on your SpringConfig class or Main class.
You can use Scheduled fixedDelay OR fixedRate
@Scheduled(fixedDelay = 10000)
public void test() {
System.out.println("Scheduler called.");
}
OR
@Scheduled(fixedRate = 10000)
public void test() {
System.out.println("Scheduler called.");
}
Difference between fixedDelay and fixedRate:
fixedDelay - makes sure that there is a delay of n millisecond between the finish time of an execution of a task and the start time of the next execution of the task.
fixedRate - runs the scheduled task at every n milliseconds.
Ideally, you should externalise the fixedDelay or fixedRate value as well in application.properties file:
@Scheduled(fixedDelayString = "${scheduler.fixed.delay}")
public void test() {
System.out.println("Scheduler called.");
}
In your application.properties file add below config:
scheduler.fixed.delay = 10000
Hope this helps.
Upvotes: 1
Reputation: 1534
CommandLineRunner
only runs once per application start. Instead, you want to use the @Scheduled
annotation to perform repeated operations at fixed intervals like
@Scheduled(fixedDelay = 1000L)
public void checkApi() {
Response response = restTemplate.getForObject(API_URL, Response.class);
System.out.println(response.toString())
}
It does not need to be a Bean
, it can just be a simple method. See the Spring guide for more information https://spring.io/guides/gs/scheduling-tasks/
Upvotes: 4