MetaProperty атрибута в дочерней сущности

Вечер добрый.

demo1.zip (89.5 КБ)
(Для удачной сборки адреса репозиториев нужно поправить, у нас локальные используются.)

Имеетя абстрактная родительская сущность AbstractClient:

@JmixEntity
@Table(name = "DEMO1_CLIENT")
@Entity(name = "demo1_AbstractClient")
public abstract class AbstractClient<T> {

    @JmixGeneratedValue
    @Id
    @Column(name = "ID", nullable = false)
    private UUID id;

    @NotNull
    @Column(name = "TYPE_", nullable = false)
    protected String type;

    /* Getters and Setters */

    @NotNull
    public abstract T getType();

    public abstract void setType(@NotNull T type);

}

У неё атрибут type строковый, но getter и setter абстрактные, чтобы в наследнике могли возвращать EnumClass по значению ключа, а может и что-то другое, или даже туже самую строку.

Имеется наследник Customer:

@JmixEntity
@Entity(name = "demo1_Customer")
public class Customer extends AbstractClient<CustomerType> {

    @Override
    public CustomerType getType() {
        return type == null ? null : CustomerType.fromId(type);
    }

    @Override
    public void setType(CustomerType type) {
        this.type = type == null ? null : type.getId();
    }

}

И Enum CustomerType:

public enum CustomerType implements EnumClass<String> {

    ORDINAL("ORDINAL"),
    VIP("VIP");

    private final String id;

    CustomerType(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    @Nullable
    public static CustomerType fromId(String id) {
        for (CustomerType at : CustomerType.values()) {
            if (at.getId().equals(id)) {
                return at;
            }
        }
        return null;
    }
}

В результате, при попытке открыть сущность Customer в Entity Inspector получаю исключение:

ClassCastException: class com.company.demo1.common.CustomerType cannot be cast to class java.lang.String (com.company.demo1.common.CustomerType is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')

Подебажив немного я обнаружил что MetaProperty demo1_Customer.type не является собственной property у MetaClass demo1_Customer, а приезжает из MetaClass demo1_AbstractClient и имеет тип String.

И далее, любая механика, которая берёт у MetaProperty её Datatype и применяет format() выбрасывает искючение.
Конкретно у EntityInspectorBrowse в какой-то момент вызывается MetadataTools.format() и далее StringDatatype.format(), где выполняется приведение типа CustomerType в String.

Вопрос: как-то можно легально указать необходимый в наследнике тип данных атрибута?
Я некоторым образом в рантайме подменяю MetaProperty но это выглядит как ненадёжный костыль.

В демо проекте changelog добавляет запись в БД для Customer и чтобы увидеть ошибку достаточно открыть в инспекторе список.

Добрый день!

Мы не предусматривали подобную возможность и пока не тестировали варианты использования дженериков в модели данных.

Не могли бы вы рассказать, какие задачи вы решаете путем создания такого параметризованного базового класса? Это поможет нам приоритизировать работу.

С уважением,
Константин

Спасибо за ответ!

На данный момент задача пока одна и она такая, специфическая, из разряда экспериментов.

Задача примерно как я описал в демо проекте.

Есть аддон, который предоставляет некоторый функционал общих справочником: одна абстрактная сущность с наследованием SINGLE_TABLE, один экран для редактирования.
В конечном приложении, где подключен этот аддон, я описываю конкретные классы сущностей, наследую их от абстрактного родителя из аддона, каждая из которых представляет некоторый справочник (типы работ, типы заданий, результаты и т.п.). То есть набор некоторых однотипных данных.

Задумка в том, чтобы избавиться от одинаковых сущностей (который отличаются, по сути, типом одного атрибута), кучи одинаковых таблиц, с максимум десятком строк в каждой, и набора экранов для каждой из них.

Описанная проблема возникает тогда, когда я хочу некоторый атрибут этих справочников сделать выбираемым из представленного набора (EnumClass). И этот набор значений должен быть уникальным для каждого из справочников, то есть у каждого класса сущности свой EnumClass.

В своей конкретной задаче я ещё и пытаюсь для нескольких разных значений @DiscriminatorValue получать сущность одного класса, для чего использую EclipseLinkовские ClassExtractor и DescriptorCustomizer и там я делаю подмену MetaProperty через MetaClassImpl.registerProperty(). Пока работает, но хотелось бы легальный путь.

Добрый день!
Спасибо за пояснения. Попробуем реализовать, завел тикет:
Support for generic superclass in entities · Issue #4099 · jmix-framework/jmix

Спасибо!
Надеюсь если решение появится, то и в JMIX 1.x оно тоже попадёт :grinning: