PropertyBinder for base type reports no children property found in parent class

Hi,
My data model is:

public class DocumentEntity{

    @PropertyBinding(binder = @PropertyBinderRef(type = PublicationBinder.class))
    private PublicationEntity publication;
}

PublicationEntity has many children and each children has different fields.

In the binder, I want to list all the dependencies but got
HSEARCH700078: No readable property named ‘title’ on type PublicationEntity.

public class PublicationBinder implements PropertyBinder {
    @Override
    public void bind(PropertyBindingContext context) {
        context.dependencies()
            .use("issn").use("publisher").use("year") // publication  basic
            .use("title") // fields inside both in journal and conference
            .use("number").use("volumn") // journal specific
            .use("abstractNumber"); // conference specific

Dose anyone know how to solve that besides flatten all children fields into parent class? Thanks!

Hey,

The current API does not offer a way to express that kind of dependency on subclasses.

Please open a ticket and we can have a look at how we can support it?

In the meantime, I think there are multiple ways to work around the problem.

The simplest solution would indeed be to pull properties into the parent class.

Otherwise, if by chance, DocumentEntity actually represents a hierarchy of types which is parallel to that of PublicationEntity, e.g. JournalEntity extends DocumentEntity points to a JournalPublicationEntity, ConferenceEntity extends DocumentEntity and points to a ConferencePublicationEntity, etc.; then in that case you should be able to change your model by overriding getPublication() to return the correct type in each subtype of DocumentEntity. Provided you use the “property” access type (@Access(AccessType.PROPERTY)), you will then be able to detect the type of the property in the bind() method of the property binder, using context.bridgedElement().isAssignableTo(...), and with that information you will know which dependencies to declare.

Otherwise, if there is a strict one-to-one relationship between PublicationEntity and DocumentEntity, another solution would be to add @Indexed on PublicationEntity instead of DocumentEntity, and to use a TypeBridge on PublicationEntity. You will then be able to inspect the type of the bridged element in the bind() method through context.bridgedElement().isAssignableTo(...), and with that information you will know which dependencies to declare.

Otherwise, yet another hack that could work, but that I’ve never tried: you could leverage fromOtherEntity in a way that it was never intended to be used. You could declare a getSelf() getter in PublicationEntity, and override it in each subtype to return that subtype (e.g. PublicationEntity getSelf() {...} in PublicationEntity, JournalPublicationEntity getSelf() {...} in JournalPublicationEntity, etc.). Don’t forget to annotate the getter with @javax.persistence.Transient to avoid problems with Hibernate ORM. Then you should be able to do this:

public class PublicationBinder implements PropertyBinder {
    @Override
    public void bind(PropertyBindingContext context) {
        context.dependencies()
            .use("issn").use("publisher").use("year"); // publication  basic
        context.dependencies().fromOtherEntity( JournalPublicationEntity.class, "self" )
            .use("title") // fields inside both in journal and conference
            .use("number").use("volumn"); // journal specific
        context.dependencies().fromOtherEntity( ConferencePublicationEntity.class, "self" )
            .use("title") // fields inside both in journal and conference
            .use("abstractNumber"); // conference specific

I’d recommend testing that changing a title actually triggers reindexing, because this is really a hack and I’ve never tried it. But in theory, it could work…

1 Like

Hey,
Thanks a lot, the last solution is the best for me because the actual physical model for DocumentEntity is more complex than the example, publication is only one sub-field.