I'm using JPA (Hibernate as provider), Glassfish and MySQL. Everything works great in development, but when I deploy the app to a test server and let it run (largely idle) overnight, I'm usually greeted with this in the morning:
[#|2011-03-09T15:06:00.229+0000|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=23;_ThreadName=Thread-1;|ERROR [htt\
p-thread-pool-8080-(1)] (JDBCTransaction.java:91) - JDBC begin failed
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 41,936,868 milliseconds ago. The last packet \
sent successfully to the server was 41,936,868 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expirin\
g and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connec\
tion property 'autoReconnect=true' to avoid this problem.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1118)
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3321)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1940)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2562)
at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:4956)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:87)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473)
at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:60)
I tried using the following in my persistence.xml, but it didn't help:
<property name="hibernate.c3p0.min_size" value="5"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.idleTestPeriod" value="30"/>
<property name="hibernate.c3p0.timeout" value="0"/>
<property name="hibernate.c3p0.max_statements" value="0"/>
So that's the C3p0 configuration; it's entirely possible I'm missing the part that actually tells hibernate "hey, use c3p0".
I'm about to try the suggestion that's right there in the error message: add autoReconnect=true to my JDBC URL, but this is really starting to feel like cargo-cult development at this point. I would appreciate some guidance on the proper way to address this issue. It's hard to debug, because the test cycle is effectively "run it overnight, see what happens in the morning".
I should probably mention how I'm actually using connections in my app. I have a custom Servlet Filter that intercepts all requests. It creates an EntityManager, stores it in a ThreadLocal, and is closed by the filter in a catch/finally block. All my entities obtain a reference to the EntityManager from the ThreadLocal.
It's entirely possible that my filter is at fault, but as it only seems to happen after idle periods, I suspect something else is wrong. I do intend to move to Seam/Weld when I have a chance to catch my breath, but for now I'm relying on this filter.
Edit: here's the TL;DR solution:
use your container's connection pool, if you can (thanks, #partenon)
make sure your connection pool uses connection validation (thanks, #matt b)
In my case, I had to go into the Glassfish console under Resources/JDBC/Connection Pools, Advanced Tab, and then enable Connection Validation:
This was really the crucial step. You also probably want to set Validate At Most Once to something reasonable, say 100 seconds. If you're using C3P0 or similar, make sure you configure idle_test_period and preferredTestQuery.
Whatever you end up doing, it's important to test out your changes to see if they have the desired effect. To make the timeout happen faster in MySQL, you can temporarily set the wait_timeout to something low like 30 seconds by editing my.cnf. This was a tremendous help in debugging this problem, as it allowed me to test changes in seconds, rather than hours.
I think the real question is: why are you using an external connection pooling mechanism instead of using Glassfish' own pooling? Your app server is better suited to provide this kind of service to your application. "External" connection pooling mechanisms are better suited for standalone applications, not in-container applications.
You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
Just a shot in the dark, but have you taken a look at setting the autoReconnect=true property in your JDBC driver? Or consider disabling the server-side setting for client connection timeouts.
I think the property to set the connection test period is idle_test_period, not idleTestPeriod as per C3P0 documentation here. So you should be using:
<property name="hibernate.c3p0.idle_test_period" value="30"/>
instead.
I was getting the same problem and it took time to figure out the solution.
I use Hibernate 4.0.1 and mysql 5.1(no spring framework) and I was facing the issue. First make sure that you configured the c3p0 jars properly which are essential.
I used these properties in hibernate.cfg.xml
<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.preferredTestQuery">SELECT 1;</property>
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<property name="hibernate.c3p0.idle_test_period">10</property>
<property name="hibernate.c3p0.acquireRetryAttempts">5</property>
<property name="hibernate.c3p0.acquireRetryDelay">200</property>
<property name="hibernate.c3p0.timeout">40</property>
But it's of no use 'cause C3p0 was still taking the default properties not the properties which I set in hibernate.cfg.xml, You can check it in logs. So, I searched many websites for right solution and finally I came up with this. remove the C3p0 properties in cfg.xml and create c3p0-config.xml in the root path(along with cfg.xml) and set properties as follows.
<c3p0-config>
<default-config>
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">40</property>
<property name="idleConnectionTestPeriod">10</property>
<property name="initialPoolSize">10</property>
<property name="maxPoolSize">20</property>
<property name="minPoolSize">5</property>
<property name="maxStatements">50</property>
<property name="preferredTestQuery">SELECT 1;</property>
<property name="acquireRetryAttempts">5</property>
<property name="acquireRetryDelay">200</property>
<property name="maxIdleTime">30</property>
</default-config>
</c3p0-config>
but if you run, ORM takes the jdbc connection but not C3p0 connection pool 'cause we should add these properties in hibernate.cfg.xml
<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
now everything works fine(At least it worked fine for me) and the issue is solved.
check the following for references.
http://www.mchange.com/projects/c3p0/index.html#configuring_connection_testing
https://community.jboss.org/wiki/HowToConfigureTheC3P0ConnectionPool
I hope this solves your problem.
Related
I've tried two methods for adding p6Spy feature to my spring used project.
Route I,
http://templth.blogspot.com.tr/2004/11/integrate-p6spy-with-spring.html
I changed my driver with com.p6spy.engine.spy.P6SpyDriver and added realdriver realdriver=com.ibm.db2.jcc.DB2Driver into spy.properties file.
But somehow my realdriver is being registered before p6spy driver com.ibm.db2.jcc.DB2Driver is a real driver in spy.properties, but it has been loaded before p6spy. p6spy will not wrap these connections.Either prevent the driver from loading, or try setting 'deregisterdrivers' to true in spy.properties
Using :p6spy: prefix doesn't work for me. It says can't establish connection with that url.
So,I chose setting this deregisterdrivers=true in property file.
This time I get sql in log file but can't execute sqls. I'm able to execute sql in another sql editor. It seemed real connection went and a dummy one came.
Route II,
We use spring. So I've tried this method. Giving datasource explicitly to p6Spy. But this time spring complained of multiple java.sql.DataSource instance. Both com.firm.BasicDataFill and com.p6spy.engine.spy.P6DataSource implements DataSource. Spring can't obtain a singleton.
http://templth.blogspot.com.tr/2004/11/integrate-p6spy-with-spring.html
<bean id="dataSource" lazy-init="true"
class="com.firm.BasicDataFill">
<property name="driverClassName" value="${database.connection.driver_class}" />
<property name="username" value="${database.connection.username}" />
<property name="password" value="${database.connection.password}" />
<property name="url" value="${database.connection.url}" />
...
<property name="accessToUnderlyingConnectionAllowed" value="true" />
</bean>
<!-- bean id="myDataSource" class="com.p6spy.engine.spy.P6DataSource">
<constructor-arg>
<ref local="dataSource"/>
</constructor-arg>
</bean-->
Finally, I discovered p6spy v1.3 and 2.4.1 settings vary. Do you have any suggestion for a spring based application.
I would recommend starting with the latest version of P6Spy 2.x. You should also REPLACE your spy.properties file with the default version for 2.X which is documented here. Depending on your application server, you might need to set the 'realdriver' setting in spy.properties to include 'com.ibm.db2.jcc.DB2Driver'. However, this is only needed when you are using an application server that prevents the automatic registration of JDBC Drivers.
To use P6Spy with Spring, the easiest method is to wrap your current data source bean with P6SpyDataSource as discussed here. The example in that answer shows a JNDI data source being wrapped but it can be used to wrap any data source. Note: If you are wrapping the data source is P6SpyDataSource, you do NOT need to modify the JDBC URL.
If you continue to have problems, please add a bit more information to your question. The following information would be helpful in troubleshooting:
The version of P6Spy being used
The contents of spy.properties
The definition of your datasource (including app server config if
using JNDI)
The type of app server and version being used
Stacktrace containing whatever error you might have received.
Have a look at Log4jdbc it'll do the job https://code.google.com/p/log4jdbc/
I am using spring boot and hibernate over jpa with tomcat connection pooling. Can you please help me understanding how spring uses DB connections during transactions. For example consider following scenario:
We have DB connection pool of 2 connections.
Spring starts a transaction i.e. call method decorated with #Transactional annotation.
This method do a DB update
The calls an external service
As response is received from the external service, it updates DB and return.
Spring commits the transaction
Assuming the external service(step 4) takes 1 minute to complete, how many DB connections will be available in the DB pool?. Assuming, spring keeps hold of DB connection until the transaction completes, there will be only 1 DB connection available for any request received during this time and if we received more than 1 requests, they will have to wait for DB connection.
Please confirm my understanding and if it is correct, suggest how I can handle this situation in a high transaction volume system.
Thanks
First your understanding is correct. See the spring documentation about declarative transaction management.
I guess you do the external service call within the transaction, because you want the database changes to be rollbacked in case of an exception. Or in other words you want the db updates to reflect the state of the external service call.
If so you can't move it out the transaction boundary. In this case you should either increase your connection pool size or maybe you can delegate long running transactions to a dedicated server node that handles them. This would keep e.g. a "main" server node that handles user requests away from long running transactions.
And you should think about the data consistency. Is it really necessary that the db update must be synchronized with the external service call? Can the external service call be moved out of the transaction boundary?
You can specify initial size and maximum size of connection pool as per your requirement(depends on the performance of your application).
For example,
<bean id="springDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
<property name="url" value="jdbc:oracle:thin:#localhost:1521:SPRING_TEST" />
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="removeAbandoned" value="true"/>
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
</bean>
this will create 20 database connection as initialSize is 20 and goes up to 30 Database connection if required as maxActive is 30. you can customize your database connection pool by using different properties provided by Apache DBCP library. Above example is creating connection pool with Oracle 11g database and i am using oracle.jdbc.driver.OracleDriver comes along with ojdbc6.jar or ojdbc6_g.jar
For unit tests (call them integration tests if you want) I have configured an embedded database in my Spring config like so:
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:schema_h2.sql" />
</jdbc:embedded-database>
Now, when running the tests from the command line, they work fine, but I get some errors at the end (harmless, but irritating):
WARN 2013-03-25 12:20:22,656 [Thread-9] o.s.j.d.e.H2EmbeddedDatabaseConfigurer 'Could not shutdown embedded database'
org.h2.jdbc.JdbcSQLException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-170]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329) ~[h2-1.3.170.jar:1.3.170]
...
at org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryBean.destroy(EmbeddedDatabaseFactoryBean.java:65) [spring-jdbc-3.2.1.RELEASE.jar:3.2.1.RELEASE]
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:238) [spring-beans-3.2.1.RELEASE.jar:3.2.1.RELEASE]
Now the tip contained in the exception is fine in general, but how do I add this attribute to the embedded datasource? Do I have to expand it, configure it by hand so to speak, to add such ‘advanced’ features?
Specify parameter in JDBC url jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE
Also for in-memory test database I suggest you to add DB_CLOSE_DELAY=-1, like this:
jdbc:h2:mem:alm;MODE=Oracle;DB_CLOSE_DELAY=-1
To add JDBC connection url to embedded-dababase change it to:
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:test;MODE=Oracle;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
<jdbc:script location="classpath:schema_h2.sql" />
</jdbc:initialize-database>
I had the same issue as Michael Piefel's one and tried to implement the solution that Michail Nikolaev explained.
but it did not work, somehow spring-batch, then, where are the metadata JOB_* tables are.
So, as the version of spring-jdbc used by my application is 3.0.5 and increasing the spring-framework one enters in conflict with dwr (i use it in my app) it's a geo localization based on spring, dwr and gmaps api.
I downloaded the spring-jdbc 4.0.3 release and get from it the H2EmbeddedDatabaseConfigurer.class who has DB_CLOSE_ON_EXIT=FALSE by default and replace with it the one on the spring-jdbc 3.0.5 Release and deploy-it in the war file and it works, the shutdown of the VM didn't provoke the closing of the in-memory database.
Hope this unusual solution helps if other people like me wouldn't be able to implement the other solution.
I had the same problem, but it was because I forgot to add the annotation #Entity on one of my entities. I add it and it work now !
I hope this helps someone.
<property name="hibernate.connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:jtds:sqlserver://host/:port/db_name;instance=smth</property>
<property name="hibernate.connection.username">XXX</property>
<property name="hibernate.connection.password">YYY</property>
<property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
With this configuration, hibernate connects my program to "master" database instead of "db_name". How can i solve this problem?
EDIT: jtds 1.2.5.
Problem is solved - SQL Server was configured in a way that we can't use name instances. jdbc:jtds:sqlserver://host:port/db_name (without ;instance=smth) is working correctly
Your URL doesn't look right to me. I don't know if it's a typo, but it should look like this:
jdbc:jtds:sqlserver://host:port/db_name;instance=smth
You should not have a slash between host and port.
http://jtds.sourceforge.net/faq.html#urlFormat
I am using Oracle 9 JDBC Thin Driver - the connection string I have used for standard JDBC was:
jdbcConn.connect("jdbc:oracle:thin:myDevDb/myDevDb#fooServer:1521:MYSIDNAME");
...just trying to get my head around using this kind of connection in Spring 2.5.
How do you wire up Spring to an Oracle connection - think it has something to do with an XML conifg file but not sure, there seems to be a couple of ways to do it.
Any help much appreciated...
LATEST EDIT
Thanks to those who have responded so far - but I need a bit of a "leg up" - on the part where you configure in the database connection string setup in your config, where do you put this info, and how?
I have an existing Java web application - and I am trying to get to grips with how I 'shoehorn' Spring into my existing app.
There are a few ways of doing this and it depends on what your environment is. If you're using Spring there's a fair chance you're deploying a Web application or you're otherwise in a J2EE environment. If this is the case (and arguably even if it isn't) you probably want to configure a DataSource.
This is a fairly minimal solution:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
The above is using the Apache (Jakarta Commons) database connection pooling but your appserver probably has an alternative you may want to use instead. Also, different database vendors have their own data source implementations too (eg OracleDataSource and OracleXADataSource for Oracle).
Note the use of properties like jdbc.username. This is a typical configuration because database configurations typically vary between environment. You can activate a property configurator with something like:
<bean id="jdbcConfiguration" class="org.springframework.beans.factory.config.PropertiesPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean>
Now you probably want transactions too I would imagine. The easiest way is to use a platform transaction manager but, like with most things Spring, there are multiple ways of doing it.
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
After this you can use this bean directly or (arguably more common) you can use declarative transactions with AOP (annotations).
More on these subjects in the (superb) Spring reference documentation.