Warp persist+JPA / UOW and "caching"

8 views
Skip to first unread message

ninomartinez

unread,
Jul 9, 2009, 1:11:26 PM7/9/09
to warp-core
Hi

I have a problem where warp persist seems to hold/cache stale data.
Now our use case are something like this:

User on the web browses around looking at entities
Mean while the database are being changed directly from sql command
line not via the web app.
User still sees the old data/entities.

Using plain JPA I usually solve something like this by setting the
persistence to Transaction level Persistence Context. However it's
mentioned on the documentation that Warp are using extended
persistence context.

How can I make sure that warp persist check's the database for
changes? Or am wrong in something?



http://www.wideplay.com/webextensions%3A%3Ajpaintegration

Best regards

ninomartinez

unread,
Jul 9, 2009, 1:29:12 PM7/9/09
to warp-core
I have some further information. We are using warp persist 1.0, and do
only specify the com.wideplay.warp.servlet.WebFilter filter...

Dhanji R. Prasanna

unread,
Jul 9, 2009, 7:34:28 PM7/9/09
to warp...@googlegroups.com
This is a problem outside warp-persist. You can set UOW to TRANSACTION and that is the equivalent of a transaction level persistence context in EJB. We don't really use the extended setting as it has little meaning outside an EJB container.

Dhanji.

nino martinez wael

unread,
Jul 10, 2009, 2:33:59 PM7/10/09
to warp...@googlegroups.com
Hi Dhanji

Very interesting .. So you are saying that the warp persist documentation are wrong? And we have set the UOW to transaction. If you need sample code or a demo project from me please say so.. So I guess what I am experiencing are actually not that the em are being destroyed around database transactions. If it were that data would be refreshed.

One thing to mention though are that we only read from the database, so we have not methods encapsulated with the transactional annotations. And another note would be that we are running on Jboss 4

Copied from the documentation about JPA and warp persist:

COPY START
.
.
.

Session-per-transaction strategy

This is a popular strategy, where an EntityManager is created and destroyed around each database transaction. Set the transaction-type attribute on your persistence unit's configuration:

 <persistence-unit name="myFirstJpaUnit" transaction-type="RESOURCE_LOCAL">
 

And change the PersistenceModule's configuration accordingly:

Injector injector = Guice.createInjector(..., PersistenceService
			.usingJpa()
			.across(UnitOfWork.TRANSACTION)
			.buildModule());
 
Note: this is the default UnitOfWork strategy even if unspecified (as in the earlier example). For advanced users, keep in mind that in warp-persist this strategy works a bit differently from Java EE container-managed EJBs and the PersistenceContextType setting for EntityManagers is always EXTENDED (not TRANSACTION as you may be led to think). You can safely ignore this in SE or servlet environments.
.
.
.
.
COPY END

2009/7/10 Dhanji R. Prasanna <dha...@gmail.com>

Dhanji R. Prasanna

unread,
Jul 10, 2009, 8:20:52 PM7/10/09
to warp...@googlegroups.com
On Sat, Jul 11, 2009 at 4:33 AM, nino martinez wael <nino.mart...@gmail.com> wrote:
Hi Dhanji

Very interesting .. So you are saying that the warp persist documentation are wrong?

 No, but it doesn't really apply unless you're using an appserver. Which I guess you are?

And we have set the UOW to transaction. If you need sample code or a demo project from me please say so.. So I guess what I am experiencing are actually not that the em are being destroyed around database transactions. If it were that data would be refreshed.

One thing to mention though are that we only read from the database, so we have not methods encapsulated with the transactional annotations. And another note would be that we are running on Jboss 4

Hmm, that's strange... this sounds like a hibernate setting. I think you need to fix it from the hibernate properties side. With UOW as TRANSACTION Warp-persist just assumes that hibernate will do the right thing and clean up the session at a commit boundary (the wp docs tell you what setting to use for this, I think it is session_context=thread or something like that).

You're not really using warp-persist if you dont have @Transactional methods (not much point without them).

I should probably clean up the documentation.

Dhanji.

nino martinez wael

