Twig + Guice - Detected use by more than one thread

98 views
Skip to first unread message

Sébastien Tromp

unread,
Mar 10, 2012, 5:40:34 AM3/10/12
to twig-p...@googlegroups.com
Hello,

I am using twig (built from trunk) and guice 3.0 (not sure my issue is linked with Guice though).

All my accesses to the datastore (via AnnotationObjectDatastore.load) fail with the exception raised in StandardFindCommand:

java.lang.IllegalStateException: Dectected use by more than one thread
at com.google.code.twig.standard.StandardCommand.<init>(StandardCommand.java:12)
at com.google.code.twig.standard.StandardFindCommand.<init>(StandardFindCommand.java:9)
at com.google.code.twig.standard.TranslatorObjectDatastore.find(TranslatorObjectDatastore.java:142)
at com.google.code.twig.standard.TranslatorObjectDatastore.find(TranslatorObjectDatastore.java:47)
        ...

I have configured my datastore in Guice as:

        binder.bind(ObjectDatastore.class).to(AnnotationObjectDatastore.class);

(I tried to bind it both as Singleton and not, and the issue appears in both cases).

For info, using debug, the datastore.thread is a simple Thread object (id=1, so I assume it is the thread used when Guice initializes everything), while Thread.currentThread() is a QueuedThreadPool$PoolThread (id 38). 

I have in fact two questions:
- Do you have an idea if I'm doing something wrong? Is the issue totally outside of twig?
- Why do we need to have the same thread?

Thanks for any help.

Cheers :-)
Seb

John Patterson

unread,
Mar 10, 2012, 6:39:42 AM3/10/12
to twig-p...@googlegroups.com
On 10/03/2012, at 5:40 PM, Sébastien Tromp wrote:

Hello,

I am using twig (built from trunk) and guice 3.0 (not sure my issue is linked with Guice though).

All my accesses to the datastore (via AnnotationObjectDatastore.load) fail with the exception raised in StandardFindCommand:

java.lang.IllegalStateException: Dectected use by more than one thread

An ObjectDatastore is not thread safe because it contains state that changes during a query.  This exception is a sanity check to ensure you don't reuse one

The main reason it is not possible to reuse an OD is because each contains "session data" which could become inconsistent with the datastore.  For example, if one thread modifies an object instance (that is shared between all threads) but does not commit the change to the datastore (maybe due to an error) then the state in memory is inconsistent.



I have configured my datastore in Guice as:

        binder.bind(ObjectDatastore.class).to(AnnotationObjectDatastore.class);

(I tried to bind it both as Singleton and not, and the issue appears in both cases).

Are you injecting into a Servlet?  If so then you should instead inject Provider<ObjectDatastore> so you get a new instance for each request.

For info, using debug, the datastore.thread is a simple Thread object (id=1, so I assume it is the thread used when Guice initializes everything), while Thread.currentThread() is a QueuedThreadPool$PoolThread (id 38). 

I have in fact two questions:
- Do you have an idea if I'm doing something wrong? Is the issue totally outside of twig?
- Why do we need to have the same thread?


A new ObjectDatastore is very cheap to create (relative to a datastore call) so there is almost no advantage to caching one as a singleton for performance.  

For data isolation you really need to read from the datastore for every request.  If you have objects that never really change much or the data does not need to be fresh then perhaps you could cache them directly in memory (a static variable) or in memcache.

The changes I use locally have added the ability to cache entity data in memcache or memory (not hydrated object instances, but the entity data that is used to populate them).  I'll try to commit them soon…. but they need a little bit of cleaning up.


Sébastien Tromp

unread,
Mar 10, 2012, 8:07:31 AM3/10/12
to twig-p...@googlegroups.com
On Sat, Mar 10, 2012 at 12:39 PM, John Patterson <jdpat...@gmail.com> wrote:
An ObjectDatastore is not thread safe because it contains state that changes during a query.  This exception is a sanity check to ensure you don't reuse one

The main reason it is not possible to reuse an OD is because each contains "session data" which could become inconsistent with the datastore.  For example, if one thread modifies an object instance (that is shared between all threads) but does not commit the change to the datastore (maybe due to an error) then the state in memory is inconsistent.

Thanks for the explanation.  
I have configured my datastore in Guice as:

        binder.bind(ObjectDatastore.class).to(AnnotationObjectDatastore.class);

(I tried to bind it both as Singleton and not, and the issue appears in both cases).

Are you injecting into a Servlet?  If so then you should instead inject Provider<ObjectDatastore> so you get a new instance for each request.

I'm injecting into a DAO that is injected in a Servlet, so yes. Injecting the Provider in my DAO, and calling provider.get() on each request works properly. 

A new ObjectDatastore is very cheap to create (relative to a datastore call) so there is almost no advantage to caching one as a singleton for performance.  

All the information and help you gave me is very valuable, and would be worth being found directly in the documentation somewhere.
Would you mind if I create a wiki page somewhere (or append to an existing page) about "common errors" to integrate what you just answered in the email? 

And possibly also detail more the comments on StandardCommand (that throws the exception) to explain why we check we have the same thread?

Thanks again for your quick answer!

Cheers :-)
Seb

Dirk Vranckaert

unread,
Jan 8, 2013, 11:02:25 AM1/8/13
to twig-p...@googlegroups.com
I'm doing the same you to avoid the problem, and it works fine as long as I avoid transactions.
Once I start using a transaction the second time I want to access the servlet I have the thread exception...

DO you also have this problem?

Maybe it's a good idea to share Twig + Guice setup (or at least a good document) somewhere...

Op zaterdag 10 maart 2012 14:07:31 UTC+1 schreef Sébastien Tromp het volgende:

John Patterson

unread,
Jan 8, 2013, 1:03:04 PM1/8/13
to twig-p...@googlegroups.com

On 9/01/2013, at 5:02 AM, Dirk Vranckaert wrote:

> I'm doing the same you to avoid the problem, and it works fine as long as I avoid transactions.
> Once I start using a transaction the second time I want to access the servlet I have the thread exception...
>
> DO you also have this problem?
>
> Maybe it's a good idea to share Twig + Guice setup (or at least a good document) somewhere…

I would love to make some example projects including a web stack, Guice, i18n, and e.g. Facebook integration. I hope to get some time for this soon.

Dirk Vranckaert

unread,
Jan 9, 2013, 4:30:23 AM1/9/13
to twig-p...@googlegroups.com
Allright cool, would be nice :-)

Op dinsdag 8 januari 2013 19:03:04 UTC+1 schreef John Patterson het volgende:
Reply all
Reply to author
Forward
0 new messages