Atomikos Forum |
|
Hi!
I ´ve been testing the new version of Atomikos with the new AtomikosDataSourceBean. Here is the config: <Resource name="jdbc/datasource" auth="Container" type="com.atomikos.jdbc.AtomikosDataSourceBean" factory="com.atomikos.tomcat.BeanFactory" uniqueResourceName="jdbc/datasource" xaDataSourceClassName="oracle.jdbc.xa.client.OracleXADataSource" maxPoolSize="3" xaProperties.URL="jdbc:oracle:thin:@..:1521:.." xaProperties.user="..." xaProperties.password=".."/> When I use with source code that worked in the 3.2.0 release like this: UserTransaction ut=null; DAO1 dao1=new DAO1(); DAO2 dao2=new DAO2(); DAO3 dao3=new DAO3(); boolean commit=false; try{ ut=getTransaction(); ut.begin(); Object obj1=dao1.getSomeObjectFromDB(Integer id); dao2.updateThings(obj1); dao3.deleteThings(obj1); ut.commit(); if(!commit){ ut.rollback(); } }finally{ } Inside every DAO I´ve always the same structure: public class DAO1 { public void getSomeObjectFromDB() throws Exception{ Connection con=null; try{ con=getConnection(); con.executeQuery.. }finally{ if (con!=null) con.close(); } } } public class DAO2 { public void updateThings(Object obj) throws Exception{ Connection con=null; try{ con=getConnection(); con.executeUpdate.. }finally{ if (con!=null) con.close(); } } } When I execute the source code below the DAO, I´ve a exception: "Cannot perform commit". I checked that it works perfectly if I move out the transaction begin-commit scope the DAO objects that only execute query operations, not updating nor deleting ones. Why this behaviour in the new release? Why this worked perfectly in previous versions? Thanks very much! Here´s is the jta.properties: com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory com.atomikos.icatch.log_base_dir=${catalina.base}/logs com.atomikos.icatch.output_dir=${catalina.base}/logs com.atomikos.icatch.console_log_level=DEBUG com.atomikos.icatch.lock_logs=false And here´s the log. I didn´t see any exception.. 08-05-20 17:45:31,609 [http-8080-Processor25] ConnectionPool: cannot grow pool as it reached max size: 3 08-05-20 17:45:31,609 [http-8080-Processor25] an AtomikosXAPooledConnection with a SessionHandleState with 0 context(s): updating last time acquired 08-05-20 17:45:31,609 [http-8080-Processor25] an AtomikosXAPooledConnection with a SessionHandleState with 0 context(s): no test query, skipping test 08-05-20 17:45:31,609 [http-8080-Processor25] an AtomikosXAPooledConnection with a SessionHandleState with 0 context(s): creating connection proxy... 08-05-20 17:45:31,609 [http-8080-Processor25] a SessionHandleState with 0 context(s): notifySessionBorrowed
Another thing here..After throwing the exception performing the "commit", if I try to shutdown Tomcat, I think it gets "idle" waiting for something, and I have to kill Tomcat.
If I start the Tomcat server again, I get a recovery error (the datasource name is jdbc/DMADuero): 08-05-20 17:42:58,625 [http-8080-Processor25] USING com.atomikos.icatch.force_shutdown_on_vm_exit = false 08-05-20 17:42:58,671 [http-8080-Processor25] AtomikosDataSourceBean: initializing with [ xaDataSourceClassName=oracle.jdbc.xa.client.OracleXADataSource, uniqueResourceName=jdbc/datasource, maxPoolSize=3, minPoolSize=1, borrowConnectionTimeout=30, maxIdleTime=60, reapTimeout=300, maintenanceInterval=60, testQuery=null, xaProperties={URL=jdbc:oracle:thin:@...:1521:..., user=...., password=...},] 08-05-20 17:42:58,718 [http-8080-Processor25] Configuration: adding resource jdbc/datasource 08-05-20 17:42:58,718 [http-8080-Processor25] Installing recovery service on resource jdbc/datasource 08-05-20 17:42:58,718 [http-8080-Processor25] jdbc/DMADuero: refreshing XAResource... 08-05-20 17:42:59,140 [http-8080-Processor25] jdbc/DMADuero: refreshed XAResource 08-05-20 17:42:59,140 [http-8080-Processor25] recovery initiated for resource jdbc/DMADuero with branchIdentifier 10.120.0.49.tm 08-05-20 17:42:59,265 [http-8080-Processor25] Error in recovery javax.transaction.xa.XAException at oracle.jdbc.xa.OracleXAResource.recover(OracleXAResource.java:705) at com.atomikos.datasource.xa.XATransactionalResource.recover(Unknown Source) at com.atomikos.datasource.xa.XATransactionalResource.endRecovery(Unknown Source) at com.atomikos.icatch.imp.TransactionServiceImp.recover(Unknown Source) at com.atomikos.datasource.xa.XATransactionalResource.setRecoveryService(Unknown Source) at com.atomikos.icatch.system.Configuration.addResource(Unknown Source) at com.atomikos.jdbc.AtomikosDataSourceBean.doInit(Unknown Source) at com.atomikos.jdbc.AbstractDataSourceBean.init(Unknown Source) at com.atomikos.tomcat.BeanFactory.getObjectInstance(BeanFactory.java:72) at org.apache.naming.factory.ResourceFactory.getObjectInstance(ResourceFactory.java:140)
Another thing: I´ve tested with de DEPRECATED datasource:
<Resource name="jdbc/datasource" auth="Container" type="com.atomikos.jdbc.SimpleDataSourceBean" factory="org.apache.naming.factory.BeanFactory" uniqueResourceName="jdbc/datasource" xaDataSourceClassName="oracle.jdbc.xa.client.OracleXADataSource" connectionPoolSize="5" connectionTimeout="40" xaDataSourceProperties="URL=jdbc:oracle:thin:@...:1521:.;user=..;password=..."/> And it worked perfectly, but the number of connections is always connectionPoolSize +1, don´t know why. I suppose something´s wrong with the new AtomikosDataSourceBean... Thanks!
Hi,
All this seems to make sense even if a bit disturbing. The old deprecated pool did not really have an upper connection limit: when the pool was empty and a new connection was requested from your code, it would just open a new database connection. The new pool takes the maxPoolSize property very strictly: in no way it's going to create more connections than specified in this setting (with the exception of the extra connection used for recovery). When the pool is exhausted, it will block until a connection can be acquired or until a configurable timeout occurs. This might be the reason why your Tomcat blocked during shutdown. Finally, using connections in the way you do can quickly deplete the pool as when a connection is acquired and then closed, the pool waits until the transaction is finished until marking that connection as reusable. in a nutshell, if you do: ut.begin(); for (int i=0;i<6;i++) { c = ds.getConnection(); c.close(); } ut.commit(); with a pool configured with max 5 connections, you will reach the limit. I hope this makes more sense to you now. Ludovic
Ok, I understood. Perhaps you could add another init param for the pool, some attribute like "onExhausted" with some values like "ON_EXHAUSTED_GROW", "ON_EXHAUSTED_BLOCK". This pool behaviour I´m telling is the same as Apache commons-pool and I think is very important for production environments.
As I said in other post, I have a problem with this connection locking. Perhaps in my proyect we have too many DAO that only does one DB operation each (and this causes many calls to getConnection()), but I think it´s not bad code design (for DAO reuse reasons). Going back to the deprecated pool is not the solution, because the new pool has very useful functionality (like shrink pool). Thanks for your reply! |