I have a Play Framework 2.2.2 application that I am deploying as a .war file and running under Tomcat 7. My application runs for days without problems on my local dev machine (through Play's built in server, not Tomcat), but once I deploy it under Tomcat, after several hours the Tomcat server will lock up, taking down all the other applications running on it as well.
I think the problem is that the BoneCP connection pool in Play, and the built-in connection pool of Tomcat are conflicting. There isn't much or any useful information in the Tomcat logs, so I'm kind of left guessing here.
I'd like to disable the BoneCP connection pooling within my Play application, but cannot find any information on how to do so.
Any advice appreciated!
There are several possible solutions for this, which might be more or less preferrable for your deployment environment.
Play gives you an "out-of-the-box" database connection, which you don't need to use. Drop the Play JDBC component from your build file (remove jdbc from your libraryDependencies) and setup your JDBC connections manually by yourself. For example, you can make a singleton TomcatConnectionPool that has a function getConnection() that gives you the JDBC connection you need for use in your Play actions.
Write your own plugin specifically extending Play's DBPlugin interface so that it's a database plugin. Implement it like Play's BoneCPPlugin but make it use the Tomcat connection pool instead of BoneCP.
Use someone else's already made custom Play Database Plugin, like this one that uses c3p0. I have some anecdotal evidence that c3p0 works well with Tomcat, but your mileage my vary.
Related
This question already has answers here:
Where to put 3rd party libs when using Maven with Tomcat?
(2 answers)
Closed 3 years ago.
I am trying to use postgresql driver with tomcat.
but when i run tomcat I am getting FileNotFound exception(Class.forName("org.postgresql.Driver")).
Is tomEE aware of maven dependency.
how can I overcome it
No. Maven not involved after Tomcat/TomEE deployment
No, TomEE does not know about Maven or your POM.
As commented by Andreas, your Maven-driven web-app project will produce a WAR file or EAR file. That file contains any dependencies you may have configured in your POM.
For deployment, you will be moving that WAR or EAR file to the TomEE server. At that point there is no more Maven involvement.
These comments above apply to your eventual deployment for production. While in development, you may be using an IDE such as IntelliJ/NetBeans/Eclipse that can call upon an external web container such as Tomcat or TomEE to run and debug your web app. Maven settings may be involved in that special case, as part of hooking up your IDE to the external web container. Even in this special case, Tomcat/TomEE is not aware of Maven having possibly participated in its launching or configuration.
JDBC drivers are special
Furthermore, deploying a JDBC driver to Tomcat, TomEE, or other Jakarta Servlet container is a complicated matter because of classloader issues and the JDBC driver registration process. Generally, you should not be bundling a JDBC driver within your WAR/EAR.
Search Stack Overflow to learn more. Remember that TomEE is built on Apache Tomcat, so most anything you read about Tomcat applies.
See:
Where to put 3rd party libs when using Maven with Tomcat?
To prevent a memory leak, the JDBC Driver has been forcibly unregistered
How should I connect to JDBC database / datasource in a servlet based application?
By the way, in modern Java with its JDBC driver registration feature (DriverManager), you no longer need to call Class.forName. That call is now legacy.
DataSource
Tip: Learn to use a DataSource implementation provided by your driver. Regarding Postgres, if using the JDBC driver from jdbc.postgresql.org, see this chapter.
PGSimpleDataSource pgDataSource = new PGSimpleDataSource();
pgDataSource.setDataSourceName("Acme Corp invoicing database");
pgDataSource.setServerName("localhost");
pgDataSource.setDatabaseName("test");
pgDataSource.setUser("testuser");
pgDataSource.setPassword("testpassword");
DataSource dataSource = pgDataSource ; // Perhaps save as an "attribute" on your web app's "context".
Ask the data source for a Connection object when needing to talk to the database. Usually best to use try-with-resources syntax.
try
(
Connection conn = dataSource.getConnection() ;
)
{
… do your database work
}
Later you can learn to configure this DataSource info externally, outside your code base. That configuration is done through JNDI and a naming server such as the LDAP-style server built into Tomcat.
I have a JAVA webapp which is using DB connection pooling for Tomcat+MySQL config.
I have another JAVA webapp which i want to deploy in the same Tomcat and connect to same MySQL database (even access the data from same tables).
I havent figured out a way how to achieve the same.
Should I have connection pooling context.xml for each of the webapps?
Or should I have a global configuration.
In the first case , I assume there is nothing different that i need to do. Only to deploy the webapp which has its own context.xml.. Please correct me if i'm wrong.
If having a global config is a better solution, how to achieve that. Haven't found any good tutorials about it. What changes in each of webapps need to made , so that it knows that it needs to read the global config.
There's nothing wrong with having a separate context for each webapp unless you want to centrally manage changes to the database (i.e. migrate it to a different DB, change connection parameters). If you think your connection properties will change or you want that flexibility then you can use a JNDI datasource in tomcat and manage it there (google is your friend for that).
I have used MySqlDataSource for in jdbc connectivity.I have used following code
MysqlDataSource d = new MysqlDataSource();
d.setUser("user");
d.setPassword("pass");
d.setServerName("hostname.com");
d.setDatabaseName("db");
Connection c = d.getConnection();
Also i have searched there is an option of Configuring a MySQL Datasource in Apache Tomcat.
Is there any performance difference between these two? which one is best to use?
Configuring Datasource in tomcat will help you to share same data source between applications running in same tomcat. that Datasource will be managed by container (tomcat in your case).
while the Datasource created in code will be created by your application and can be used by that application only.
So if you have multiple application running on tomcat and accessing same data source, that configuring Datasource in tomcat will be good approach and have performance factor because only one data source is created and not having separate connections for each application
But if you have only single application that the first approach you have used is good one
They both use the internally the same driver, i dont think the performance is much different here, i guess if you need to access teh database only at that place and the enduser isn't supposed to use his own authentication you may use it directly from java, but if you will need the connectivity on different places it could be helpful to configure this using apache configuration, specially that if anything changes like database server, user name or whatever you don't need to get in the code to change it, this could be very important if end users have to set their own configurations.
The improvement of configuring a pool of Connections (as the one provided by tomcat) is mainly that you will actually create and close a lot less of connections.
When using a pool, when you request a Connection to a pool it will look if it has any connection already created and available for reuse and, if it has, it will provide you with it (instead of creating a new Connection, which is a heavy operation). You must still close() a Connection provided by Tomcat so Tomcat knows that it can now reuse when it is requested again.
Additionally, the advantage of the pool is that your code does not need to know the configuration data for the Connection. He just requests a Connection from a given pool and the sysadmin configures it, allowing for greater flexibility (the sysadmin does not need to know how to configure your app, just how to configure the Tomcat which is fairly more standard).
I'm using spring to connect to mysql currently.
I'm thinking of moving to simply servlets and drop spring as I don't need 99% of spring's functionality.
What do you suggest I use to get connection pooling functionality? Is there a mysql connection pool that is framework independent?
Even if you don't need 99% of Spring's features you can still use Spring JDBC which by itself is worthwhile. You don't need the whole Spring infrastructure to use it either - you can drop it in and use it by itself...no DI required. I have a coworker who is using Stripes as his app's framework but uses Spring JDBC for database access.
You don't say what your container is (e.g. Tomcat, JBoss, etc) but there are several container independent connection pools to choose from, such as DBCP, c3p0, BoneCP. If you're using Tomcat 7 it ships with a new connection pool called The Tomcat JDBC Connection Pool (I guess their marketing budget was cut :) ).
We just switched from DBCP to Tomcat's connection pool and it works great. We haven't run any benchmarks on it but haven't run into any issues yet either.
I recommend sticking with Spring JDBC even if you use another connection pool, just for the database connection/statement management, disconnected result set, and "free" prepared statements (Spring JDBC creates prepared statements under the hood for you).
The Tomcat JDBC connection pool uses Tomcat JULI as part of its logging requirements.
Play uses log4j for its logging. My worry is, will there be any conflict?
Is it good to go with this?
Please advise.
I have used Play within Tomcat and no conflicts here...