I do create a timer which start when i deploy my application, what i note is this timer not stop when i Undeploy my application?
How can this happen, and show me the result in Output netbeans?
Should i restart my server every time that i Undeploy my
application?
Singleton
#Singleton
#Startup
public class StartWhenDeploy {
private static final int PERIOD = 3000;
#PostConstruct
public void init() {
System.out.println("I will set information to start my task");
Timer timer = new Timer();
timer.schedule(new TimerAction(1), new Date(), PERIOD);
}
}
TimerTask
public class TimerAction extends TimerTask {
public int nbrUsers;
public TimerAction(int nbrUsers) {
this.nbrUsers = nbrUsers;
}
#Override
public void run() {
System.out.println("This task is planified to execute at " + new Date());
System.out.println("Creation " + (createUser() ? "------------Success------------" : "------------Failed------------"));
}
public boolean createUser() {
try {
System.out.println("-------------->" + nbrUsers);
for (int i = 0; i < nbrUsers; i++) {
System.out.println("Create user >>>>" + i);
}
return true;
} catch (Exception e) {
System.out.println("Exception " + e);
return false;
}
}
}
It still show me the result like this in Output netbeans:
...
Infos: This task is planified to execute at Wed Nov 16 14:40:29 GMT+01:00 2016
Infos: -------------->1
Infos: Create user >>>>0
Infos: Creation ------------Success------------
...
Someone have an idea about this issue?
Thank you.
In GlassFish (in JavaEE in general), you should use the TimerService from the EJB specification for scheduling. I assume you are using java.util.Timer, which just runs in a separate thread. GlassFish does not know anything about the thread, so it cannot stop it with undeploy.
You should rewrite your Singleton to something like this:
#Singleton
#Startup
public class StartWhenDeploy {
private static final int PERIOD = 3000;
// Inject the TimerService into this EJB
#Resource
private TimerService timer;
private TimerAction action;
#PostConstruct
public void init() {
System.out.println("I will set information to start my task");
// the action object is created before the timer
action = new TimerAction(1);
timer.createTimer(new Date(), PERIOD, "My timer");
}
// this method will be executed when the timer fires - it needs to wrap your `TimerAction` created once per this singleton instance (`TimerAction` does not have to extend `TimerTask` now)
#Timeout
public void runTimerAction() {
action.run();
}
}
TimerTask spawns a new thread whose lifecycle is unaffected by undeploying your application.
A better way to do this would be to use a proper EJB timer with #Schedule like this example:
#Singleton
#Startup
public class SimpleTimerBean {
static Logger logger = Logger.getLogger(SimpleTimerBean.class.getCanonicalName());
#Schedule(hour = "*", minute = "*", second = "*/3", info = "Create user every 3 seconds", timezone = "UTC")
public boolean createUser() {
try {
System.out.println("-------------->" + nbrUsers);
for (int i = 0; i < nbrUsers; i++) {
System.out.println("Create user >>>>" + i);
}
return true;
} catch (Exception e) {
System.out.println("Exception " + e);
return false;
}
}
}
Related
I have a spring boot java service I have to schedule to run on a particular time. I have enabled the #Enablescheduling and #Scheduled annotation and given the cron expression.
It's working fine. The scheduler is running at the expected time. But my concern is I should control the cron expression somewhere from outside my jar file. I have tried using it in property file but when packaging my property file also getting included in that.
Sample code:
#PostMapping(path = "getoktatodynamodb")
#Scheduled(cron = "0 0/5 0 * * ?")
#ApiOperation("Sync data to DynamoDB")
public FinalResponse getdatatodynamodb() {
FinalResponse finalResponse = new FinalResponse();
try {
LOGGER.info("Sync data to DynamoDB starts - " + new Date());
finalResponse = dynamodbuserService.dynamoDbSync();
} catch (MyRestTemplateException ex) {
LOGGER.error(ex.getMessage());
finalResponse.setResponseMessage(ex.getMessage());
finalResponse.setStatusCode(ex.getStatusCode().value());
} catch (Exception execption) {
LOGGER.error(execption.getMessage());
finalResponse.setResponseMessage(execption.getMessage());
finalResponse.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
} finally {
LOGGER.info("Sync data DynamoDB Ends - " + new Date());
}
return finalResponse;
}
The main intention is scheduler should be in our control whenever we need to change the time it should be configurable. No code change and restarting the scheduler for minor changes.
How should we achieve this also we would like to schedule this in linux ec2 instance? in case if we have better suggestion to achieve this kindly share it.
You can implement SchedulingConfigurer:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/SchedulingConfigurer.html
This DZone article shows a really good example: https://dzone.com/articles/schedulers-in-java-and-spring which I'm showing here in case the article doesn't stay permanent.
#Configuration
#EnableScheduling
public class ScheduledConfiguration implements SchedulingConfigurer {
TaskScheduler taskScheduler;
private ScheduledFuture<?> job1;
private ScheduledFuture<?> job2;
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler =new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(10);// Set the pool of threads
threadPoolTaskScheduler.setThreadNamePrefix("scheduler-thread");
threadPoolTaskScheduler.initialize();
job1(threadPoolTaskScheduler);// Assign the job1 to the scheduler
// Assign the job1 to the scheduler
this.taskScheduler=threadPoolTaskScheduler;// this will be used in later part of the article during refreshing the cron expression dynamically
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
private void job1(TaskScheduler scheduler) {
job1 = scheduler.schedule(new Runnable() {
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + " The Task1 executed at " + new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, new Trigger() {
#Override
public Date nextExecutionTime(TriggerContext triggerContext) {
String cronExp = "0/5 * * * * ?";// Can be pulled from a db .
return new CronTrigger(cronExp).nextExecutionTime(triggerContext);
}
});
}
private void job2(TaskScheduler scheduler){
job2=scheduler.schedule(new Runnable(){
#Override
public void run() {
System.out.println(Thread.currentThread().getName()+" The Task2 executed at "+ new Date());
}
}, new Trigger(){
#Override
public Date nextExecutionTime(TriggerContext triggerContext) {
String cronExp="0/1 * * * * ?";//Can be pulled from a db . This will run every minute
return new CronTrigger(cronExp).nextExecutionTime(triggerContext);
}
});
}
}
This question already has answers here:
Stop a periodic task from within the task itself running in a ScheduledExecutorService
(5 answers)
Closed 5 years ago.
Note: This is toy code and not production ready.
I want to schedule MyTask to run every fixed delay (say 2 seconds for example). And this task when done wants itself to be stopped. The code for MyTask is:
public class MyTask implements Runnable {
MainClass parent;
AtomicInteger integer = new AtomicInteger(0);
public MyTask(MainClass parent) {
this.parent = parent;
}
#Override
public void run() {
try {
int valueNow = integer.incrementAndGet();
System.out.println("Running with value: " + valueNow + " and going to do work");
Thread.sleep((long)(Math.random() * 10000)); // simulate some work
System.out.println("Running with value: " + valueNow + " and work over");
if(valueNow == 5) {
parent.stopTask();
}
} catch (Exception exception) {
System.out.println("Interrupted");
}
}
}
And the MainClass is the one which schedules it:
public class MainClass {
private ScheduledExecutorService executorService;
private ScheduledFuture updateFuture;
public static void main(String[] args) {
new MainClass().startMyTask();
}
public void startMyTask() {
System.out.println("Starting MyTask to run every 2 seconds..............");
executorService = Executors.newScheduledThreadPool(2);
updateFuture = executorService.scheduleAtFixedRate(new MyTask(this), 1, 2, TimeUnit.SECONDS);
}
public void stopTask() {
System.out.println("Stopping MyTask to run further");
updateFuture.cancel(true);
}
}
This is just a toy code to reproduce the scenario. Is there anything wrong with this approach where I am passing a reference to the parent to the thread so that it can be stopped? Is there any better approach for this?
Well, what is 'wrong' is that you create a cyclic dependency between the two classes. It'll work but cyclic dependencies are generally undesirable.
But it's easy enough to break the cycle. Rather than passing parent itself, your task can accept a Runnable to run when it is done; basically a callback.
public class MyTask implements Runnable {
Runnable runOnDone;
AtomicInteger integer = new AtomicInteger(0);
public MyTask(Runnable runOnDone) {
this.runOnDone = runOnDone;
}
#Override
public void run() {
try {
int valueNow = integer.incrementAndGet();
System.out.println("Running with value: " + valueNow + " and going to do work");
Thread.sleep((long)(Math.random() * 10000)); // simulate some work
System.out.println("Running with value: " + valueNow + " and work over");
if(valueNow == 5) {
runOnDone.run();
}
} catch (Exception exception) {
System.out.println("Interrupted");
}
}
}
The task can then be instantiated like this : new MyTask(this::stopTask)
Alternatively you can throw an exception from your task, which will also end it being rescheduled. See this stackoverflow answer.
I'm looking to create a ScheduledThreadPoolExecutor with an unknown pool size. Pool size is determined at run-time, will likely be between 1-5, and for this example I used size 2. We use a custom Task that simply executes a method every so often, but that method will eventually throw an exception (which I've simulated with a simple numTimes variable and if statement). If an exception is thrown, I only want to cancel execution of THAT specific thread! If all threads are cancelled, I want to shut down the ScheduledThreadPoolExecutor. Once numTimes == 5 I simulate the exception to cancel the thread), and I can manage to cancel the thread a number of ways but they just don't feel right.
As a side note, I placed ScheduledFuture everywhere just to play around with cancelling it.
public class Test
{
static ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(2);
public static void main(String[] args)
{ stpe.scheduleWithFixedDelay(new UpdateTask(1), 0, 1000, TimeUnit.MILLISECONDS);
stpe.scheduleWithFixedDelay(new UpdateTask(2), 0, 5000, TimeUnit.MILLISECONDS);
// stpe.shutdown();
}
public static class UpdateTask implements Runnable
{
int id;
int numTimes = 0;
ScheduledFuture<?> t;
public UpdateTask(int id)
{ this.id = id;
}
public void run()
{ System.out.println("Hello " + id + " num: " + numTimes);
String fn = "C:\\lib" + id;
if (numTimes++ == 5)
{ File f = new File(fn);
f.mkdir();
t.cancel(false);
}
}
}
}
Calling t.cancel() from run() or from main() have the same effect, in that the thread stops executing but the program does not stop running. Naturally, this is because the ThreadPoolExecutor is still doing stuff, despite both threads no longer being scheduled.
I tried invoking shutdown on stpe, but it doesn't finish thread execution. Two directories are created with stpe.shutdown commented out, and they are not otherwise.
I can't figure out an elegant way to cancel ScheduledFuture, then ScheduledThreadPoolExecutor when all ScheduledFuture's are cancelled.
Final approach ##
I was not able to get s1.get() to work as described in the answer below, so I simply created my own class to handle it.
public class Test
{
static ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(2);
static CancelUpdateTasks canceller;
public static void main(String[] args)
{ Test t = new Test();
canceller.add(0, stpe.scheduleWithFixedDelay(new UpdateTask(0), 0, 1000, TimeUnit.MILLISECONDS));
canceller.add(1, stpe.scheduleWithFixedDelay(new UpdateTask(1), 0, 5000, TimeUnit.MILLISECONDS));
canceller.waitForSchedules();
stpe.shutdown();
}
public Test()
{ canceller = new CancelUpdateTasks();
}
public static class UpdateTask implements Runnable
{
int id;
int numTimes = 0;
public UpdateTask(int id)
{ this.id = id;
}
public void run()
{ System.out.println("Hello " + id + " num: " + numTimes);
if (numTimes++ == 5)
{ canceller.cancel(id);
}
}
}
public class CancelUpdateTasks
{ List<ScheduledFuture<?>> scheduler;
boolean isScheduled;
public CancelUpdateTasks()
{ scheduler = new ArrayList<ScheduledFuture<?>>();
isScheduled = false;
}
public void waitForSchedules()
{ int schedId = 0;
while(isScheduled)
{ ScheduledFuture<?> schedule = scheduler.get(schedId);
if (schedule.isCancelled())
{ if (schedId == scheduler.size() - 1)
return;
schedId++;
}
else
{ try
{ Thread.sleep(1000);
}
catch (InterruptedException e)
{ e.printStackTrace();
}
}
}
}
public void add(int id, ScheduledFuture<?> schedule)
{ scheduler.add(id, schedule);
if (!isScheduled)
isScheduled = true;
}
public void cancel(int id)
{ scheduler.get(id).cancel(false);
}
public void cancelNow(int id)
{ scheduler.get(id).cancel(true);
}
}
}
You'll want to issue a shutdown on the pool. The JVM will continue to run until there are only daemon threads alive. A ThreadPoolExecutor by default will create non-daemon threads.
Just invoke stpe.shutdown();
edit: Based on OPs update
shutdown admittedly is different for ScheduledThreadPoolExecugtor than a plain ThreadPoolExecutor. In this case shutdown prevents any scheduled task to become re scheduled. To make it work correctly you will have to wait on the futures completion. You can do so by get()ing on the ScheduledFuture
ScheduledFuture sf1 = stpe.scheduleWithFixedDelay(new UpdateTask(1), 0, 1000, TimeUnit.MILLISECONDS);
ScheduledFuture sf2 = stpe.scheduleWithFixedDelay(new UpdateTask(2), 0, 5000, TimeUnit.MILLISECONDS);
sf1.get();
sf2.get();
stpe.shutdown();
In this case both tasks are run asynchronously, the main thread will first wait for sf1 to complete then will wait for sf2 to complete and finally shutdown.
I'm new to the #Schedule annotations in J2EE6
I want to run a job using EJB 3.x with Glassfish 3.1.
The javax.ejb.Schedule seems to be a good choice for us, so we could think of our custom time as something like:
#Singleton
public class CustomTimer {
#EJB
SettingsFacade settingsFacade;
#Schedule(second="someSecondParameter", minute="someMinuteParameter",hour="someHourParameter", persistent=false)
public void executeTimer(){
//Code executing something against database using the settingsFacade
}
}
Here, we want the parameters to be got from database, so they are changed every month. Any clean solution for this?
#Singleton
#Startup
public class ScheduleTimerService {
#Resource private TimerService timerService;
public void setTimerService(TimerService timerService) {this.timerService = timerService; }
#PostConstruct
private void postConstruct() {
timerService.createCalendarTimer(createSchedule());
}
#Timeout
public void timerTimeout(Timer timer) {
Add your code here to be called when scheduling is reached...
in this example: 01h:30m every day ;-)
}
private ScheduleExpression createSchedule(){
ScheduleExpression expression = new ScheduleExpression();
expression.dayOfWeek("Sun,Mon,Tue,Wed,Thu,Fri,Sat");
expression.hour("01");
expression.minute("30");
return expression;
}
}
No, there is no solution with #Schedule, because annotation attributes in general should be compile time constants.
When more flexibility is needed, programmatic timers can be used.
Also then polling database for changed configuration and removing existing and creating new timers must be implemented.
Well You need to created Two Scheduler
One Scheduler will run to update data from Database
Based On that You Can created Other Scheduler.
But for this Need to do it some what programmatic.
You also can see EJB Timers for the same what will help you in this case. which is also annotation based.
There is a simple way of doing this. I wanted to something that called a process every day but, the job itself should be done randomly over the same day. I managed to do that by adding a simple thread worker to run after the EJB timer service has been called. Then I would put it to sleep for a random amount of time during that day.
The following code is an example of a service that wakes up every 1 minute and waits for a thread to finish.
#Schedule(minute = "*/1", hour = "*", persistent = false)
public void runEveryMinute() throws InterruptedException {
log.log(Level.INFO, "Scheduling for every minute .. now it's: " + new Date().toString());
// Delay, in milliseconds before we interrupt adding a follower thread
//we can therefore garantee that it runs every day
long patience = 1000 * 5;
threadMessage("Starting forever alone no more thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for new thread to finish");
// loop until MessageLoop thread exits
while (t.isAlive()) {
threadMessage("Still waiting...");
// Wait maximum of 1 second for MessageLoop thread to finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t.isAlive()) {
threadMessage("Tired of waiting! Adding new followers now!");
t.interrupt();
// Shouldn't be long now -- wait indefinitely
t.join();
}
}
threadMessage("Finally! You are not alone anymore!");
}
// Display a message, preceded by
// the name of the current thread
static void threadMessage(String message) {
String threadName = Thread.currentThread().getName();
System.out.format("%s: %s%n", threadName, message);
}
private static class MessageLoop implements Runnable {
public void run() {
String importantInfo[] = {
"A kid will eat ivy too"
};
try {
for (int i = 0;
i < importantInfo.length;
i++) {
// Pause for 4 seconds
int max = 10;
int min = 2;
int randomTimer = 0 + (int) (Math.random() * ((max - min) + 1));
Thread.sleep(randomTimer * 1000);
// Print a message
threadMessage(importantInfo[i]);
}
} catch (InterruptedException e) {
threadMessage("Patience is not a virtue! Thread stopping for now!");
}
}
}
Hi every one i am having an issue with timer service, on timeout it perform some business logic if there is any exception in business logic. which is catched in one of interceptor as well as in timer service. then timer service is not canceled. timer.cancel();
So how it works my timer service get exectued on timeout, it calls an ejb function, this ejb has an interceptor associated with it. if ejb function has any exception. Interceptor is basically logging that exception. then i have a code which stops the timer, it should work in case of success or failure, but it only stop timer in case of success. in case of failure(when exception occurs) it does not cancel the timer. so every time i restart jboss it try to excute the timer again (as it was failed).
My Question is how can i stop timer in case of success and failure(exception). Please note i am using Interceptor as well (Which i can not remove, while removing it fixes the issue).
Here is my different code classes which may help in understanding the issue.
Business Logic Bean
#Stateless
#Local(UtilityLocal.class)
#Interceptors({ ExceptionInterceptor.class })
public class UtilityEJB implements UtilityLocal {
public void doDomeThing(MazTimerTask task) {
System.out.println("--- Business logic ---");
Integer x = 5/0; // this will generate an exception
System.out.println("--- Business logic ---");
}
}
Interceptor
public class ExceptionInterceptor {
#Resource
private javax.ejb.SessionContext ctx;
#AroundInvoke
public Object aroundInvoke(final InvocationContext invocationContext)
throws Exception { //NOPMD
try {
return invocationContext.proceed();
}
catch (Exception exception) {
System.out.println(" Logg the exception here");
throw exception;
}
}
}
Timer Service
#Stateless
public class MazTimer implements MazTimerLocal, MazTimerRemote{
#EJB
private transient UtilityLocal ejb;
#Resource
private transient TimerService timerService;
#Timeout
#TransactionTimeout(3600)
public void handleTimeout(Timer timer) {
MazTimerTask task = (MazTimerTask) timer.getInfo();
if (task != null ) {
try{
ejb.doDomeThing(task);
}catch(Exception e) {
System.out.println("------------ Exception occured : " + task.getName());
}
finally {
stopTimer(task);
}
}
}
public void startTimer(MazTimerTask task) {
timerService.createTimer(new Date(), 10, task);
}
private void stopTimer(MazTimerTask task) {
try {
Timer timer = getTimer(task);
if (timer != null) {
timer.cancel();
System.out.println("------------ Timer stopped : " + task.getName());
}
} catch (RuntimeException e) {
}
}
private Timer getTimer(Serializable timerId) {
Timer timer = null;
if (timerId != null) {
Iterator<Timer> it = timerService.getTimers().iterator();
while (it.hasNext()) {
Timer currentTimer = it.next();
if (currentTimer.getInfo().equals(timerId)) {
timer = currentTimer;
break;
}
}
}
return timer;
}
}