Implement background process in Spring - java

I need to implement Spring process which checks database table for new rows and makes calculations. I'm thinking to implement infinite loop which is triggered every 10 minutes.
Is there someway to implement this with Spring Boot? I can always use Java Thread but it's for sure it's better to let Spring to manage this.

You can try scheduling with Spring Schedule
Here is a official example
Technically, you enable scheduling with #EnableScheduling and annotated your task with #Scheduled(fixedRate=600000).
Another config you can used to tune your scheduler:
fixedRate: Execute the annotated method with a fixed period in milliseconds between invocations.
fixedDelay: Execute the annotated method with a fixed period in milliseconds between the end of the last invocation and the start of the next.
cron: A cron-like expression, extending the usual UN*X definition to include triggers on the second as well as minute, hour, day of month, month and day of week.

find the below sample code
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class AppScheduler {
#Scheduled(fixedRate = 10000)
public void myScheduler() {
System.out.println("Test print");
}
}

It looks like this questions is old, but I would like to answer.
See, you can make an object of ThreadPoolTaskExecutor and assign the background process to it.
Here is my detailed code if anyone wants to see.
https://github.com/xbox2204/SpringBoot-JPA-Swagger-Angular
First thing to do would be, add these two annotation in your application starter class.
#EnableAsync
#EnableScheduling
Now, create you TaskExceutor in the same class and assign it to bean with a name, so that background tasks can be created anywhere in your application and attached with this bean.
#Bean(name="thPlExectr")
public Executor getExecutor(){
return new ThreadPoolTaskExecutor();
}
Now create a component class somewhere in the project, where you you will create the background task.
Here, you will mention the frequency with which you want your task to be exceuted. I wanted to print a statement every 5 second, you can choose your own frequency and give your own method definiton. Also, make it async and attach it with the TaskExecutor bean mentioned above, so that it doesn't interrupt the normal flow of your application.
#Component
public class BackgroundTasks {
private static final Logger log= LoggerFactory.getLogger(BackgroundTasks.class);
#Async("thPlExectr")
#Scheduled(fixedRate = 5000)
public void backTask(){
log.info("Hi Vineet! I am a background task");
}
}

Related

How do you separate roles in Spring Boot ? (Web vs Scheduler, etc..)

I am coming from a (mostly) Python Django/Celery background and starting with Spring Boot.
I am having a hard time to understand how do you separate the roles.
For example when having a Django/Celery project, I will have one one side the web backends started as gunicorn, and on the other side the workers started as celery (so, different commands, but pointing at the same code).
But on Spring Boot, you only have a single entrypoint, and as soon as the scheduler is injected, the jobs will start being processed.
What is the correct way do separate those like in a Django/Celery application ?
Should I put almost all my code as a library and then create 2 final applications, one that will setup the #DispatcherServlet and another one that will setup #EnableScheduling, or is there some kind of configuration to be injected at runtime ?
In my opinion, if 'the web' and 'the scheduler' are both the important function in the application, then we don't need to separate them as long as you are creating a monolithic application.
Because you are using spring boot, so #DispatcherServlet and all the other web component that a web application needed will be injected and configured automatically. The only thing you have to do is creating some class that annotated with #Controller or #RestController and set up the #RequestMapping methods inside those class.
How about Scheduler? you need to add #EnableScheduling in one of the #Configuration class first, then create Scheduler class in scheduler package like below code sample.
You can use cron property to set up the specify execute time just like Linux crontab. The jobs will start being processed only if the cron time is up.
#Component
public class PlatformScheduler {
#Autowired
private BatchService batchService;
#Scheduled(cron = "0 0 12 * * *")
public void dailyInitialize() {
clearCompletedBatches();
queryBatchesToRunToday();
}
#Scheduled(fixedRate = 10000, initialDelay = 10000)
private void harvestCompletedBatches() {
batchService.harvestCompletedBatches();
}
#Scheduled(fixedRate = 10000, initialDelay = 10000)
private void executeWaitingBatches() {
batchService.executeWaitingBatches(new DateTime());
}
}
The most simple project hierarchy will be like below, 'the web' and 'the scheduler' can be in the same project safely and share the same #Service components without harm.

How to schedule executing method for certain time during runtime

Lets say I have some rest api where arguments are time when to execute method and second argument is name of the method in class. What is the best way for invoking call of this method in certain time (just once) in spring-boot application ?
First, enable scheduling in your spring-boot application:
#SpringBootApplication
#EnableScheduling
public class Application {
// ...
Then, inject the TaskScheduler bean and schedule the task programmatically every time the user invokes the REST method:
public class MyScheduler {
#Autowired
private TaskScheduler scheduler;
public void scheduleNewCall(Date dateTime) {
scheduler.schedule(this::scheduledMethod, dateTime);
}
public void scheduledMethod() {
// method that you wish to run
}
}
However, you should also think about limiting the amount of calls to this method, otherwise the malicious user could schedule a lot of tasks and overflow the task pool.

Spring - Dynamically add and remove scheduled task

I am working on spring based server application. Basically it will poll scores of various sporting events in very short interval and save in db. For polling there will be many(can be around 100) calls to different apis concurrently at regular interval for example some api call will have 3 seconds interval some have 5 seconds etc., server will keep polling for latest data at frequent interval.
These calls will be added and removed dynamically. I have little experience in using spring. I think I have to use some scheduler. Can anyone point in right direction what approach or which scheduler is best in this scenario.
In essence you want to inject an instance of a scheduling task executor
#Configuration
public class MyApplicationConfiguration {
#Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler tpts = new ThreadPoolTaskScheduler();
// maybe configure it a little?
return tpts;
}
#Bean
public MyService myService() {
return new MyService();
}
}
class MyService {
#Autowired
private ThreadPoolTaskScheduler tpts;
public void doSomething() {
Runnable task = ...
tpts.scheduleWithFixedDelay(task, 1000);
}
}
You can see a reasonable guide here, or the SchedulingTaskExecutor Javadoc and the Spring Task Execution and Scheduling Reference
You can use #Scheduled Spring Annotation for this. Refer this link for examples.

