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

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
> 
> 
> -----Original Message-----
> From: eclipselink-users-bounces@xxxxxxxxxxx
> [mailto:eclipselink-users-bounces@xxxxxxxxxxx] On Behalf Of James
> Sutherland
> Sent: Tuesday, February 17, 2009 07:29
> To: eclipselink-users@xxxxxxxxxxx
> Subject: Re: [eclipselink-users] session handling for multi-threaded fat
> client
> 
> 
> If you use the same DatabaseSession for both threads, then they will be
> sharing eachothers uncommitted data, and potentially committing/rolling
> back
> each others changes (regardless of whether you make commit()
> synchronized). 
> This is probably not good, but it depends on what the background thread is
> doing exactly?  Is it read-only, what is it doing?
> 
> It is possible to create a ServerSession with a single connection
> (although
> this may not be a good idea).  Just set the ServerSession
> readConnectionPool
> and default writeConnectionPool to the same ConnectionPool objects that
> has
> a single connection.  This however will require that one thread wait for
> the
> other to finish using its connection before it can use it (query or
> commit).
> 
> i.e.
> serverSession.setReadConnectionPool(serverSession.getDefaultConnectionPool()
> );
> 
> 
> Anthony Oganesian wrote:
>> 
>> Dear all,
>> 
>> I have the following problem and would greatly appreciate any feedback to
>> my
>> proposed solutions. I am leaning towards "Solution 2" but possibly there
>> is
>> another easier way?
>> 
>> Thanks a lot in advance!
>> 
>> --
>> Tony 
>> 
>> == Problem description ==
>>  * Two-tiered (fat client) application with heavy DB access on the main
>> UI
>> thread. 
>>  * Application has a low-priority background thread which needs DB access
>> as
>> well
>> 
>> My current approach to providing DB access in the code follows and is
>> incorrect:
>>  * Once during application startup I create a DatabaseSession and keep it
>> as
>> a static variable in my utility class (ApplicationDataConnector). 
>>  * Anywhere in the application I access this session via getSession()
>> method
>> which results in different threads accessing the same session possibly at
>> the same time. (I did get a ConcurrentModificationException just by
>> calling
>> readAllObjects())
>> 
>> class ApplicationDataConnector
>> {
>>     private static Session globalSession;
>> 
>>     public static init()
>>     {
>>         globalSession = project.createDatabaseSession();
>>     }
>> 
>>     public static Session getSession()
>>     {
>>         return globalSession;
>>     }
>> }
>> 
>> == Possible Solution 1 ==
>> Create a ServerSession and provide ClientSession instances upon request.
>> Unfortunately I was not able to configure the ServerSession to only open
>> one
>> connection. It insists on creating a readOnlyPool in addition to a
>> regular
>> pool and at a minimum creates 2 connections to the DB. In my case this
>> defeats the purpose as I could have just as well allocated a separate
>> connection to my background thread. Maintaining 2 connections is not an
>> option in my opinion. Any help here is appreciated. Maybe there is a way
>> to
>> limit a ServerSession to one connection?  
>> 
>> class ApplicationDataConnector
>> {
>>     private static ServerSession globalSession;
>> 
>>     public static init()
>>     {
>>         globalSession = project.createServerSession();
>>     }
>> 
>>     public static Session getSession()
>>     {
>>         return globalSession.acquireClientSession();
>>     }
>> }
>> 
>> == Possible Solution 2 ==
>> Extend a DatabaseSessionImpl and manually perform synchronization, which
>> should not be a bottle-neck in my scenario.
>> For the UnitOfWork I had to copy the acquireNonSynchronizedUnitOfWork
>> method
>> to inject my UnitofWork extension.
>> I really need some feedback in this scenario. Is it a good idea? Any
>> problems I am missing?
>> 
>>   
>> class ApplicationDataConnector
>> {
>>     private static SynchronizedSession globalSession;
>> 
>>     public static init()
>>     {
>>         globalSession = new SynchronizedSession(project);
>>     }
>> 
>>     public static Session getSession()
>>     {
>>         return globalSession
>>     }
>> }
>> 
>>     public static class SynchronizedSession extends DatabaseSessionImpl
>>     {
>>         public UnitOfWorkImpl
>> acquireNonSynchronizedUnitOfWork(ReferenceMode
>> referenceMode) {
>>             setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() +
>> 1);
>>             UnitOfWorkImpl unitOfWork = new UnitOfWorkImpl(this,
>> referenceMode)
>>             {
>>                 public void commit() throws DatabaseException,
>> OptimisticLockException
>>                 {
>>                     synchronized(SynchronizedSession.class)
>>                     {
>>                         super.commit();    
>>                     }
>>                 }
>> 
>>                 // Override and "synchronize" more UnitOfWorkImpl methods
>> as
>> needed
>>             };
>>             if (shouldLog(SessionLog.FINER, SessionLog.TRANSACTION)) {
>>                 log(SessionLog.FINER, SessionLog.TRANSACTION,
>> "acquire_unit_of_work_with_argument",
>> String.valueOf(System.identityHashCode(unitOfWork)));
>>             }
>>             return unitOfWork;
>>         }
>> 
>>         public synchronized Vector readAllObjects(Class domainClass,
>> Expression selectionCriteria) throws DatabaseException
>>         {
>>             return readAllObjects(domainClass, selectionCriteria);
>>         }
>> 
>>         public synchronized Object executeQuery(DatabaseQuery query)
>> throws
>> EclipseLinkException
>>         {
>>             return executeQuery(query);
>>         }
>> 
>>         // Override and "synchronize" more methods as needed
>> 
>>     }
>> 
>>
> 
> 


-----
---
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-tp22031861p22078639.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top