unread,
Jul 11, 2009, 9:47:49 AM7/11/09
to warp...@googlegroups.com
Okay, we have also set (remember we are using JPA) :

<persistence-unit name="myFirstJpaUnit" transaction-type="RESOURCE_LOCAL">

The part that should tell hibernate via JPA to clean up stuff .. Or
should I specify this aswell, I never had todo so with spring:

hibernate.transaction.factory_class=org.hibernate.transaction.JDBCTransactionFactory
hibernate.current_session_context_class=thread

You are saying that Im not using warp persist if I do not have applied
@transactional on any methods. We only read from the database and make
no commits, so I dont see any idea in using @transactional.. In the
future we will probably need to commit to the database.
However we are using dynamic finders a LOT.

Im pretty clueless on howto fix this. I just want to say that I
appreciate the efforts behind warp persist.

regards Nino

2009/7/11 Dhanji R. Prasanna <dha...@gmail.com>

Robbie Vanbrabant

unread,
Jul 11, 2009, 3:37:14 PM7/11/09
to warp...@googlegroups.com
If you don't want to use @Transactional, you could switch to UnitOfWork.REQUEST if it fits your use case, otherwise you could consider using a custom unit of work as described here: http://www.wideplay.com/transactionsemantics (bottom of the page)

Non-transactional access is usually not what you want though, you'd have to be 100% sure nobody else is doing writes and you are only doing reads. My advice would be to use transactions even if you don't need them (yet). It has little performance impact and you'll sleep better.
If you use Hibernate (not JPA), there's even an experimental READ_ONLY mode for @Transactional.

Also note that the reason you have to configure Hibernate in a certain way is that WP is not really a persistence abstraction. It's just a library that tries to ease the integration of persistence in your Guice app. In theory, if you know Guice and Hibernate / JPA you're good to go. It's just that the docs are a bit confusing at the moment because the 1.0 docs are a bit outdated and the 2.0 docs aren't ready yet. And we thank you for pointing out the pain points :)

Hope this helps,
Robbie

nino martinez wael

unread,
Jul 13, 2009, 4:18:31 AM7/13/09
to warp...@googlegroups.com
Hi Robbie

Thanks for the reply.

2009/7/11 Robbie Vanbrabant <robbie.v...@gmail.com>

If you don't want to use @Transactional, you could switch to UnitOfWork.REQUEST if it fits your use case, otherwise you could consider using a custom unit of work as described here: http://www.wideplay.com/transactionsemantics (bottom of the page)
I've tried switching to Request. It's not that I dont want to use transactional but we just do not have any methods that writes. It's a read only configuration database. Hmm looking thru the code I noticed this:

    public void configure() {
        bindConstant().annotatedWith(JpaUnit.class).to(unit);
        bind(ReadOnlyAllInOneService.class).to(
                ReadOnlyAllInOneServiceDatabaseImpl.class).in(Singleton.class);

        bind(PersistenceInitializer.class).asEagerSingleton();
    }

Could all the fuss be that I bind our db service as Singleton, I guess I can bind it as session scoped? If so I really apologize :(



Non-transactional access is usually not what you want though, you'd have to be 100% sure nobody else is doing writes and you are only doing reads. My advice would be to use transactions even if you don't need them (yet). It has little performance impact and you'll sleep better.
If you use Hibernate (not JPA), there's even an experimental READ_ONLY mode for @Transactional.

Also note that the reason you have to configure Hibernate in a certain way is that WP is not really a persistence abstraction. It's just a library that tries to ease the integration of persistence in your Guice app. In theory, if you know Guice and Hibernate / JPA you're good to go. It's just that the docs are a bit confusing at the moment because the 1.0 docs are a bit outdated and the 2.0 docs aren't ready yet. And we thank you for pointing out the pain points :)
So could one use dynamic finders and "plain"  jpa/hibernate/guice?

nino martinez wael

unread,
Jul 13, 2009, 7:59:41 AM7/13/09
to warp...@googlegroups.com
hmm when I changed to session scoped this happened:

