0

we are facing an issue with initializing our cache at server startup or application deployment. Initializing the cache involves

  1. Querying a database to get the list of items
  2. Making an rmi call for each item
  3. Listening to the data on a JMS queue/topic
  4. Constructing the cache

This initialization process is in startup code. All this is taking lot of time due to which the deployment is taking lot of time or server start time is increasing.

So what I proposed is to create a thread in the startup and run the initialization code in it. I wrote a sample application to demonstrate it.

It involves a ServletContextListener, a filter. In the listener I am creating a new thread in which the HeavyProcess will run. When it finishes an event will be fired which the filter will be listening. On receiving the event the filter will allow incoming http requests. Until then the filter redirects all clients to a default page which shows a message that the application is initializing.

I presented this approach and few concerns were raised.

  1. We should not ideally create a thread because handling the thread will be difficult.

My question is why cant we create a thread like these in web applications.

If this is not good, then what is the best approach?

Krishna Chaitanya
  • 2,533
  • 4
  • 40
  • 74
  • Please clarify: A solution for *servlet container only* or *EJBs allowed*? Which application server (including version)? – Beryllium Aug 29 '13 at 15:11
  • We are using EJB 3.0 and Glassfish 3.1.2.2 application server. We are USING @Startup annotation till now which delayed the deployment. I gave the solution described above using servlet api. – Krishna Chaitanya Aug 29 '13 at 17:42

2 Answers2

0

In general, creating unmanaged threads in a Java EE environment is a bad idea. You will loose container managed transactions, user context and many more Java EE concepts within your unmanaged thread. Additionally unmanaged threads may block the conainer on shutdown if your thread handling isn't appropriate.

Which Java EE Version are you using? Perhaps you can use Servlet 3.0's async feature?

Or call a asynchronous EJB for doing the heavy stuff at startup (@PostConstruct). The call will then set a flag when its job is done.

roehrijn
  • 1,387
  • 1
  • 11
  • 20
  • Why creating unmanaged threads is a bad idea? One of my senior college also said the same but dint justify his answer. I want to know. We are using Java EE 6. I will read about asynchronous EJB and check how it fits in our problem. Thank you. – Krishna Chaitanya Aug 29 '13 at 17:47
  • Have a look at the answer again. I amended an explaination why unmanaged threads are bad. – roehrijn Aug 31 '13 at 21:40
0

If you can use managed threads, avoid unmanaged ones. The container has no control over unmanaged threads, and unmanaged threads survive redeployments, if you do not terminate these properly. So you have to register unmanaged threads, and terminate these somehow (which is not easy as well, because you have to handle race-conditions carefully).


So one solution is to use @Startup, and something like this:

@Schedule(second = "*/45", minute = "*", hour = "*")
protected void asyncInit(final Timer timer) {
    timer.cancel();

    // Do init here

    // Set flag that init has been completed
}

I have learned about this method here: Executing task after deployment of Java EE application

So this gives you an async managed thread, and deployment will not be delayed by @PostConstruct. Note the timer.cancel().


Looking at your actual problem: I suggest using a cache which supports "warm starts".

For example, Infinispan supports cache stores so that the cache content survives restarts. If you have a cluster, there are distributed or replicated caching modes as well.

JBoss 7 embeds Infinispan (it's an integrated service in the same JVM), but it can be operated independently as well.

Another candidate is Redis (and any other key/value store with persistence will do as well).

Community
  • 1
  • 1
Beryllium
  • 12,808
  • 10
  • 56
  • 86
  • Hi thanks for helping. Basically I used a stateless ejb and annotated it with `@Startup`, one of the method with `@Schedule`. After the initialization completed I am firing an event which a Filter listens to and sets a flag allowing the requests to proceed. Its working now. – Krishna Chaitanya Sep 02 '13 at 09:17