Skip to content
accelerando

Tag Archives: Tomcat

Fixing hibernate “Cannot release connection” exception using DBCP and MySQL.

21-Nov-11

Every 8 hours i got a Hibernate exception “Cannot release connection” within a Java application using Hibernate, Apache DBCP on Tomcat:

org.hibernate.exception.GenericJDBCException: Cannot release connection
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
    ..
    ..
Caused by: java.sql.SQLException: Already closed.

Not only that the messages polluted my inbox, the exception was visible to the enduser, resulting in a HTTP 500 error. An older blog post i found suggested dismissing DBCP and using c3p0, a solution that i’m not quite found of. At least, the post helped to reproduce the problem within my development setup. The underlying problem was indeed the MySQL wait_timeout.

There’s quite a long documentation on the Tomcat JDBC Connection Pool. Although the Tomcat team recommends their own solution since Tomcat 7, i still wanted to go with DBCP.

The relevant keywords are “testOnBorrow”, “testOnReturn”, “testWhileIdle”, “validationQuery” and “timeBetweenEvictionRunsMillis”. The first 3 are boolean values. If set to true, the query given as validationQuery is executed on borrowing a connection from the pool, on returning or when idling. The first option is not an option on production use as the query is executed before each call. Although “Select 1″ is probably very fast, i just don’t want to have. Also: The problem is an invalidated, idle connection so i set testWhileIdle to true. And what happened? Nothing! The problem stayed. So there is the last option timeBetweenEvictionRunsMillis which should, according to the docs, default to 5 seconds but it doesn’t. The documentation is wrong. It’s under zero, so the eviction thread that tests idle connections never run. I’ve tweeted the tomcat team, but there was no reaction.

So the correct configuration for a DBCP pool database source is:

<Resource
	type="javax.sql.DataSource"
	driverClassName="com.mysql.jdbc.Driver"
	maxActive="100"
	maxIdle="30"
	maxWait="10000"
	testOnBorrow="false"
	testOnReturn="false"
	testWhileIdle="true"
	validationQuery="Select 1"
	timeBetweenEvictionRunsMillis="1800000"
/>

This way the eviction thread runs every 30 minutes, testing idle connections with the query “Select 1″ and removing them from the pool. The timeBetweenEvictionRunsMillis should not be to low. It should be adapted to the configured MySQL wait_timeout.

Apache httpd, Tomcat und sendfile

28-Jun-11

I used to use mod_xsendfile by Nils Maier, who’s Homepage doesn’t seem to exist anymore, to send files from Ruby proxied by Apache respectively powered by modrails. Those files shouldn’t be in any public www directory as authorization needs to be checked, but are accessed very often so that streaming them is not an option.

To use this technique you need mod_xsendfile, which is attached to this post.

I just have rewritten my application from Ruby on Rails to Java and it’s easy to add the necessary headers in a HttpServletResponse:

response.setHeader("X-Sendfile", file.getAbsolutePath());
response.flushBuffer();

You may add other headers like Content-Type and the like but you must not modify the body, hence the flushBuffer.

This works quite well… As long as had my Apache httpd running with mpm-prefork.

Switching to Apache mpm-worker caused some problems. I cannot say with a final conclusion that mod_xsendfile was causing troubles but i started to see the wrong files (images in this case) delivered or not delivered at all.

My alternate solution was streaming the files using Channels from java.nio but CPU usage went nuts.

The solution now employed is the using Apache Tomcats asynchronous writes that are available since Tomcat 6. Their documentation is rather short but so is implementing them:

/*
HttpServletRequest request = ...
HttpServletResponse response = ...
*/
 
if(request != null && Boolean.TRUE.equals(request.getAttribute("org.apache.tomcat.sendfile.support"))) {		
  long l = file.length();
  request.setAttribute("org.apache.tomcat.sendfile.filename", absolutePath);
  request.setAttribute("org.apache.tomcat.sendfile.start", 0l);
  request.setAttribute("org.apache.tomcat.sendfile.end", l);
  response.setHeader("Content-Length", Long.toString(l));
  response.flushBuffer();
} else if(use_xsendfile) {
  // see above
} else {
  // stream files
}

