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,

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
> 
> 




Back to the top