Home » Support » Forum » Field not persisted in abstract class with two level of nesting

Field not persisted in abstract class with two level of nesting

#1

Hi,

I have a field (embedded TZ1) which is not persisted in class MHD1 (TZ1  extends AS and AS extends ATT).

But it seems to work fine when I skip the AS and make TZ2 extend directly from ATT.

Here is an example code

MHD1

package BUG2;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;

@Entity
public class MHD1 implements Serializable{
    private TZ1 timezone;
    public MHD1() {
    }

    public MHD1(TZ1 timezone) {
        this.timezone = timezone;
    }

    public static void main(String[] args){
        EntityManager em = Persistence.createEntityManagerFactory("$objectdb/db/TEST1.odb").createEntityManager();
        em.getTransaction().begin();
        TZ1 tz = new TZ1("GMT");
        MHD1 MH = new MHD1(tz);
        em.persist(MH); 
        em.getTransaction().commit();
        em.clear();
    }
}

TZ1

package BUG2;

import javax.persistence.Embeddable;

@Embeddable
public class TZ1  extends AS<TZ1>{
    TZ1() {
    }
   
    public TZ1(String v) {
        super(v);
    }

    @Override
    public boolean equals(Object obj) {
        TZ1 x = (TZ1) obj;
        return (x.value == null ? value == null : x.value.equals(value));
    }

    @Override
    public int hashCode() {
        int hash = 7;
        return hash;
    }
}

AS

package BUG2;

import javax.persistence.Embeddable;

@Embeddable
abstract class AS<Type2> extends ATT<String, Type2>{    

    public AS(String s) {
        super(s);
    }
    public AS() {
        super();
    }
}

ATT

package BUG2;

import java.io.Serializable;
import javax.persistence.Embeddable;

@Embeddable
public abstract class ATT<Type1,Type2>   implements Serializable{
    Type1 value;

    public ATT(){
    }

    public ATT(Type1 value){
        this.value = value;
       
    }

   
}

and the classes for skipping the AS class

MHD2

package BUG2;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;

@Entity
public class MHD2 implements Serializable{
    private TZ2 timezone;
    public MHD2() {
    }

    public MHD2(TZ2 timezone) {
        this.timezone = timezone;
    }

    public static void main(String[] args){
       
        EntityManager em = Persistence.createEntityManagerFactory("$objectdb/db/TEST2.odb").createEntityManager();
        em.getTransaction().begin();
        TZ2 tz = new TZ2("GMT");
        MHD2 MH = new MHD2(tz);
        em.persist(MH); 
        em.getTransaction().commit();
        em.clear();
    }
}

and TZ2

package BUG2;

import javax.persistence.Embeddable;

@Embeddable
public class TZ2  extends ATT<String,TZ2>{
    TZ2() {
    }
   
    public TZ2(String v) {
        super(v);
    }

    @Override
    public boolean equals(Object obj) {
        TZ2 x = (TZ2) obj;
        return (x.value == null ? value == null : x.value.equals(value));
    }

    @Override
    public int hashCode() {
        int hash = 7;
        return hash;
    }
}

I tried to make as short as i could - but it looks like this problem is only happening when TZ1/ TZ2 classes are embedded - they are fine when they are entities - hence I needed the holders.

Here is the exception when I run MHD1

Exception in thread "main" [ObjectDB 2.5.6] javax.persistence.PersistenceException
Failed to generate dynamic type objectdb.BUG2.AS (error 361)
at com.objectdb.jpa.EMImpl.persist(EMImpl.java:445)
at BUG2.MHD1.main(MHD1.java:23)
Caused by: com.objectdb.o.UserException: Failed to generate dynamic type objectdb.BUG2.AS
at com.objectdb.o.MSG.d(MSG.java:74)
at com.objectdb.o.ACL.d(ACL.java:166)
at com.objectdb.o.STL.j(STL.java:156)
at com.objectdb.o.UTY.X(UTY.java:517)
at com.objectdb.o.TYS.y(TYS.java:787)
at com.objectdb.o.TYS.x(TYS.java:640)
at com.objectdb.o.TYS.v(TYS.java:592)
at com.objectdb.o.TYM.ae(TYM.java:531)
at com.objectdb.o.TYM.ac(TYM.java:467)
at com.objectdb.o.TYM.ao(TYM.java:788)
at com.objectdb.o.TYM.at(TYM.java:873)
at com.objectdb.o.TYM.aw(TYM.java:945)
at com.objectdb.o.OBM.bD(OBM.java:381)
at com.objectdb.o.OBM.bD(OBM.java:267)
at com.objectdb.jpa.EMImpl.persist(EMImpl.java:442)
... 1 more
Caused by: java.lang.IllegalAccessError: class objectdb.BUG2.AS cannot access its superclass BUG2.AS
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at com.objectdb.o.ACL.d(ACL.java:155)
... 14 more
Java Result: 1

Thanks

EKK

 

 

 

 

 

 

 

 

#2

Thank you for this report. The cause is an attempt of ObjectDB to generate a concrete subclass for every managed abstract type. That subclass cannot access your abstract class because it is not public. Adding public to the definition of the abstract class (AS) solves the problem.

This concrete subclass may be needed for some uses, but starting build 2.5.6_02 it will not be generated for non public abstract class, so your test passes with build 2.5.6_02. However, the exact effect of this change has to be explored further, so when possible, defining abstract persistable types as public is preferred.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)

Post Reply

To post a reply and/or subscribe to update notifications - please login