Hi Daniel,
many thanks for your detailed description and suggestion.
>
> The solution is in ConnectionManagerImpl.getConnection method. The code is
> already there, but commented out:
>
>> // if (con == null || !isAlive(con))
>> // isAlive check, how do we react if false and we in tx?
>> // create a new connection isn't the right way I think.
>> if (con == null)
>
>
> I think this code should be applied - or at the very least, should be
> modified and applied if not inside a transaction:
>
> if (con == null || (!isInLocalTransaction() && !isAlive(con)) )
>
I will check in your patch ASAP. Additionally I think we should release the closed connection instance and I will do a minor refactoring of CollectionProxyDefaultImpl to handle the used PB instance more strict.
regards, Armin
Daniel Perry wrote:
I believe that I have solved this problem, and that there is a bug in OJB. I cannot be sure, but with the fix, the app has been running for 10 days now with no reported errors.
It seems that in certain circumstances an old connection will be reused, and it will not be validated (or checked for being alive).
The following conditions are required for the error to occur : 1. An object is cached (it will only happen with a long term cache - eg ObjectCacheDefaultImpl) 2. The object has been cached for long enough for the database connection that was used to load it has expired 3. The object was loaded from outside a transaction (or possibly also inside a very long living transaction) 4. A collection proxy (not sure if it affects other proxies) is materialised from within this object
What seems to happen, is the connection which was used to load the object is held onto, and when the collection is materialised it reuses this stale connection and crashes out. It might also be caused if it has already been materialised and refresh=true - not sure how that works though.
This bug will only affect people using OJB in accordance with the above criteria. ObjectCachePerBrokerImpl shouldn't be affected. Also the bug wont apply if using transactions - as when it is closed it drops the connection.
The solution is in ConnectionManagerImpl.getConnection method. The code is already there, but commented out:
// if (con == null || !isAlive(con)) // isAlive check, how do we react if false and we in tx? // create a new connection isn't the right way I think. if (con == null)
I think this code should be applied - or at the very least, should be modified and applied if not inside a transaction:
if (con == null || (!isInLocalTransaction() && !isAlive(con)) )
Daniel.
-----Original Message----- From: Daniel Perry [mailto:[EMAIL PROTECTED] Sent: 02 November 2004 11:14 To: OJB Users List Subject: RE: SQLExcpetion
Once again our app has started getting these errors (see trace below). It seems to be happening after several days of operation.
The problem always seems to happen when iterating over a proxied collection in a jsp (using jakarta JSTL c:forEach tag).
See comments below:
Is the error always caused by the same class
>>>>at >>>>org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForE >>> >>>achIterator
or always caused when materialized a proxied collection?
Yes it's caused by that same class, but not always from the same jsp.
But it's also always when proxied collections are materialised.
Does the error occur when OJB materialize a class with clob/blob or binary/object field?
Dont think so.
Is there a way for me to clear the connection pool?
You can try ConnectionFactoryFactory.createConnectionFactory().releaseAllResources() CFF is a singleton. This call clear the used pool and close all connections of the pool (connections in use will be ignored AFAIK)
Or extend ConnectionFactoryPooledImpl and add your own
monitoring methods.
I've tried clearing the connection pool every hour, so the connections should be fine. I havnt tried clearing the cache...
How are connections obtained when cached objects have their proxied collections materialised? (note no transactions are being used)
I think an object is being loaded, and stuck in the cache. Days later the object is being used and is having a proxied collection materialised, and this is using the origional connection.
From what i can see in the code, a collection proxy obtains a broker, the broker obtains a connection - but (and i might have got the code wrong here) it should reuse the broker it used when it was initally loaded, and then the broker reuses the conenction without checking it isnt closed : ConnectionManagerImpl.getConnection
// if (con == null || !isAlive(con)) // isAlive check, how do we react if false and we in tx? // create a new connection isn't the right way I think. if (con == null)
This only checks if it has a connection, not if the connection is valid. Maybe i should reinstate the (con == null || !isAlive(con)) ???
Could this be the cause of my problem? or am i way off track!
Daniel.
Stack trace:
org.apache.jasper.JasperException: org.apache.ojb.broker.PersistenceBrokerException: org.apache.ojb.broker.PersistenceBrokerSQLException: java.sql.SQLException: No operations allowed after connection closed.
Connection was closed due to the following exception:
** BEGIN NESTED EXCEPTION **
java.sql.SQLException MESSAGE: Communication link failure: java.io.IOException, underlying cause: Unexpected end of input stream
** BEGIN NESTED EXCEPTION **
java.io.IOException MESSAGE: Unexpected end of input stream
STACKTRACE:
java.io.IOException: Unexpected end of input stream at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:1455) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1826) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1098) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1192) at com.mysql.jdbc.Connection.execSQL(Connection.java:2051) at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1496) at org.apache.ojb.broker.accesslayer.JdbcAccessImpl.executeQuery(Unknown Source) at org.apache.ojb.broker.accesslayer.RsQueryObject.performQuery(Unkno wn Source) at org.apache.ojb.broker.accesslayer.RsIterator.<init>(Unknown Source) at org.apache.ojb.broker.core.RsIteratorFactoryImpl.createRsIterator(Unknown Source) at org.apache.ojb.broker.core.PersistenceBrokerImpl.getRsIteratorFrom Query(Unkn own Source) at org.apache.ojb.broker.core.PersistenceBrokerImpl.getIteratorFromQu ery(Unknow n Source) at org.apache.ojb.broker.core.QueryReferenceBroker.getCollectionByQue ry(Unknown Source) at org.apache.ojb.broker.core.QueryReferenceBroker.getCollectionByQue ry(Unknown Source) at org.apache.ojb.broker.core.PersistenceBrokerImpl.getCollectionByQu ery(Unknow n Source) at org.apache.ojb.broker.core.DelegatingPersistenceBroker.getCollecti onByQuery( Unknown Source) at org.apache.ojb.broker.core.DelegatingPersistenceBroker.getCollecti onByQuery( Unknown Source) at org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.loadDa ta(Unknown Source) at org.apache.ojb.broker.core.proxy.ListProxyDefaultImpl.loadData(Unknown Source) at org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.getDat a(Unknown Source) at org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl.iterat or(Unknown Source) at org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForEa chIterator (ForEachSupport.java:329) at org.apache.taglibs.standard.tag.common.core.ForEachSupport.support edTypeForE achIterator(ForEachSupport.java:205) at org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare (ForEachSu pport.java:137) at javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSuppo rt.java:22 7) at org.apache.jsp.WEB_002dINF.jsps.manager.behavioursscreen.appraisal _jsp._jspx _meth_c_forEach_0(appraisal_jsp.java:294) at org.apache.jsp.WEB_002dINF.jsps.manager.behavioursscreen.appraisal _jsp._jspS ervice(appraisal_jsp.java:186) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94) at javax.servlet.http.HttpServlet.service(HttpServlet.java:810) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrap per.java:2 98) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236) at javax.servlet.http.HttpServlet.service(HttpServlet.java:810) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(A pplication FilterChain.java:237) at org.apache.catalina.core.ApplicationFilterChain.doFilter(Applicati onFilterCh ain.java:157) at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationD ispatcher. java:703) at org.apache.catalina.core.ApplicationDispatcher.processRequest(Appl icationDis patcher.java:463) at org.apache.catalina.core.ApplicationDispatcher.doForward(Applicati onDispatch er.java:398) at org.apache.catalina.core.ApplicationDispatcher.forward(Application Dispatcher .java:312) at org.apache.struts.action.RequestProcessor.doForward(RequestProcess or.java:10 56) at org.apache.struts.action.RequestProcessor.processForwardConfig(Req uestProces sor.java:388) at org.apache.struts.action.RequestProcessor.process(RequestProcessor .java:231) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1158) at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:397) at javax.servlet.http.HttpServlet.service(HttpServlet.java:697) at javax.servlet.http.HttpServlet.service(HttpServlet.java:810) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(A pplication FilterChain.java:237) at org.apache.catalina.core.ApplicationFilterChain.doFilter(Applicati onFilterCh ain.java:157) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapp erValve.ja va:214) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardV alveContex t.java:104) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline. java:520) at org.apache.catalina.core.StandardContextValve.invokeInternal(Stand ardContext Valve.java:198) at org.apache.catalina.core.StandardContextValve.invoke(StandardConte xtValve.ja va:152) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardV alveContex t.java:104) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline. java:520) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValv e.java:137 ) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardV alveContex t.java:104) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValv e.java:117 ) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardV alveContex t.java:102) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline. java:520) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngine Valve.java :109) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardV alveContex t.java:104) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline. java:520) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929) at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160) at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:296) at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:372) at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:694) at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket .java:626) at org.apache.jk.common.SocketConnection.runIt(ChannelSocket.java:807) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(Thre adPool.jav a:644) at java.lang.Thread.run(Thread.java:534)
** END NESTED EXCEPTION **
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
