Due to the fact that I still did not find out a fully satisfying and reactive solution for my topic: click, which the main assumption was:
How to run a Web Flux method cyclically in a reactive way?
I found a walkaround to make it real using the @Scheduled
annotation. Implementation below:
@Component
@AllArgsConstructor
public class Covid19APIHandler {
private Covid19APIService apiService;
private CountryCasesHistoryRepository repository;
private CountryCasesWrapperRepository countryCasesWrapperRepository;
private ServerRequest serverRequest;
public Mono<Void> getCountryCasesAndSave(ServerRequest serverRequest) {
return apiService
.findCasesByCountry()
.flatMap(
wrapper ->
countryCasesWrapperRepository
.save(
CountryCasesWrapper.builder()
.countries_stat(wrapper.getCountries_stat())
.statistic_taken_at(wrapper.getStatistic_taken_at())
.build())
.then(Mono.empty()));
}
@Scheduled(fixedDelay = 10000)
public void casesByCountryScheduled() {
getCountryCasesAndSave(serverRequest);
}
}
The problem is that while code execution I am receiving an error:
Description:
Parameter 3 of constructor in com.covid.application.Covid19APIHandler required a bean of type 'org.springframework.web.reactive.function.server.ServerRequest' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.web.reactive.function.server.ServerRequest' in your configuration.
I tried final
keyword with @RequiredArgsConstructor
, generating all args. constructor via IntelliJ
but still, my ServerRequest
field is not initialized. Here comes the question, how to create my custom bean of ServerRequest
and make it initialized properly. I will be grateful for suggestions on how to make it real.
As pointed out in the comments, why do you even need a ServerRequest
, you arn't even using it. Remove it and clean up the code.
@Component
public class Covid19APIHandler {
private Covid19APIService apiService;
private CountryCasesWrapperRepository countryCasesWrapperRepository;
@Autowire
public Covid19APIHandler(Covid19APIService apiService, CountryCasesHistoryRepository repository) {
this.apiService = apiService;
this.repository = repository;
}
@Scheduled(fixedDelay = 10000)
public void casesByCountryScheduled() {
apiService.findCasesByCountry()
.flatMap(response ->
return countryCasesWrapperRepository.save(
CountryCasesWrapper.builder()
.countries_stat(response.getCountries_stat())
.statistic_taken_at(response.getStatistic_taken_at())
.build()))
.subscribe();
}
}
In this code, your scheduled task will run in accordance to the fixedDelay
if you want it to run each hour i recommend setting a cron
job in the scheduler.
The code will run because of the subscribe
. You see when you call subscribe
you are basically running the code. The consumer
should always be the subscriber
. You application is a consumer
of another application. So your service initiates the request by calling subscribe, this will start the flow of making a request and storing it in your database.
I suggest reading up on the the following
cron job with @Scheduled
Cron syntax
https://en.wikipedia.org/wiki/Cron
Nothing happens until you subscribe (reactor documentation)
https://projectreactor.io/docs/core/release/reference/#reactive.subscribe