5 Replies Latest reply on Sep 22, 2006 4:59 AM by andydale

    EntityManager not working correctly

    andydale

      Hi,

      I am currently experiencing some problems using the that JBoss 4.0.4GA persistence with postgres 8.1.4. I am having lots of trouble reading Entities back out of the database.

      The application works as follows, data is received and a new object (Entity) is created and then persisted from within a stateless session bean. The a message is sent to a Message Driven Bean where the entity is then attempted to be read out of the database (with EntityManager.find()) and this is where the problem is. Most of the time the find() method cannot find the Entity even though it has been persisted (verified persistence by viewing the table in pgAdmin) but now this is where it gets interesting, if you code the EntityManager.find() code as so

      <object> = EntityManager.find(<object>.class, Integer.valueof(pk))


      null is returned most of the time. But if you code the EntityManager.find() like below:


      <object> = EntityManager.find(<object>.class, Integer.valueof(pk))
      if(<object> == null){
       try{
       synchronized(this){
       wait(2000);
       }
       <object> = EntityManager.find(<object>.class, Integer.valueof(pk))
       }
       catch(InterruptedException e){
       e.printStackTrace();
       }
      }


      the object is always found on the second call of the find method. Has anybody else experienced this strange behaviour ????

      Another few things to note are that if i call the find method directly after persisting the Entity in the stateless session bean then is is always found, and in both beans the EntityManager is injected with the @PersistenceContext using the same persistence unit . Also note that the stateless session bean and the message driven bean are in different archives in a .ear file, would this make a difference ??

      Thanks,

      Andy

        • 1. Re: EntityManager not working correctly
          andydale

          Hi,

          After spending the whole week trying to fix this problem, i am still no closer to the actual solution but i have discovered some more information. This problem is Postgres specific at the moment as i have tested the EntityManager.find() method call in the same context when using Hypersonic and MySQL and the entity is always found.

          After studying the log file created by Postgres (without having the 2 second delay) it seems to not be able to commit the initiial insert statement generated from the EntityManager.persist() call before it tries to query it with the select statement, thus the .find() returns null. The thing that worries me about this problem is that some times it works with Postgres, and that it always works with the 2 other databases i tested with.

          I have read up on the EntityManager and discovered that it is not thread safe, could this be causing the problem with Postgres, if so i know i need to use an EntityManagerFactory as this is a thread safe object, but how do i just create on factory that the whole of the application can use (be used in different beans, possible JNDI lookup ??), and even then i do not know if this would solve my problem. Is there anyway of making the EntityManager.persist() method wait until the database has actually commited before it returns ??? I have also tried to introduce flush() calls but they do not solve the problem.

          Is this a possible bug in the EntityManager or Postgres JDBC code ???

          I also have a very simple test application (.ear file) that just persists some bytes to a database and then tries to find them again in a seperate MDB, and then prints out if it cannot find the persisted object. If anybody wants it to test the problem with this application i will make it available to them.


          If anyone can help, or offer advice it is appreciated.

          Cheers,

          Andy

          • 2. Re: EntityManager not working correctly
            andydale

            Yesterday we managed to get it working with pure JDBC without any problems. We then integrated the EntityManager with the JDBC statements, and we think the problem exists with the .persist() method. It seems as if it returns from the method without waiting for the commit to happen at the database level.

            Andy

            • 3. Re: EntityManager not working correctly
              kamra

              I m facing exactly the same problem with Oracle database too.
              EntityManager.find() method is not able to find the entity in the database.

              In the session bean before firing a message to a queue, I m persisting some data using EntityManager.persist() . and MDB on receiving the message, tries to fetch the data from the DB.

              Initially I doubted that, may be the entityManager.persist is not commiting the data into the DB. But then I put the code which persist the data in session bean in a new transaction, this transaction is done even before the session bean fires the message into the queue thus making sure that data is commited into the database. (Even checked manually that data is available in DB). But still EntityManager.find() is not able to find the data in the DB.


              This is how I m persisting the data

              @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
              private void updateTradeFormGenerationStatus(String tradeFormRequestID, String formID, String locale) {

              FormattedDocument fd = new FormattedDocument(tradeFormRequestID);
              fd.setAForm(formID);
              fd.setAFormLanguage(localeConvertor.getLanguage(locale));
              fd.setADocumentStatus(Constants.TRADEFORM_STATUS_PEN);

              em.persist(fd);
              em.flush();
              }


              Looks like this is a bug in the database connectivity implementation of JBoss 404GA.

              • 4. Re: EntityManager not working correctly
                kamra

                There is another intresting observation,
                If I use the createquery then I m able to find the record in the database, that is ..

                String query = "select e from FormattedDocumentETF e where e.uoid like '"+uoid+"'";
                FormattedDocumentETF result1 = (FormattedDocumentETF)em.createQuery(query).getSingleResult();
                result1.setADocumentStatus("GEN");
                em.merge(result1);

                But this also works for some of the entities. I try to use this approach in other entites, but it fails for some of them.

                • 5. Re: EntityManager not working correctly
                  andydale

                  Karma,

                  I found that annotating the class (where the data is persisted) with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) solved the problem for me, but unfortunately it does not seem to work for you. But after reading your post i have revisited the problem and removed the annotations and it still works !!! so i really don't know what the cause of problem was in the first place.

                  I would imagine that the underlying cause of the problem i had will be the same as the problem you are currently experiencing, namely that the em.persist() only triggers an update and does not wait for the transaction to commit, and i also found that trying em.flush() after had no effect at all. To see if that is the case turn on full database logging and you should see the insert, select, and then commit in that order.

                  The current program layout i have that is working is to have a top level method that calls 2 other methods. Method 1 is the presist data method and method 2 is the send message method. See below:

                  public void action(){
                  
                   int pk = 0;
                  
                   try{
                   pk = doPersistData();
                   }catch(Exception e){
                   e.printStackTrace();
                   }
                  
                   try{
                   // send a JMS message
                   doMessageStuff(pk);
                   }catch(Exception e){
                   e.printStackTrace();
                   }
                   }


                  The thread i also create about this on the hibernate website can be found here: http://forum.hibernate.org/viewtopic.php?t=962664&highlight=

                  Cheers,

                  Andy