Spring Boot: Configure Job Scheduler Pool via Annotation

I have a Spring Boot Application with a bunch of background jobs. I have added the following Annotation on my main application class:
#SpringBootApplication
#EnableScheduling
public class MyApplication {
In the job class, I have following configuration:
#Component
public class MyTask {
#Scheduled(fixedDelay = 14400000)
public void doSomething()
Right now, Spring Boot is executing the jobs in a sequential manner, i.e., one job at a time. This seems most likely due to a single thread based pool.
Is there any Annotation/property that can be used to increase the thread pool size?
Till now, I have found a solution here, but it requires writing a new Configuration class.
Ideally, it should be a property in application.properties file.
I usually don't put business logic inside a #Scheduled method, instead, I call another method in other component and this method has the #Async annotation. When your scheduled job is fired, then it calls the async method in another thread and you scheduler is free to run other jobs.
Check more how to do it here: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-annotation-support
I don't see a property for this in https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html and I don't see any annotation in the docs.
If you want it configurable at that level, just create your own custom properties, which you inject into the other solution you found.

java scheduler spring vs quartz

Currently I am building a spring standalone program in order to learn new methods and architectures.
The last few days I tried to learn scheduler. I never used them before so I read some articles handling the different possible methods. Two of them are especially interesting: The spring nativ #Scheduler and Quartz.
From what I read, Spring is a little bit smaller then Quartz and much more basic. And quartz is not easy to use with spring (because of the autowired and components).
My problem now is, that there is one thing I do not understand:
From my understanding, both methods are creating parallel Threads in order to asynchronously run the jobs. But what if I now have a spring #Service in my main Application, that is holding a HashMap with some information. The data is updated and changed with user interaction. Parallel there are the scheduler. And a scheduler now whants to use this HashMap from the main application as well. Is this even possible?
Or do I understand something wrong? Because there is also the #Async annotation and I did not understand the difference. Because a scheduler itself is already parallel to the main corpus, isn't it?
(summing up, two questions:
can a job that is executed every five seconds, implemented with a scheduler, use a HashMap out of a service inside the main program? (in spring #Scheduler and/or in Quartz?)
Why is there a #Async annotation. Isn't a scheduler already parallel to the main process?
)
I have to make a few assumptions about which version of Spring you're using but as you're in the process of learning, I would assume that you're using spring-boot or a fairly new version, so please excuse if the annotations don't match your version of Spring. This said, to answer your two questions the best I can:
can a job that is executed every five seconds, implemented with a scheduler, use a HashMap out of a service inside the main program? (in spring #Scheduler and/or in Quartz?)
Yes, absolutely! The easiest way is to make sure that the hashmap in question is declared as static. To access the hashmap from the scheduled job, simply either autowire your service class or create a static get function for the hashmap.
Here is an example of a recent Vaadin project where I needed a scheduled message sent to a set of subscribers.
SchedulerConfig.class
#Configuration
#EnableAsync
#EnableScheduling
public class SchedulerConfig {
#Scheduled(fixedDelay=5000)
public void refreshVaadinUIs() {
Broadcaster.broadcast(
new BroadcastMessage(
BroadcastMessageType.AUTO_REFRESH_LIST
)
);
}
}
Broadcaster.class
public class Broadcaster implements Serializable {
private static final long serialVersionUID = 3540459607283346649L;
private static ExecutorService executorService = Executors.newSingleThreadExecutor();
private static LinkedList<BroadcastListener> listeners = new LinkedList<BroadcastListener>();
public interface BroadcastListener {
void receiveBroadcast(BroadcastMessage message);
}
public static synchronized void register(BroadcastListener listener) {
listeners.add(listener);
}
public static synchronized void unregister(BroadcastListener listener) {
listeners.remove(listener);
}
public static synchronized void broadcast(final BroadcastMessage message) {
for (final BroadcastListener listener: listeners)
executorService.execute(new Runnable() {
#Override
public void run() {
listener.receiveBroadcast(message);
}
});
}
}
Why is there a #Async annotation. Isn't a scheduler already parallel to the main process?
Yes, the scheduler is running in its own thread but what occurs to the scheduler on long running tasks (ie: doing a SOAP call to a remote server that takes a very long time to complete)?
The #Async annotation isn't required for scheduling but if you have a long running function being invoked by the scheduler, it becomes quite important.
This annotation is used to take a specific task and request to Spring's TaskExecutor to execute it on its own thread instead of the current thread. The #Async annotation causes the function to immediately return but execution will be later made by the TaskExecutor.
This said, without the #EnableAsync or #Async annotation, the functions you call will hold up the TaskScheduler as they will be executed on the same thread. On a long running operation, this would cause the scheduler to be held up and unable to execute any other scheduled functions until it returns.
I would suggest a read of Spring's Documentation about Task Execution and Scheduling It provides a great explanation of the TaskScheduler and TaskExecutor in Spring

Categories