6 Replies Latest reply on Jan 21, 2010 2:14 AM by Nikolay Elenkov

    Performance Problems with EntityManager Instances

    Jonathan Clarke Newbie

      Everyone, I have a performance problem which I hope someone can help me with. The scenario is quite involved, so please bear with me.


      I have several threads of behaviour, each of which is controlled by a quartz job. Each thread can then have several objects of different class types, which are called in sequence, in order to achieve an end result. Some of those objects in the sequence need to perform database work, some do not. Of each of the objects that do, I wish to commit the work done to-date, so essentially a work-flow performed on the server-side.


      So, ordinarily, in a conversation with the user, I would inject the entitymanager into the parts that have database work, and Seam would handle the database states for me. However, on the server side, the objects in the sequence should intentially not have any knowledge of Seam, only an entitymanager. In order to achieve that work-flow database control, I am therefore creating an entitymanager for each one of those objects in the sequence, but it's a large performance hit to create one making the createentitymanagerfactory and then createentitymanager calls. I also don't want to pass a single entitymanager instance to all of the those objects in the sequence (for example, from the point at which the quartz job is created) because I don't know exactly what the sequence of objects is going to be until at run-time.


      So, my questions are: how can I either get at a single entitymanager from a pool somewhere that is nothing to do with the built in Seam pool used in the backing beans @In technique, or how can I speed up the createentitymanager process? Thanks in advance, and apologies for the length of the question!

        • 2. Re: Performance Problems with EntityManager Instances
          Jonathan Clarke Newbie

          Thanks for the swift response Nikolay. However, I thought that @PersistenceContext was used during conversations with a client browser session, rather than on the server side, especially as I will have multiple quartz jobs running at the same time, each requiring their own transactional session. That's why I thought I needed several entitymanager instances. I can find few examples of server side implementations that resemble my requirements. What I need is an independent transaction for each of the jobs that are running under quartz. I thought that @PersistenceContext would certainly handle the transactions during front-end conversations, but how do I tell Seam that each quartz job should be considered its own conversation?

          • 3. Re: Performance Problems with EntityManager Instances
            Jonathan Clarke Newbie

            Looking in the Seam documentation, it says A resource-local entity manager or an entity manager created with EntityManagerFactory.createEntityManager() (application-managed) has a one-to-one relationship with a persistence context. In other situations persistence context propagation occurs, which is exactly what I'm doing right now, but I'd like to reduce the performance overhead of having to create these entitymanagers all the time.

            • 4. Re: Performance Problems with EntityManager Instances
              Nikolay Elenkov Master

              Background jobs don't have access to the session or conversation. @PersistenceContext is transaction-bound, so you get a fresh instance with every transaction. If your Quartz jobs are EJB's, they will run in a transaction by default, each with its separate @PersitenceContext. If however on SLSB calls another, the two calls will be part of the same transactions. If you need them to be independent, use @TransactionalAttribute(REQUIRES_NEW).


              All of this, of course, assumes you are using EJB's.


              HTH

              • 5. Re: Performance Problems with EntityManager Instances
                Jonathan Clarke Newbie
                Almost all of my source from the invocation of the quartz job is based on POJOs, with no Seam @ augmentation (the client-facing aspects of the application do indeed use many of the Seam facilities, though). So, an example object (let's say of type 'A') may call the following initialise() code from its constructor:

                public class A {

                protected EntityManager fEntityManager;          

                protected void initialise() {
                   super.initialise();

                   EntityManagerFactory fEntityManagerFactory = Persistence.
                       createEntityManagerFactory("MyApp");          
                   fEntityManager = fEntityManagerFactory.createEntityManager();
                }

                public doResults() {

                   // Database persists.

                   fEntityManager.flush();
                }

                }

                The only Seam @ augmentation I use is from an object (Let's say of type 'Manager') that calls doResults() on each of the objects that need database work performed:

                @Name("manager")
                class Manager {

                @Transactional
                public void doDatabase(A aA) {
                   aA.doResults();
                }

                }

                • 6. Re: Performance Problems with EntityManager Instances
                  Nikolay Elenkov Master

                  If you can use EJB's, do. That would save you a lot of trouble, IMHO. If not use Seam's persistence context. (@In EntityManger) The real performance problem is the createEntityManagerFactory call, creating an EntityManager is not that expensive.