1

I am developing a Java web application using Spring.

What I would like to do is that after the user gets to a page, the code starts running a function every 10 seconds, keeping track on the time the last action was performed.

I tried to do so with a Scheduler but it starts running immediately - and not only after the user gets to a page.

@Scheduled(fixedRate = 60000)
public void run(String param) {
    //just an example of action to be performed repeatedly
    System.out.println("Previously performed action was " + new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(previousActionTime)) + " with " + param);
    //update previousActionTime
    previousActionTime.setSeconds(previousActionTime.getSeconds() + 10);
}

Moreover I don't know what it is a convenient way to store the time when the last action automated action was performed.

The scheduler should be somehow activated when browsing to the page:

@RequestMapping(value = "/hellopage", method = { RequestMethod.POST, RequestMethod.GET })
public String hellopage(HttpServletRequest request, HttpServletResponse response) {
        // Activate scheduler
        run(request.getParameter("param1"))
        ...
}

The scheduler (or whatever performs the automated actions) should stop as soon as the user gets again to the same web page triggering the automated actions and should run in background not blocking any other code from execution (to be precise, I cannot simply put a while loop with Sys.sleep in the function mapped to the page URL request why the page should do other things)

Any help?

Mario
  • 137
  • 1
  • 10
  • 1
    What are you exactly planning with these automated actions? Seems to me like you should let the scheduler part run in your web app. Could be a piece of javascript that sends a trigger to the server every 10 seconds. If you run it with the scheduler, how would you detect if the user is still on the page and avoid an infinite running scheduler? – Yoni Mar 01 '21 at 09:27
  • The action that the scheduler needs to perform is a SQL query to get some data from a database and send it to my Java program to perform some calculations. How to avoid an infinite runnign scheduler - don't know unfortunately. – Mario Mar 01 '21 at 09:32

2 Answers2

0

Consider using ScheduledExecutorService.scheduleAtFixedRate for this as the Spring scheduler are independent of any users' request (which you have already observed and noted in question).

You may use shutdownNow to terminate the scheduler once the users' session is no longer valid / a new request is received. To achieve this you could maintain cache of previous executor(s) with user id (or any relevant information) to identify the instance which should be invalidated.

As an alternative you could use Timer and TimerTask if more fine grained control is required (however not recommended as noted here)

Bond - Java Bond
  • 3,972
  • 6
  • 36
  • 59
0

There are two common ways of achieving this.

The first is to run your timer client-side, in JavaScript, and then runs an AJAX/websocket/whatever call. This has many advantages - once the user navigates away from your site, the timer will stop, and you're not tying up server-side resources so your application will scale much more cleanly. This is by far the cleanest solution if your timer is linked to a single user.

The second is to use a message queue; pop a message on the queue and have an asynchronous process checking those messages, ideally aggregating multiple client sessions in a single database request. You need to figure out how to detect sessions timing out and remove the message from the message queue. This approach is best when your timer is looking at information that's not tightly connected to the current user.

Neville Kuyt
  • 29,247
  • 1
  • 37
  • 52