Remove not working

#1

Hello!

We have a strange problem.

Caused by: com.objectdb.o._EntityNotFoundException: Entity is not found: ObjectManager of appnode1/127.0.0.1:6136 [2015-12-15 20:04:20 -> 2015-12-15 20:04:20] - 226 (removed in current transaction)
at com.objectdb.o.JPE.g(JPE.java:94)
at com.objectdb.o.ERR.f(ERR.java:56)
at com.objectdb.o.OBC.onObjectDBError(OBC.java:1503)
at com.objectdb.o.RSL.get(RSL.java:176)
at com.objectdb.o.LDR.H(LDR.java:680)
at com.objectdb.o.LDR.G(LDR.java:619)
at com.objectdb.o.LDR.E(LDR.java:472)
at com.objectdb.o.OBC.U0(OBC.java:1080)
at com.objectdb.o.QRR.h(QRR.java:297)
at com.objectdb.o.QRR.f(QRR.java:180)
at com.objectdb.o.QRR.a(QRR.java:618)
at com.objectdb.o.InvMemberQuery.e(InvMemberQuery.java:139)
at com.objectdb.o.UMR.v(UMR.java:508)
at com.objectdb.o.ENT.loadInverse(ENT.java:1485)
at com.objectdb.o.IVP.m(IVP.java:149)
at com.objectdb.o.IVP.l(IVP.java:137)
at com.objectdb.o.ILP.size(ILP.java:232)
at com.objectdb.o.CLT.visitRefs(CLT.java:156)
at com.objectdb.o.TVS.j(TVS.java:169)
at com.objectdb.o.TVS.cascade(TVS.java:156)
at com.objectdb.o.TVS.g(TVS.java:105)
at com.objectdb.o.TVS.g(TVS.java:93)
at com.objectdb.jpa.EMImpl.remove(EMImpl.java:464)

Newest version of ObjectDB. No errors if I run the doctor. I've reduced my testcase to this:

@Test
    @Transactional
    public void deleteUnitTest() throws NoResultException {
        Unit byName = unitDAO.findByName("6ff4b08a");
        em.remove(byName);
    }

The unit retrieval works but during commit the exception above get's thrown. The weird thing is that it works for some units and for some not.

Best Regards

Ralph

#2

The following test case demonstrates a similar exception:

import java.util.*;

import javax.persistence.*;

public class T1772 {
    public static void main(String[] args) {
        String url = "objectdb:$objectdb/db/test.tmp;drop";
        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory(url);

        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        B b = new B();
        b.a = new A();
        em.persist(b);
        em.persist(b.a);
        em.getTransaction().commit();
        em.close();
      
        em = emf.createEntityManager();
        em.getTransaction().begin();
        b = em.find(B.class, 1);
        em.remove(b);
        A a = em.find(A.class, 2);
        em.remove(a);
        em.getTransaction().commit();
        em.close();
      
        emf.close();
    }
  
    @Entity
    public static class A {
        @OneToMany(mappedBy="a", cascade=CascadeType.REMOVE)      
        private List<B> bs;
    }
  
    @Entity
    public static class B {
        private A a;
    }
}

The exception is thrown because the removal of A is cascaded to removal of a B instance that has already been removed earlier in the same transaction. No exception is thrown if em.flush() is invoked before em.remove(a);

Is it possible that you have a similar condition?

Build 2.6.4_10 includes an attempt to cancel the exception in this and similar cases.

ObjectDB Support
#3

I double and tripple checked that there are no already deleted objects in the graph to delete but it still didn't work. As you can see my testcase does nothing other than retrieving the object and removing it. No second remove in the same or any other transaction.
With you fix it of course works. Thank you!

#4

Thank you for the update. Good to hear that it works well now.

ObjectDB Support
#5

I came across a similar problem and I thought I would share it with everyone in case it helps someone else fix their issue.

 

I received this ObjectDB exception:  "com.objectdb.o._JdoObjectNotFoundException: Entity is not found: ObjectManager of com.objectdb.o.WSM@2a7d1a2b - 2 (removed in current transaction)".

 

It seems to happen because, in the same transaction, I gather an Extent, delete an object, then try to gather the same Extent again.  The Extent traversal throws the error because it encounters the object that was deleted.

The fix was to do a PersistenceManager.flush() before trying to gather the Extent the second time.

