Search code examples
javajpaeclipselink

Does EclipseLink DescriptorCustomizer not support inherited subtypes?


Basically, I have a base class type that describes entities as being not deletable. I use eclipse link's descriptor customizer API to override the default delete SQL and add an additional criteria to only return non-archived entities.

This works for all classes that extend the Archiveable class directly. Classes that extend a non MappedSuperClass that extends the Archiveable class do not inherit the customizer. See my example below:

For what it's worth, I am using EclipseLink 2.5.1.

/**
 * Base Abstract class that implements archiving functionality 
 */ 
@MappedSuperClass
@Customizer(ArchiveableCustomizer.class)
public abstract class Archiveable {

   @NotNull
   @Column(name = "DELETED)
   private Boolean archived = false;    

   // omitted: getters/setters    
}

/**
 * The EclipseLink customizer implementation (followed their docs)
 */ 
public class ArchiveableCustomizer extends DescriptorEventAdapter
        implements DescriptorCustomizer {

     @Override
     public void customize(ClassDescriptor descriptor) throws Exception {
         // omitted: override delete string

         // this is the piece not working
         descriptor.getQueryManager().setAdditionalCriteria("this.archived = false");
     }
}


/**
 * Base class for entities that are stored in the Catalog table. All are archived
 */ 
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TYPE", DiscriminatorType.STRING)
public abstract class Catalog extends Archiveable {
    // omitted: shared columns, not relevant. 
}

/**
 * This class does <b>NOT</b> work
 */
@Entity 
@DiscriminatorValue("CAR_TYPE")
public class CarType extends Catalog {
    // omitted: class details, not relevant
}

/**
 * Class that does not extend the Catalog class but the Archiveable 
 * class directly. This class can be queried correctly with the 
 * additional criteria
 */ 
@Entity
public class Car extends Archiveable { 
     // omitted: clas details, not relevant
}

In summary, the class CarType does not pick up the ArchiveableCustomizer. The class Car does pick up the ArchiveableCustomizer.


Solution

  • Within the internals of EclipseLink, MappedSuperClass classes do not have descriptors themselves, so all settings are pulled from them and applied to subclass entity descriptors - including customizers.

    With inheritance, each entity in the hierarchy has its own descriptor, and while mappings and other settings are inherited, descriptor customizers are only executed on the descriptor they assigned to - the root in this case. Also note that some changes in the root entity will be seen in subclasses; inheritance graphs all use the same cache for instance, and changes to common mappings might be visible on child descriptors though I'm unsure of that point