Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [eclipselink-users] session handling for multi-threaded fat client

James,

Thank you very much for looking into this issue. I wanted to report back and let you 
know that both methods (ServerSession with your hint on how to limit it to a single 
connection) and my SynchronizedSession hack worked well in production (providing 
similar performance) We will be using SynchronizedSession approach for now until we 
migrate the legacy code and then move to the ServerSession with a single connection
approach as more clean and supportable in the future.

Thanks again!
--
Tony.

-----Original Message-----
From: eclipselink-users-bounces@xxxxxxxxxxx [mailto:eclipselink-users-bounces@xxxxxxxxxxx] On Behalf Of James Sutherland
Sent: Monday, February 23, 2009 04:46
To: eclipselink-users@xxxxxxxxxxx
Subject: RE: [eclipselink-users] session handling for multi-threaded fat client


I see, you are using batch writing, and the background thread is trying to
flush the other threads batch.  I suppose this is why it is best to use a
ServerSession.

If you called beginTransaction() and commitTransaction() around each query
from your background thread, this should remove this issue.  But still
better to use a ServerSession.



Anthony Oganesian wrote:
> 
> James,
> 
> In the stack trace below you can see how 2 threads work in parallel. 
> I put a "U" at the start of the line for UI lines and "B" for 
> background lines.
> 
> I can consistently reproduce this by setting the frequency of 
> my background thread to 0.5 second and just putting a simple 
> ReadAllQuery in a loop in the main UI thread. I tested both solutions: 
> my SynchronizedSession and ServerSession with one connection (per your 
> recommendation). Both perform well under this kind of stress test. 
> The only drawback to using the ServerSession/ClientSession that I can see 
> is that I loose session.writeObject(), session.insertObject() convenience 
> methods which are sometimes used in my legacy code which I am reluctant to 
> refactor at the moment.
> 
> - The exception appears in the EL code. Something to do with the batching?
> - I am using JTDS driver for MS SQL database
> 
> Thank you very much!
> --
> Tony
> 
> 
> U[EL Finest]: 2009.02.12
> 12:21:03.173--DatabaseSessionImpl(1553074)--Thread(Thread[main,5,main])--Exe
> cute query
> ReadAllQuery(com.ligolab.application.domain.diagnosis.DiagnosisGroup)
> B[EL Finer]: 2009.02.12
> 12:21:03.174--DatabaseSessionImpl(1553074)--Connection(19220932)--Thread(Thr
> ead[main,5,main])--Begin batch statements
> B[EL Fine]: 2009.02.12
> 12:21:03.174--DatabaseSessionImpl(1553074)--Connection(19220932)--Thread(Thr
> ead[main,5,main])--UPDATE SECURITY_APPLICATION_STATUS SET
> LAST_HEARTBEAT_TIME = {ts '2009-02-12 B12:22:14.303'} WHERE
> ((APPLICATION_ID
> = 0) AND (WORKSTATION_ID = 96))
> B[EL Finer]: 2009.02.12
> 12:21:03.174--DatabaseSessionImpl(1553074)--Connection(19220932)--Thread(Thr
> ead[main,5,main])--End Batch Statements
> B[EL Finer]: 2009.02.12
> 12:21:03.200--DatabaseSessionImpl(1553074)--Connection(19220932)--Thread(Thr
> ead[Application Management Thread,1,main])--commit transaction
> B[EL Finer]: 2009.02.12
> 12:21:03.287--UnitOfWork(11369856)--Thread(Thread[Application Management
> Thread,1,main])--end unit of work commit
> B[EL Finer]: 2009.02.12
> 12:21:03.287--UnitOfWork(11369856)--Thread(Thread[Application Management
> Thread,1,main])--release unit of work
> U[EL Warning]: 2009.02.12
> 12:21:03.287--DatabaseSessionImpl(1553074)--Thread(Thread[main,5,main])--jav
> a.util.ConcurrentModificationException
> 	at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
> 	at java.util.AbstractList$Itr.next(Unknown Source)
> 	at
> org.eclipse.persistence.internal.databaseaccess.DynamicSQLBatchWritingMechan
> ism.prepareJDK12BatchStatement(DynamicSQLBatchWritingMechanism.java:206)
> 	at
> org.eclipse.persistence.internal.databaseaccess.DynamicSQLBatchWritingMechan
> ism.executeBatchedStatements(DynamicSQLBatchWritingMechanism.java:123)
> 	at
> org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecut
> eCall(DatabaseAccessor.java:539)
> 	at
> org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall
> (DatabaseAccessor.java:500)
> 	at
> org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(Abstra
> ctSession.java:855)
> 	at
> org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.execut
> eCall(DatasourceCallQueryMechanism.java:204)
> 	at
> org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.execut
> eCall(DatasourceCallQueryMechanism.java:190)
> 	at
> org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.execut
> eSelectCall(DatasourceCallQueryMechanism.java:261)
> 	at
> org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.select
> AllRows(DatasourceCallQueryMechanism.java:594)
> 	at
> org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllR
> owsFromTable(ExpressionQueryMechanism.java:2506)
> 	at
> org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllR
> ows(ExpressionQueryMechanism.java:2464)
> 	at
> org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(Rea
> dAllQuery.java:478)
> 	at
> org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(Ob
> jectLevelReadQuery.java:879)
> 	at
> org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:666
> )
> 	at
> org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelRead
> Query.java:840)
> 	at
> org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:456)
> 	at
> org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQue
> ry(AbstractSession.java:2207)
> 	at
> org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(Abstr
> actSession.java:1178)
> 	at
> org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(Abstr
> actSession.java:1162)
> 	at
> org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(Abstr
> actSession.java:1108)
> 	at
> org.eclipse.persistence.internal.sessions.AbstractSession.readAllObjects(Abs
> tractSession.java:2494)
> 	at
> com.ligolab.application.ligolab.main.LigoLabInitializer.initApplicationEntit
> iesFromDB(LigoLabInitializer.java:145)
> 
> 
> -----Original Message-----
> From: eclipselink-users-bounces@xxxxxxxxxxx
> [mailto:eclipselink-users-bounces@xxxxxxxxxxx] On Behalf Of James
> Sutherland
> Sent: Wednesday, February 18, 2009 05:25
> To: eclipselink-users@xxxxxxxxxxx
> Subject: RE: [eclipselink-users] session handling for multi-threaded fat
> client
> 
> 
> If each thread has its own UnitOfWork to isolate its changes then you
> should
> be ok.  The database commit is already synchronized through the
> DatabaseSession's transaction mutex, so you should not need to do anything
> special.  Even without the UnitOfWork I can't see how you could have got a
> ConcurrentModificationException, please include the stack trace for this,
> was it in EclipseLink code, your JDBC driver or your application code?
> 
> The main benefit of using the ServerSession over the DatabaseSession is
> that
> the JDBC connections are used exclusively, where as the DatabaseSession
> will
> allow concurrent reads on the same JDBC connection (but not concurrent
> writes), depending on your JDBC driver it may not allow concurrent reads
> on
> the same connection.  You could use an external connection pool with a
> DatabaseSession to prevent concurrent reads.
> 
> 
> 
> Anthony Oganesian wrote:
>> 
>> James,
>> 
>> Thank you very much for looking into this! 
>> 
>> My background thread is reading and writing to the DB, but is using a
>> completely separate set of tables. 
>> But in theory let's say that was not the case. All my DB updates are
>> handled
>> through a UnitOfWork, 
>> is that not sufficient to protect threads from committing/rolling back
>> each
>> others changes?
>> I am curious because one other suggestion I got from a forum was to do
>> all
>> my reads and writes through a 
>> UnitOfWork to allow multiple threads to work with the same
>> DatabaseSession. 
>> 
>> In my stress test it seems that my home-brewed synchronization works for
>> me,
>> but the single-connection
>> ServerSession seems a more proper way of accomplishing the same thing,
>> and
>> yes I am OK with one thread waiting 
>> For the other to finish. (my background thread is a very low-volume once
>> every 15 minute operation)
>> 
>> Also, there was a mistake in my original post:
>> synchronized(SynchronizedSession.this) is needed to 
>> Synchronize UnitOfWork commits with session's synchronized methods.
>> 
>>> public void commit() throws DatabaseException, OptimisticLockException
>>> {
>>> 	synchronized(SynchronizedSession.this)
>>>     {
>>>      super.commit();    
>>>     }
>>>}
>> 
>> --
>> Tony
>> 
>> 
> 
> 
> _______________________________________________
> eclipselink-users mailing list
> eclipselink-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
> 
> 


-----
---
http://wiki.eclipse.org/User:James.sutherland.oracle.com James Sutherland 
http://www.eclipse.org/eclipselink/
 EclipseLink ,  http://www.oracle.com/technology/products/ias/toplink/
TopLink 
Wiki:  http://wiki.eclipse.org/EclipseLink EclipseLink , 
http://wiki.oracle.com/page/TopLink TopLink 
Forums:  http://forums.oracle.com/forums/forum.jspa?forumID=48 TopLink , 
http://www.nabble.com/EclipseLink-f26430.html EclipseLink 
Book:  http://en.wikibooks.org/wiki/Java_Persistence Java Persistence 
-- 
View this message in context: http://www.nabble.com/session-handling-for-multi-threaded-fat-client-tp22031861p22160864.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.

_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users



Back to the top