Categories
Java Tomcat

Solution to “Tomcat can’t stop [Abandoned connection cleanup thread]”

I am preparing a web service for one of my larger projects, using Tomcat, Hibernate and MySQL. While developing I stumbled across several Tomcat error messages that suggest some threads could not be stopped. Most of the threads could simply be vanished by calling Hibernate’s SessionFactory.close() method. However, a few threads seem to remain, e.g.

Jul 09, 2014 10:55:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/examples] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to 
unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Jul 09, 2014 10:55:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/examples] appears to have started a thread named [Abandoned connection cleanup 
thread] but has failed to stop it. This is very likely to create a memory leak.

and in fact, Tomcat stopped working after a few redeployments due to memory problems. Two main reasons:

  1. The MySQL AbandonedConnectionCleanupThread does not shutdown correctly.
  2. The MySQL J/Connector driver doesn’t unregister anymore from the DriverManager.

At least with J/Connector V5.1.31 the problem disappears by using this shutdown procedure (hooked in by a ServletContextListener):

1
2
3
4
5
6
7
8
9
10
11
12
13
   try {
      com.mysql.jdbc.AbandonedConnectionCleanupThread.shutdown();
   } catch (Throwable t) {}
   // This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks
   Enumeration<java .sql.Driver> drivers = java.sql.DriverManager.getDrivers();
   while (drivers.hasMoreElements()) {
      java.sql.Driver driver = drivers.nextElement();
      try {
         java.sql.DriverManager.deregisterDriver(driver);
      } catch (Throwable t) {}
   }
   try { Thread.sleep(2000L); } catch (Exception e) {}
</java>

I still have to observe long-term effects and will keep you informed.

Categories
Java Tomcat

Undocumented Java WebStart Features

Many of you might use Oracle’s JNLP Download Servlet, delivered with JDK in jnlp-servlet.jar. One of the nice features of this servlet is the automatic replacement of variables at runtime, e.g. codebase and context. However, the existing documentation does not reveal all of these replacements. While searching for a solution where I need to put the server name into the JNLP file, I also examined the source code of JnlpDownloadServlet. And voilá: the feature is already there but not documented.

Here is the complete list of replacements that the servlet does for you while delivering a JNLP:

  • $$name: will be replaced by the name of the URL file requested (without path, e.g. myfile.jnlp)
  • $$hostname: will be replaced by the servername as given in the HTTP(S) request
  • $$codebase: will be replaced by the codebase (request without URL file: http://my.server/appname/somedir/)
  • $$site: will be replaced by the protocol, server and port, e.g. http://my.server:8080

I hope you’ll find that useful next time you look for a solution to deliver WAR files to individual servers with the specific servername in its JNLP file.

Categories
Java Tomcat

Enable Browser Caching for Tomcat’s Deliveries

Tomcat automatically adds “no-cache” directives to each response. This is not a good idea when you are not using Apache as the serving host for static content. I found a very easy way to get rid of that HTTP header. Just add a new file named “context.xml” to the WEB-INF directory of your application:

1
2
3
4
<context>
	<valve className="org.apache.catalina.authenticator.BasicAuthenticator"  
		disableProxyCaching="false" />
</context>

For finer control, please have a look at Symphonious’ article on that topic.