You have a Java web application (Java Web, Grails, Spring, etc...). You have had the application deployed to PWS where it has been running successfully for a while. You have recently, as of Sept 2014, pushed your application and it's now failing stating that the maximum number of connections to the database has been exceeded.
It is important to note that the Java build pack, which runs your Java based applications on PWS, was updated in Sept 2014 to use both Java 8 and Tomcat 8 as it's defaults. In other words, when you push your application to PWS now (after Sept 2014), your application will run using Java 8 and, if it's web based be deployed in a Tomcat 8 container. Both of these changes are major changes. Previously the build pack was defaulting to Java 7 and Tomcat 7, and this major change may cause compatibility issues with your application. The issue discussed in this article is complicated, but results from changes introduced in Tomcat 8.
In Tomcat 8 the default DataSource implementation has changed. In previous versions it was Commons DBCP. It's now Commons DBCP2. If your application is using the auto configuration feature of PWS, you may see the implementation of your DataSource change because of this. This happens because auto configuration examines your class path for a few different DataSource implementations, using the one it finds first. If your application does not bundle DBCP with it, auto configuration will attempt to use the version of DBCP bundled with Tomcat however that no longer ships with Tomcat 8. It will then fall back to Tomcat's jdbc-pool implementation, which is present in Tomcat 8.
In some cases, this change will not impact your application. When it does, it will manifest as an error saying that you are exceeding the maximum connections for your database. This happens because Tomcat's jdbc-pool defaults to creating 10 connections at startup, whereas DBCP defaults to zero. The error occurs because most of the database providers on PWS limit the maximum number of database connections to four on their free tier databases.
There are a couple ways to resolve this issue.
- From the service side, you can upgrade your service instance so that it supports more simultaneous connections. It would need to support 10 or more to resolve this issue.
- From the application side, you can define some limits on your DataSource. To do this, you'll need to use the manual service configuration option which is described in the documentation here.
Manual service configuration will override the defaults and allow you to set a connection limit. You can do this by using the Spring "cloud" namespace, which offers one way to set the size of the connection pool.
<cloud:data-source id="dataSource"> <cloud:pool pool-size="2" /> </cloud:data-source> </beans>
More details on the Spring "cloud" namespace can be found here.
Instead of using the Spring "cloud" namespace, you could simply define the connection pool bean directly. You can do this in a variety of ways, but using Spring's Profile feature or using property place holders are easy ways to accomplish this.
- From the build pack side, you can instruct it to use Tomcat 7.