0

I've a spring web app running in a Tomcat server. In this there is a piece of code,in one of the Spring beans, which waits for a database connection to become available. My scenario is that while waiting for a database connection, if the Tomcat is shutdown, I should stop waiting for a DB connection and break the loop.

private Connection prepareDBConnectionForBootStrapping() { Connection connection = null; while (connection == null && !Thread.currentThread().isInterrupted()) { try { connection = getConnection(); break; } catch (MetadataServerException me) { try { if (!Thread.currentThread().isInterrupted()) { Thread.sleep(TimeUnit.MINUTES.toMillis(1)); } else { break; } } catch (InterruptedException ie) { logger.error("Thread {} got interrupted while wating for the database to become available.", Thread.currentThread().getName()); break; } } } return connection; } 

The above piece of code is executed by one of the Tomcat's thread and it's not getting interrupted when shutdown is invoked. I also tried to achieve my scenario by using spring-bean's destroy method, but to my surprise the destroy method was never called. My assumption is that Spring application context is not getting fully constructed - since, I've the above waiting loop in the Spring bean - and when shutdown is invoked corresponding context close is not getting invoked.

Any suggestions?

4
  • so are you saying that the JVM that Tomcat is running does not get shutdown? Commented May 27, 2016 at 5:21
  • @ScaryWombat Yes, indeed that is what is happening when I shutdown the Tomcat service. Commented May 27, 2016 at 5:31
  • Is this scenario real? If Tomcat is being shutdown, why would a bean be asking for a connection? And why wouldn't a connection be available immediately on demand? And if not, how come getConnection() isn't just blocking until there is one? Commented May 27, 2016 at 5:44
  • @EJP, Our web-app needs to wait for the db connection to become available- services could be started in any order. And while waiting, if someone shutsdown the web-app, then it should shutdown gracefully. Commented May 27, 2016 at 5:51

1 Answer 1

2

Tomcat defines a life-cycle for Web applications (well, it's a kind of common specification aspect and not just tomcat specific, but anyway...)

So there is a way to hook into this process and terminate the loop or whatever.

In spring its very easy, because if tomcat shuts down gracefully, tomcat attempts to "undeploy" the WAR before actually exiting the process. In servlet specification in order to do that, a special web listener can be defined and invoked (you can see javax.servlet.ServletContextListener API for more information)

Now spring actually implements such a listener and once invoked, it just closes the application context. Once this happens, your @PreDestroy methods will be called automatically. This is already a spring stuff, tomcat has nothing to do with that.

So bottom line, specify @PreDestroy method on your bean that would set some flag or something and it would close the logic that attempts to close the connection.

Of course all the stated above doesn't really work if you just kill -9 <tomcat's pid> But in this case the whole jvm stops so the bean is irrelevant.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. We already have all that in place, and as I mentioned in the question Spring way of achieving the functionality didn't work for us.
Do you mean, a method marked with @PreDestroy is not invoked at all on the bean?
Yes. That could be due to the reason that context itself was never fully constructed -my assumtion. As I mentioned, the waiting logic is actually in Spring bean.
Well, its a kind of weird usage of spring then... Spring context has to be constructed in order to operate properly. As for what you describe, there are 2 possible reasons for that. 1. annotation configuration is not allowed (if you configure spring for xml or something), in this case just use 'destroy method' in bean definition. 2. the application is stuck in the wait call. If so, spawn a thread that would handle the blocking call and don't interfere with the spring startup lifecycle logic. Again, in order to get a fully operational spring driven webapp, the context has to be initialized.
That is exactly our use case is. We can't allow our database bean to be available until db connection is made because there is some intilization logic that required db connection. BTW, we do have annotation config enabled and I tried the XML way as well.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.