1

My web app needs to allow users at different locations to possibly schedule one data import job per location. Each job may take a long time to complete. There can be multiple users at a location who may simultaneously schedule the job (using different schedules), in which case, the schedule last submitted wins out. Schedules can be canceled and modified at any time. Also, new locations (and their schedules) may be added at any time. I'm using JDK 1.6 and raw servlets.

My plan below seems full of red flags given thread safety issues and the dependence on servlet state.

Plan:

  1. Use ScheduledExecutorService to schedule jobs in the init() method of a servlet. A ServletContextListener is the generally recommended place to schedule a job, but given that an HttpRequest may arrive to change the schedule of a existing job, it seems like I need to:

  2. Track the scheduled job threads in the servlet using a member variable map<location, ScheduledFuture<?>>. I know that keeping state in a servlet is considered BAD, but in my case, it seems needed so that I can:

  3. Cancel a scheduled job thread and reschedule it when requested by the user by using the known location as a key to the map above. This part seems to require synchronized blocks but the block should execute quickly and simultaneous access should be limited to a handful of users. Does this seem like a valid use case for using synchronization?

Is it okay to manage scheduled jobs with Servlet state? What holes do you see in my plan and what would be better way to do what I want?

Thanks!

rimsky
  • 1,163
  • 3
  • 16
  • 27

1 Answers1

1

Instead of doing the work in the servlet, do it in an offline process (program that is not part of the web-app) instead. Have the servlet simply act as the triggering mechanism for the offline process. There are multiple ways to accomplish how the triggering process is done (file transfer, shared database, messaging or remote procedure invocation). See enterprise integration patterns as a starting point.

The benefits of having the processing in an offline program are you don't need to manage state in the servlet and it leads to more modular code.

Edit: edited for clarity.

Monica Granbois
  • 6,632
  • 1
  • 17
  • 17
  • I've used something similar. Add info. to DB -> crontab fires -> python code checks DB, processes and updates DB if required. -> next request to web app shows changes.. Also: I have never seen servlets used in a non-transaction based context. – Ross Jun 18 '15 at 05:26
  • @Ross and user4704303, Thanks for the ideas. A database sounds simplest (since I'm already using it), but this sounds like a polling solution rather than a push, which isn't necessarily bad for my needs. But, it seems like the scheduler isn't being used the way I understand it to be intended -- to schedule recurring jobs. Instead, it schedules a job to check to see if a new job should start. I guess the remote procedure would be a push but not sure I want to set that up. – rimsky Jun 18 '15 at 16:47
  • I was going to write an answer but simply don't have enough knowledge to give one of sufficient quality where I am completely confident. What I can say is I do think it's valid for synchronization because a servlet is multi-threaded and that variable is going to change. I don't think you need to use the init() method in a servlet. Maybe once you define ScheduledExecutorService (see this : stackoverflow.com/q/4691132/539394 for more) with the help of the ServletContextListener you can access it using the getServletConfig() method in the servlet? eliminating the need for a servlet variable. – Ross Jun 19 '15 at 02:58
  • Also.. what happens with exceptions: http://code.nomad-labs.com/2011/12/09/mother-fk-the-scheduledexecutorservice/ – Ross Jun 19 '15 at 03:06