I am using J2EE with Jboss server. I am trying to finding a way to invoke sendEmail api in my code every month.
#GET
#Path("/sendEmail")
#Transactional
public String test(){
I want to invoke this test api which can be accessed using web-browser http://localhost:8181/api/calc/sendEmail
I found some ways to do this:
https://cloud.google.com/appengine/docs/java/config/cron
https://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/
Using cron job looks intuitive way to do this but I find it difficult to search resources to find a way to schedule invoking of the APIs using it.
Please point me to some resources where I can find a way to do so by just adding single dependency for this purpose in pom.xml
You can use Spring Framework for this.
Something like this:
#Scheduled(cron = "0 0 12 1 1/1 ? *")
public void doScheduledWork() {
Check the following link: Spring cron expression for every day 1:01:am
When the application is deployed in multiple boxes or multiple pods(in case of kubernetes) then in each pods the cron expression gets set.
This results in the cron getting triggered n(number of pods) times which results in error case. Better option is to call the cron from external monolith configuration systems by calling through an api.
Applying on a method with the annotation is apt if application runs in only one box(pure monolith).
Related
How can I run a task from the command line for long-running jobs like reports from Jenkins in Spring Boot? I'm looking for something similar to Ruby on Rails Rake tasks. Rake tasks execute the code from the command line in the same application context as the web server so that you can re-use code.
I found Spring Batch but it sounded more like Resque.
I found command line runners but it said that they all run before the web server starts, so I can't not run it or only run one task.
I found scheduled tasks which sounds perfect, but my app is load balanced with many instances so I would not want it running multiple times at once!
I have a report where the query takes more than 30s to run, and generates a CSV file I would like to mail. I want it to run automatically each week with cron or Jenkins.
I hacked a solution. Suggestions welcome.
package com.example.tasks;
#Component
public class WeeklyReport implements CommandLineRunner {
#Override
public void run(String... args) throws Exception {
Arrays.asList(args).stream().forEach(a -> System.out.println(a));
if (!(args.length > 0 && args[0].equals("-task report:weekly"))) return;
System.out.println("weekly report");
System.exit(0);
}
And running it from a 'cron' job with
$ mvn spring-boot:run -Drun.arguments="-task report:weekly"
https://docs.spring.io/spring-boot/docs/1.5.19.RELEASE/reference/htmlsingle/#boot-features-command-line-runner
https://www.baeldung.com/spring-boot-command-line-arguments
https://therealdanvega.com/blog/2017/04/07/spring-boot-command-line-runner
I was facing a similar problem recently and I came up with these three possible solutions:
Designate a "housekeeper" role that can be assumed by at most one instance whose responsibility would be complete the scheduled job. But for this the housekeeper would have to send a heartbeat to the others (through the load balancer..) and if it stops then the remaining instances must elect a new one so it seems to be an interesting but way more complex approach that I might play with later.
Have a single-instance external service that would run scheduled tasks and will generate the weekly csv for you
Have a single-instance external service that only has the capacity to make scheduled api calls and that would call your original service through the load balancer. I prefer this solution as all the resources to complete the task are already present at the original service and it preserves the functionality. It is also flexible as the scheduler service can be replaced by more light weight cron job with a curl call or merged to another service in the future..etc.
I have developed a spring boot project.
It uses #EnableScheduling and #Scheduled annotations to schedule task. I have tried both ways to schedule my function.
1)
#Scheduled(initialDelayString = "${scheduler.initialDelay}", fixedDelayString = "${scheduler.fixedDelay}")
2)
#Scheduled(cron = "0 0 1 * * *")
In both ways when I run my code locally, It gets run perfectly fine. But when I deploy my code to AWS instance using auto scaling group, spring application gets start, but after that nothing is happening. I don't even see any logs or error about scheduler. Application is running but scheduler is not getting invoked.
It seems very strange to me. And since its working perfectly very well in local, it is difficult to debug also.
I had a similar issue, I believe its to do with the Springboot default threadpool for scheduling. It worked for me when i altered the below setting in application.properties / yaml
spring.task.scheduling.pool.size=20
I wrote a core Java program that will update the database based on some criteria. It just fetched some data from table and manipulates it and store the new data.
I need to run this program at 3.0 am everyday.
can a core java program be run in a web server through cron jobs.
Or only servlet can be run on the server side? I'm new to this. Please help.
crontab 0 3 * * * myshell.sh
where your shell runs java -jar myapp.jar
or simply use build-in db sheduler
some details are missing but:
if you use a web server (tomcat?) only to use a container for the application, you can consider to deploy the application as a standalone jar, and then execute it using linux crontab (assuming you're using linux).
usage example 1, usage example 2.
i don't know if you need it, but when you execute the task with crontab, you can pass arguments to the executed task.
if you decided to use the web server, then you can write a java code, that schedules a timed task (you can schedule it with a specific time to run, an interval). when the task is executed, it can then run the code that manipulates the data. there are different implementation for the issue (java's TimerTask, quartz and more). you can read about them here.
As mentioned by Drimity you can put the java program run command in a script and schedule the script.
echo "start"
java YourClass
echo "end"
Its a good practice to redirect all output of your java program to a log file instead of System.out /System.err
However, there is a much better way if you're using Java EE and on a Java EE server. Server will schedule the job for you. All you need is an annotation.
import javax.ejb.Schedule;
import javax.ejb.Singleton;
#Singleton
public class ShedulerEjb {
/**
* This scheduler method runs at 0200 hours (system time)
*/
#SuppressWarnings("unused")
#Schedule(hour="2", minute="0", second="0")
private void doStuff(){
//Do your stuff
}
}
Underneath it uses operating system's timer services.
PS: If you don't make your bean singleton and at the scheduled time, there are more than one instances (say n) of your EJB bean, the scheduled method will be executed n number of times.
In my application I have one cron job which connects to a FTP server and transfer files, a very simple functionality and it is configured using spring #Schedule annotation with cron expression as a parameter.
It was running fine for few months and then suddenly it stopped, got the connectException.
May be the FTP server was down or something happened which causes the cron thread to stop.
I looked (google) for the reasons but didnt get any ( Nothing much in the logs also - Just the exception name ).It may be a one time thing :)
my question is that can I put some check or watcher on the #Schedule cron job to know whether it is running or not ?
Sorry for my bad explanation/english
Thanks
my question is that can I put some check or watcher on the #Schedule
cron job to know whether it is running or not ?
Basically, you can't.
When you use #Scheduled, Spring uses a ScheduledAnnotationBeanPostProcessor to register the tasks you specify (annotated methods). It registers them with a ScheduledTaskRegistrar. The ScheduledAnnotationBeanPostProcessor is an ApplicationListener<ContextRefreshEvent>. When it receives the ContextRefreshEvent from the ApplicationContext, it schedules the tasks registered in the ScheduledTaskRegistrar.
During this step, these tasks are scheduled with a TaskScheduler which typically wraps a ScheduledExecutorService. If an exception is uncaught in a submitted task, then the task is removed from the ScheduledExecutorService queue.
The TaskScheduler class does not provide a public API to retrieve the scheduled tasks, ie. the ScheduledFuture objects. So you can't use it to find out if your tasks are running or not.
And you probably shouldn't. Develop your tasks, your #Scheduled methods, to be able to withstand an exception being thrown. Some times, obviously, that's not possible. With a network error, for example, you would probably have to restart your application. Without knowing anything else about your application, I would say more logging is your best bet.
I am using camel 2.9.0 in my project. We have a number of routes divided into different camel contexts. Each camel context is bundled separately and deployed in Apache Karaf. Now the problem is divied into 2 parts:
1.) Each route is a scheduled route. Although using Quartz component, we are able to define a cron expressio in each route, we want a console where in we can trigger,stop any route and also put a cron expression to any route.(Scheduling a route through a web console is our main objective).
2.) Also we tried to configure the cron expression for each route through quartz.property. But if someone wants to change the cron expression at runtime in Apache Karaf, then we have to stop the bundle deployed and start in again. What can be done to change the value of cron expression at runtime.
Any replies and help would be appreciable.
Piyush
JMX provides remote context/route management support (start, stop, etc)
see these posts for more information:
http://www.consulting-notes.com/2010/08/managing-camel-routes-with-jmx-apis.html
http://www.consulting-notes.com/2011/01/apache-camel-monitoring.html
otherwise, to add/remove/alter routes at runtime, you'd need to get a handle to the CamelContext and leverage its APIs (addRoute(), removeRoute(), etc)
see these for more information:
Add camel route at runtime in Java
http://camel.apache.org/loading-routes-from-xml-files.html