Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically started UnitOfWork is never ended #730

Closed
gissuebot opened this issue Jul 7, 2014 · 7 comments
Closed

Automatically started UnitOfWork is never ended #730

gissuebot opened this issue Jul 7, 2014 · 7 comments

Comments

@gissuebot
Copy link

From spootsy.ootsy on September 26, 2012 22:48:16

We've been using Guice in our projects for a while now, and it's been great. There's one feature/bug that is a reliable source of bugs for us, though.

When using the JpaPersistService, if you attempt to access an EntityManager outside of an active UnitOfWork, Guice will automatically start one for you. However, as Guice does not (and cannot) know when to end this UnitOfWork, it never does.

Result? The offending thread will be stuck with the same EntityManager throughout the life of the application. This is a bad state for the application to run in, and ours inevitably exhaust the available memory after a while and crash.

The real killer here is that it's not at all obvious when you've made this mistake. The only real tip-off is that you're getting inconsistent data from your database between different threads (due to the EMs first-level cache) or that the applications memory consumption keeps on growing.

I think it would be much better behaviour to simply throw an exception if an attempt is made to access an EntityManager instance outside of an active UnitOfWork. This lets the developer know that they've made a mistake and are attempting to access the database outside of a valid scope. Steps to reproduce: 1. 'mvn test' on the supplied maven project (assumes postgres running on localhost:5432 with DB/user/pass 'test')

Binary attachments: guice_persist_same_em.zip

Original issue: http://code.google.com/p/google-guice/issues/detail?id=730

@gissuebot
Copy link
Author

From spootsy.ootsy on October 10, 2012 16:44:26

I've created a git patch which addresses this issue, as well as issue 731 . Rundown of changes from the commit log:

  • JpaPersistService now counts invocations of begin() and end(), and only closes
      EntityManager when end() has been called an appropriate number of times
  • Attempting to get an EntityManager outside of an active UnitOfWork now results
      in an IllegalStateException
  • Added a new @WorkUnit annotation. This is equivalent to the @Transactional
      annotation for methods/classes which access the database but do not modify it

Patch also updates the appropriate unit tests.

Attachment: gist
   0001-Updates-to-JpaPersistService-implementation-of-UnitO.patch

@gissuebot
Copy link
Author

From prashant.mr on October 10, 2012 18:54:55

@WorkUnit annotation, is this similar to Spring's @Transactional(readOnly = true) http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/transaction.html#transaction-declarative-annotations http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/transaction/annotation/Transactional.html#readOnly() IMO, readOnly=true expresses the transaction's behavior clearly that the changes will not be committed.

@gissuebot
Copy link
Author

From spootsy.ootsy on October 10, 2012 20:11:22

@WorkUnit is just a shorthand means of using the UnitOfWork interface, by wrapping the annotated method with calls to uow.begin/uow.end in a try/finally block. No JPA transaction is explicitly started.

I think it's conceptually different from a read-only transaction. That would certainly make more sense as an additional attribute on the existing @Transactional annotation.

@gissuebot
Copy link
Author

From bimschas on August 22, 2013 14:38:05

Will this fix be part of Guice 4.0?

@gissuebot
Copy link
Author

From spootsy.ootsy on August 22, 2013 22:01:52

I was hoping they'd include a patch of some kind but I don't see any changes in trunk. It's a shame, because the current semantics of UnitOfWork are pretty badly broken IMHO.

Also, please note there's a significant bug in this patch, as discussed here: https://code.google.com/p/google-guice/issues/detail?id=731 It's a simple fix but I haven't got around to it yet. If anybody else has a vested interest you're more than welcome to fix it and post the updated patch here.

@gissuebot
Copy link
Author

From sberlin on December 20, 2013 06:17:02

(No comment was entered for this change.)

Labels: Component-Persist

@woru
Copy link

woru commented May 13, 2015

+1 IMHO this a serious bug. You forget to add @transactional and end up with OutOfMemoryError in production.
Also JpaPersistService is not public and cannot be overridden.

rauligs added a commit to alphagov/pay-connector that referenced this issue Oct 2, 2017
     - Add _@Transactional_ annotation to TransactionDao since this is
     causing issues, so PP-2515 can be added back:
         google/guice#730

     - Reinstante PP-2515 Implementation of `TransactionDao`

    The implementation of `TransactionDao` is meant to be used a as
    drop-in replacement for `ChargeDao` when we want to take refunds into
    consideration while searching.

      - A transaction can be of two types `charge` or `refund`. Depending
        on whether we want to search for only charges or refunds, an
        optional payment type can be specified in the filtering
        criteria. The absence of a payment type in the search criteria
        implies all types are considered during the search.
      - The filtering criteria has been augmented to allow searching by
        refund status or charge status or any combination of both.
      - Technical note: Performance being an overriding concern when
        searching for transactions, the underlying query required to be
        hand-optimized in order to get a decent execution plan out of a
        SQL UNION with pagination. Since JPA tend to get in the way
        because of its lack of support for UNION query, we were forced to
        resort to using a native query constructed dynamically with the
        support of jOOQ's query DSL API.
        https://www.jooq.org/doc/3.9/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder/
copybara-service bot pushed a commit that referenced this issue Apr 21, 2023
…because it leads to leaks. Fixes #739, fixes #997, fixes #730, fixes #985, fixes #959, fixes #731. This also adds an optional Options to the JpaPersistModule constructor, if users wish to use the legacy behavior. This is a breaking change, but to a better default value. Users who want to keep the dangerous form can opt back in with the options.

PiperOrigin-RevId: 525852009
copybara-service bot pushed a commit that referenced this issue Apr 21, 2023
…because it leads to leaks. Fixes #739, fixes #997, fixes #730, fixes #985, fixes #959, fixes #731. This also adds an optional Options to the JpaPersistModule constructor, if users wish to use the legacy behavior. This is a breaking change, but to a better default value. Users who want to keep the dangerous form can opt back in with the options.

PiperOrigin-RevId: 525852009
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment