0

I have a Spring 3.0 WebMVC application running on Tomcat 7. On application startup I kick off a background thread to load an in-memory cache with records from a DB. This thread typically takes over an hour to load all the data from the DB. In the same application I have a @Controller annotated class which exposes a REST interface by which clients can get objects from the loaded cache.

One of our requirements is that any REST requests that are made prior to the data load being finished will return a SERVICE_UNAVAILABLE (503) HTTP code to the client immediately. To accomplish this I set up a simple check of a boolean flag that each request method in the controller makes before doing any work. If the value is false the method should return immediately with a 503 code. The loader thread will set the flag to true once it is completed with the load to allow the request methods to function normally.

The problem is that the background thread seems to be causing all HTTP requests sent to my controller to timeout after 30 seconds instead of hitting the flag and returning a 503 code immediately to the client. I'm not an expert in Tomcat threading issues and I wonder if I'm doing something wrong when creating my long running background thread? I am basically using the "implements Runnable" method to create the thread as described in this question and starting the thread on the containing bean initialization. Is there a better way to kick off a long running background thread inside Tomcat that doesn't interfere with the request handling? Or is there something else that I'm missing?

Community
  • 1
  • 1
Tom
  • 3,006
  • 6
  • 33
  • 54
  • How are you synchronizing access to the boolean flag? – David Schwartz Jun 29 '13 at 04:39
  • @DavidSchwartz The flag is a value in the in-memory cache that the request method checks via a cache DAO object. The loader thread simply updates this cache value when it is completed via the same cache DAO object which I believe is thread safe (not 100% sure); it doesn't access it prior to the load being finished so I wouldn't think it is an issue? – Tom Jun 29 '13 at 04:44
  • instead of polluting every single service, wouldn't it be easier and better maintainable to just implement a filter? Granted, this wouldn't solve the problem you ask about, but might simplify the issue to a single place of interaction. – Olaf Kock Jun 30 '13 at 10:16

1 Answers1

0

If I were you, I would do few things differently:

  1. See if you want to use a external cache. In the past, I had some success with using Project Voldemort (http://www.project-voldemort.com/voldemort/), there are other alternatives.
  2. If you externalize your cache, then, restart of Tomcat will not require reloading of cache.
  3. Build a separate application whose job is to load the cache.
  4. See if you want to process the request, if the entry you are looking for is not available in cache, by directly looking it from DB.
  5. Do not use your own Threads in application containers like Tomcat. Tomcat has its own thread management logic built into it, and creating a user threads is a BIG-NO.
Wand Maker
  • 18,476
  • 8
  • 53
  • 87
  • I'm curious if you have a reference to back up your claim in #5...that user threads are not a good idea to create inside of a web app running in Tomcat? – Tom Jun 29 '13 at 22:42
  • I remember reading it Rod Johnson's book, unfortunately I am not able to trace it. Also, I have seen practically in our projects where threads started as part of request processing have brought systems to halt in production. I found this link where this topic is discussed: http://stackoverflow.com/questions/533783/why-spawning-threads-in-java-ee-container-is-discouraged – Wand Maker Jun 30 '13 at 03:34