I did not think this would be required because I had PersistenceManager.ignoreCache=false.  I expected the second Extent gathering to notice that my transaction had deleted an object from the cache and it should therefore not include it in its list of objects.  Maybe it only does that for its iterator() object and perhaps does not respect the cache when using the Extent in a for-each statement.

 

transaction.begin

get Extent, traverse its entries, delete an object in there

// needs a flush() here else the next statement throws the Exception

get Extent, traverse its entries

transaction.end
#6

This is indeed unexpected, as every Extent iterator creation starts with invoking flush, if there are changes and ignoreCache is false. A for-each loop is actually implemented with the same iterator.

If you provide a test case that demonstrates this behaviour it will be fixed.

ObjectDB Support
#7

Hmm, let's start with this.  In my simple test I was creating, it seems that IgnoreCache setting was not respected.  Did I make a mistake, or is this configuration showing a true failure?

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import java.util.Properties;
public class Test{
    private static PersistenceManager persistenceManager;
    public static void main(String[] args) throws Exception{
        System.out.format("Running Test ...%n");
        openDatabase();
        System.out.format("ignoreCache is %b.%n", persistenceManager.getIgnoreCache());
        if(persistenceManager.getIgnoreCache()) throw new Exception("ignoreCache should be FALSE.");
        System.out.format("Test complete.%n");
    }
    private static void openDatabase(){
        Properties properties = new Properties();
        properties.setProperty("javax.jdo.PersistenceManagerFactoryClass", "com.objectdb.jdo.PMF");
        properties.setProperty("javax.jdo.option.Optimistic", "true");
        properties.setProperty("javax.jdo.option.RetainValues", "true");
        properties.setProperty("javax.jdo.option.RestoreValues", "false");
        properties.setProperty("javax.jdo.option.IgnoreCache", "false");
        properties.setProperty("javax.jdo.option.NontransactionalRead", "false");
        properties.setProperty("javax.jdo.option.NontransactionalWrite", "false");
        properties.setProperty("javax.jdo.option.Multithreaded", "true");
        properties.setProperty("javax.jdo.option.DetachAllOnCommit", "false");
        properties.setProperty("javax.jdo.option.CopyOnAttach", "false");
        properties.setProperty("javax.jdo.option.TransactionType", "RESOURCE_LOCAL");
        properties.setProperty("javax.jdo.option.TransactionIsolationLevel", "read-uncommitted");
        properties.setProperty("javax.jdo.option.ConnectionURL", "Test.odb;drop");
        PersistenceManagerFactory persistenceManagerFactory = JDOHelper.getPersistenceManagerFactory(properties);
        persistenceManager = persistenceManagerFactory.getPersistenceManager();
    }
}

The output from this code is:

Running Test ...
ignoreCache is true.
Exception in thread "main" java.lang.Exception: ignoreCache should be FALSE.
at Test.main(Test.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
#8

Ah, my problem above was using "Test.odb;drop" instead of "Test.tmp;drop".

I'll post a new test program.

 

#9

Looks like ignoreCache set to false is still ignored after the above fix.  So this would explain why the Extent appeared to fail on the second access (because it ignored the cache, like it was told to do).  If I manually set ignoreCache=false to correct the failure above, then the test succeeds.

#10

#11

The test program response is:

Running Test ...
ignoreCache is true.
Listing objects:
Object1, My data for Object1.
Object2, My data for Object2.
Listing objects:
Object1, My data for Object1.
Test complete.

Comment out this line:  if(persistenceManager.getIgnoreCache())persistenceManager.setIgnoreCache(false);

Then the test program response is:

Running Test ...
ignoreCache is true.
Exception in thread "main" java.lang.Exception: ignoreCache should be FALSE.
at Test.main(Test.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

 

#12

Build 2.9.6_06 fixes the issue of ignoring "javax.jdo.option.IgnoreCache".

Thank you for your report.

Since JDO is not commonly used these days, including with ObjectDB (maybe less than 5% of the active users), you may find other minor issues (at the wrapper level, as the ObjectDB engine is common to JDO and JPA).

Note that it is usually a bad idea to add posts to an old thread. The issue in the original post was already solved. All our new posts (starting #5) discuss a totally different issue (the "javax.jdo.option.IgnoreCache"), which is not related to the subject of this original post. It should have been discussed in a new thread.

Please see the posting instructions, which also explain the need to open new threads, the preferred format for posted test cases and the need to post a stack trace on an exception report. Thanks! 

ObjectDB Support
#13

Fix confirmed.  Thank you.

Reply