Thanks Robert, That was the answer. The memory leak disappeared. I now create a DataContext with 'method scope' that gets gc-ed when the method has finished. That brought up what must be another problem with my code which I'm investigating now:
Caused by: org.apache.cayenne.CayenneRuntimeException: [v.3.0 Apr 26 2010 09:59:17] Error detecting database type: Data source rejected establishment of connection message from server: "Too many connections" at org.apache.cayenne.dba.AutoAdapter.loadAdapter(AutoAdapter.java:185) at org.apache.cayenne.dba.AutoAdapter.getAdapter(AutoAdapter.java:155) at org.apache.cayenne.dba.AutoAdapter.getExtendedTypes(AutoAdapter.java:263) at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:243) at org.apache.cayenne.access.DataDomainQueryAction.runQuery(DataDomainQueryAction.java:422) at org.apache.cayenne.access.DataDomainQueryAction.access$000(DataDomainQueryAction.java:69) at org.apache.cayenne.access.DataDomainQueryAction$2.transform(DataDomainQueryAction.java:395) at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:850) at org.apache.cayenne.access.DataDomainQueryAction.runQueryInTransaction(DataDomainQueryAction.java:392) at org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:121) at org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:743) at org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:333) at org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:96) at org.apache.cayenne.access.DataContext.onQuery(DataContext.java:1278) at org.apache.cayenne.access.DataContext.performQuery(DataContext.java:1267) at com.seasoft.store.orm.CayenneInterpretedQuery.execute(CayenneInterpretedQuery.java:265) at com.seasoft.store.DomainQuery.execute(DomainQuery.java:43) at com.seasoft.store.DomainQueries.executeRetCollection(DomainQueries.java:56) at com.cmts.business.orm.DOActivity.storeRealtimeReadings(DOActivity.java:113) at com.cmts.business.SenderGasReceiver.storeRealtimeSamplesIntoSummaryReadings(SenderGasReceiver.java:266) at com.cmts.business.StoreRealtimeIntoDBJob.execut e(StoreRealtimeIntoDBJob.java:20) at org.quartz.core.JobRunShell.run(JobRunShell.java:216) Maybe I need to recycle connections or something?? In the Cayenne documentation I found this: "Cayenne will also periodically close unused database connections if it determines there are too many that are open and idle." Is there some way to hint to Cayenne that you've finished with a DataContext's connection pool, something like 'dataContext.close()'? Here is the exception at a lower level: Caused by: java.sql.SQLException: Data source rejected establishment of connection message from server: "Too many connections" at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1997) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1906) at com.mysql.jdbc.MysqlIO.secureAuth411(MysqlIO.java:2520) at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:817) at com.mysql.jdbc.Connection.createNewIO(Connection.java:1782) at com.mysql.jdbc.Connection.<init>(Connection.java:450) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:411) at org.apache.cayenne.conn.DriverDataSource.getConnection(DriverDataSource.java:156) at org.apache.cayenne.conn.PooledConnectionImpl.reconnect(PooledConnectionImpl.java:83) at org.apache.cayenne.conn.PooledConnectionImpl.getConnection(PooledConnectionImpl.java:120) at org.apache.cayenne.conn.PoolManager.uncheckConnection(PoolManager.java:369) at org.apache.cayenne.conn.PoolManager.getConnection(PoolManager.java:353) at org.apache.cayenne.conn.PoolManager.getConnection(PoolManager.java:330) at org.apache.cayenne.access.DataNode$TransactionDataSource.getConnection(DataNode.java:364) at org.apache.cayenne.conf.NodeDataSource.getConnection(NodeDataSource.java:46) at org.apache.cayenne.dba.AutoAdapter.loadAdapter(AutoAdapter.java:170) Thanks ~ Chris Murphy On 11 December 2011 17:57, Robert Zeigler <robert.zeig...@roxanemy.com>wrote: > Note that DataContext creation is cheap. What I typically do in situations > like this is to periodically create a new data context that you can throw > away. When it's gone, the associated objects will be gc'ed. Eg: you could > periodically dump the "reading" data context and create a fresh one after > every 1,000 Reading objects or whatever makes sense for your use-case. If > the frequency of readings transactions is low, it probably makes sense to > create a new DataContext, import whatever objects you need into it (via > localObject), create your readings, commit, then discard the DataContext. > If the readings are very frequent, then it makes sense to have a dedicated > "readings" DataContext that you can periodically swap out. > > HTH, > > Robert > > On Dec 11, 2011, at 12/1112:51 AM , Chris Murphy (www.strandz.org) wrote: > > > I have a server application that continually reads data from sensors. At > > set intervals the data is summarized. This summary data is used to create > > Cayenne data objects of type Reading. A short transaction commits these > > Reading objects to the database, after which it is not important that > they > > are held in memory - they were created only to be stored. After a long > > period of time their continual collection results in an 'OutOfMemory' JVM > > condition. > > > > There are many objects of type Reading for another Cayenne data object > > called SubstancePoint. And there's a whole object graph going back from > > there. I basically want to keep the whole of the object graph in memory, > > except for these Reading objects. > > > > Is there a way to 'disappear' data objects from the DataContext? For that > > is what I think would solve my problem. I have tried calling > > DataContext.unregisterObjects() post-commit on the Reading data objects I > > want evacuated from memory, but I can see that the leak is still going > on. > > > > Thank you ~ Chris Murphy > >