What i got wrong at first was setting those attributes in the response. That didn’t work. The must be set in the request and you must take care setting all of those and with the correct type (String respectively long). And that’s it.

The request attribute org.apache.tomcat.sendfile.support will be true when the connector is configured to either use the APR connector (org.apache.coyote.http11.Http11AprProtocol) or the non blocking Java connector (org.apache.coyote.http11.Http11NioProtocol) (the later one being easier to deploy as it has no external dependencies).

CPU usage for sending those files is now nearly 0.

Disable jsessionid path parameter in Java web applications

28-Jan-11

Wow, this has driven me nuts…

Most J2EE developers will know the ugly-as-hell ;jsessionid=BLAHBLAHBLAH appended as a path parameter to all urls of an application on the first call of a page that creates a session.

Tomcat as of version 6 has the possibility to add the attribute ‘disableURLRewriting=”true”‘ to the context of the application but that didn’t work for me…

The problem was: I’m using Spring Security and Spring Security has it’s own mechanism and control for the session store.

It can be disabled through security-conf.xml (or wherever you’ve stored the Spring Security configuration) within the http element:

<http use-expressions="true" disable-url-rewriting="true" create-session="ifRequired">

And boom, the path parameter is gone.

For more information see The Security Namespace

The jsession parameter is used on the first page that requires a session as the server cannot now at this point in time whether the client supports cookies or not. If you disable it, you’re clients need to allow cookies, otherwise no session will be created.

Different day, same shit, today: Java 5 on Oracle Enterprise Linux 5

19-Jan-09

Worlds collide: Oracle and Sun JDK. Perfect start to ruin a not so bad Monday morning.

Background: Need to have a Tomcat Server deployed on a Oracle Enterprise Linux 5 system.

I was happy, when i saw a tomcat5 package in the repositories. Great, i thought. All i need. Well. Not.

Under Windows you’ll get between one and ten JVM versions installed with on Oracle product (slight exaggerated), within the OEL5 there was only one ancient 1.4.2 JDK. *sigh* Did i mention that the application that is supposed to run on that thing uses a buttload of Java 5 features?

“yum search java-“… No Java 5. WtF?

There is no Java 5.

Again, do it yourself:

This is a nice entry that describes howto build rpms for the “official” Sun Java 5 jdk.

I used the following steps to build my rpms:

  • Downloaded this rpm
  • Downloaded jdk-1_5_0_15-linux-i586.bin from the Sun JDK archive page
  • Put the later one into /usr/src/redhat/SOURCES/
  • Built the rpms with rpmbuild –rebuild java-1.5.0-sun-1.5.0.15-1jpp.nosrc.rpm. If rpmbuild is not installed, it’s hidden in the package rpm-build, not rpmbuild.
  • Installed missing libXp
  • Installed the rpms:
    rpm -Uvh /usr/src/redhat/RPMS/i586/java-1.5.0-sun-1.5.0.15-1jpp.i586.rpm
    rpm -Uvh /usr/src/redhat/RPMS/i586/java-1.5.0-sun-devel-1.5.0.15-1jpp.i586.rpm
    rpm -Uvh /usr/src/redhat/RPMS/i586/java-1.5.0-sun-src-1.5.0.15-1jpp.i586.rpm
    rpm -Uvh /usr/src/redhat/RPMS/i586/java-1.5.0-sun-demo-1.5.0.15-1jpp.i586.rpm
    rpm -Uvh /usr/src/redhat/RPMS/i586/java-1.5.0-sun-plugin-1.5.0.15-1jpp.i586.rpm
    rpm -Uvh /usr/src/redhat/RPMS/i586/java-1.5.0-sun-fonts-1.5.0.15-1jpp.i586.rpm
    rpm -Uvh /usr/src/redhat/RPMS/i586/java-1.5.0-sun-alsa-1.5.0.15-1jpp.i586.rpm
    rpm -Uvh /usr/src/redhat/RPMS/i586/java-1.5.0-sun-jdbc-1.5.0.15-1jpp.i586.rpm
  • Last step: Choose the right java version with alternatives –config java