com.wideplay.warp.servlet.OutOfScopeException: Cannot access scoped object. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.wideplay.warp.servlet.WebFilter as a servlet filter for this request.
    at com.wideplay.warp.servlet.ContextManager.getContext(ContextManager.java:86)
    at com.wideplay.warp.servlet.ContextManager.getRequest(ContextManager.java:76)
    at com.wideplay.warp.servlet.Servlets$3$1.get(Servlets.java:101)
    at com.google.inject.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
    at com.google.inject.InjectorImpl$9$1.call(InjectorImpl.java:708)
    at com.google.inject.InjectorImpl.callInContext(InjectorImpl.java:747)

I have this in web.xml:
    <filter>
        <filter-name>guiceFilter</filter-name>
        <filter-class>com.wideplay.warp.servlet.WebFilter</filter-class>
    </filter>
    <listener>
        <listener-class>
            com.netdesign.modules.ServicesCreator
        </listener-class>
    </listener>
    <filter-mapping>
        <filter-name>guiceFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

And it comes after my struts servlet binding. Notice that I only have this in my injector:

                PersistenceService.usingJpa().across(UnitOfWork.REQUEST)
                        .forAll(Matchers.annotatedWith(Transactional.class),
                                Matchers.any()).buildModule(),

And not this one :
uice.createInjector(..., Servlets.configure()
			.filters()
			.buildModule(); 


2009/7/13 nino martinez wael <nino.mart...@gmail.com>

Dhanji R. Prasanna

unread,
Jul 13, 2009, 8:20:44 AM7/13/09
to warp...@googlegroups.com
On Mon, Jul 13, 2009 at 6:18 PM, nino martinez wael <nino.mart...@gmail.com> wrote:

If you don't want to use @Transactional, you could switch to UnitOfWork.REQUEST if it fits your use case, otherwise you could consider using a custom unit of work as described here: http://www.wideplay.com/transactionsemantics (bottom of the page)
I've tried switching to Request. It's not that I dont want to use transactional but we just do not have any methods that writes. It's a read only configuration database. Hmm looking thru the code I noticed this:

Btw you absolutely MUST do all reads inside a transaction. It is simply not possible in any other way. The hibernate docs and a lot of other systems will go into great detail about why. In fact, if you dont explicitly open one, many drivers will implicitly start a transaction when reading.

There's just no such thing as reading from a database outside a transaction (except auto-commit mode, and I hope you're not using that =).


    public void configure() {
        bindConstant().annotatedWith(JpaUnit.class).to(unit);
        bind(ReadOnlyAllInOneService.class).to(
                ReadOnlyAllInOneServiceDatabaseImpl.class).in(Singleton.class);

        bind(PersistenceInitializer.class).asEagerSingleton();
    }

Could all the fuss be that I bind our db service as Singleton, I guess I can bind it as session scoped? If so I really apologize :(

Ohh that count be it. singletons hold on to their state between requests. Try not binding it as anything. Or inject the EM as a Provider<EntityManager> and call get() from it in each of your methods before using it. This avoid the "caching"




Non-transactional access is usually not what you want though, you'd have to be 100% sure nobody else is doing writes and you are only doing reads. My advice would be to use transactions even if you don't need them (yet). It has little performance impact and you'll sleep better.
If you use Hibernate (not JPA), there's even an experimental READ_ONLY mode for @Transactional.

Also note that the reason you have to configure Hibernate in a certain way is that WP is not really a persistence abstraction. It's just a library that tries to ease the integration of persistence in your Guice app. In theory, if you know Guice and Hibernate / JPA you're good to go. It's just that the docs are a bit confusing at the moment because the 1.0 docs are a bit outdated and the 2.0 docs aren't ready yet. And we thank you for pointing out the pain points :)
So could one use dynamic finders and "plain"  jpa/hibernate/guice?

Absolutely, that is our primary use case.
HTH

Dhanji.

nino martinez wael

unread,
Jul 13, 2009, 9:34:38 AM7/13/09
to warp...@googlegroups.com
Thanks Dhanji!

The singleton scope seemed to be the cause of the problem. And actually it seems a logical cause..

Thanks for the help everyone :)


2009/7/13 Dhanji R. Prasanna <dha...@gmail.com>
Reply all
Reply to author
Forward
0 new messages