After that, everything could be fine. Well, it wasn’t:

sun.misc.InvalidJarIndexException: Invalid index

Jehova! Finally not a NPE but something new, at least to me. Sometimes i wonder why i always run into bugs like these.

Some script changes and repackages all jar files in some weird ways so that a standard JDK has funny problems.

My solution to it: Reindex everything in /usr/share/java after you’ve chosen your newly installed java with the following command:

find /usr/share/java/ -iname "jakarta*commons*.jar" -exec jar -i {} \;

I opted to reindex only the jakarta commons files, that got Tomcat up and running with Java 5.

One last note: The /usr/bin/dtomcat5 is broken imho, at least when run from /etc/init.d/tomcat5. In ignores /etc/tomcat5/tomcat5.conf and therefore cannot stop Tomcat.

My solution: Replace

if [ -z "$CATALINA_HOME" ]; then
    TOMCAT_CFG="/etc/tomcat5/tomcat5.conf"
fi

(in line 55 on my setup) with

if [ -z "$CATALINA_HOME" ]; then
    TOMCAT_CFG="/etc/tomcat5/tomcat5.conf"
    [ -r "$TOMCAT_CFG" ] && . "${TOMCAT_CFG}"
fi

and remove

if [ -z "$CATALINA_HOME" ]; then
    [ -r "$TOMCAT_CFG" ] && . "${TOMCAT_CFG}"
fi

(in line 105 on my setup).

I wonder why simple things like these always are a pain in the ass. Stupid nuisances that keeps people from getting their work done. *sigh* Not a good start for the week.

Kaputte UTF-8 Daten im Servlet

05-Oct-06

Beruflich habe ich gerade mit einer Webanwendung zu tun, die mit Spring realisiert ist. Spring macht ähnlich viel Spaß wie Ruby und ist bis jetzt das erste J2EE Framework, dass mir von Anfang zusagte und es auch schaffte, mich zu begeistern.

Die Webanwendung ist komplett UTF-8 basiert. Soweit so gut. Leider mußte ich feststellen, dass Eingaben per form nicht so ankamen, wie ich mir das vorgestellt hatte, irgendwo ging das Characterset verloren.

Ich nutze zur Zeit Java 1.5.0.8, Apache Tomcat 5.5.17, Spring 1.2.8 sowie Hibernate 3.1.x. Irgendwo im Zusammenspiel der ersten drei Komponenten trat der Fehler auf, obwohl ich in allen beteiligten JSP Dateien den Content Type angegeben habe. Ich habe mir jetzt mit folgenden Filter beholfen, der dafür sorgt, dass UTF-8 auch als solches ankommt:

package filter;
 
import java.io.IOException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
 
public class CharsetFilter implements Filter {
	FilterConfig config;
	String encoding = "UTF-8";
 
	/**
	 * @see javax.servlet.Filter#destroy()
	 */
	public void destroy() {
	}
 
	/**
	 * Sets the character encoding on the request
	 * @see javax.servlet.Filter#doFilter(javax.servlet.Servle tRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		request.setCharacterEncoding(encoding);
		chain.doFilter(request, response);
	}
 
	/**
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConf ig)
	 */
	public void init(FilterConfig config) throws ServletException {
		this.config = config;
		this.encoding = config.getInitParameter("requestEncoding");
	}
}

Der Filter kann im web.xml einfach konfiguriert werden:

<filter>
	<filter-name>
		charsetFilter
	</filter-name>
	<filter-class>
		filter.CharsetFilter
	</filter-class>
	<init-param>
		<param-name>requestEncoding</param-name>
		<param-value>UTF-8</param-value>
	</init-param>
</filter>
 
<filter-mapping>
	<filter-name>charsetFilter</filter-name>
	<url-pattern>/app/html/*</url-pattern>
</filter-mapping>