Проблемы с атрибутом типа Embedded ReferenceToEntity

Добрый день.
Собрал несколько багов в одну тему, если не возражаете:

  1. Не могу использовать com.haulmont.cuba.core.entity.ReferenceToEntity - не отображается при создании атрибута. Не хотелось бы изобретать велосипед, когда в платформе уже рабочая сущность.
    image
    При этом прописать вручную - все отлично работает
    @Embedded
    @EmbeddedParameters(nullAllowed = false)
    protected ReferenceToEntity reference;
  1. При создании Edit-экрана при включенном во view embedded-атрибута светит ошибку:
Exception when process 'C:\Program1\CUBA Studio SE\resources\app\studio\templates\snippet\screen\fieldGroup.xml' snippet.
Cannot cast object '{datasource=referenceDs}' with class 'java.util.LinkedHashMap' to class 'groovy.lang.MetaClass' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: groovy.lang.MetaClass(java.util.LinkedHashMap)

Воркэраундом было убрать данный атрибут из view, создать экран и затем добавить его обратно во view

upd: на тестовом проекте, к сожалению, не получается воспроизвести проблему. Возможно, на тот момент часто менял атрибут и где-то при генерации что-то не так пошло.

  1. Также заметил, что в EntityInspector не отображается атрибут ReferenceToEntity#entityId (UUID)
    image

CubaStudio SE 6.10.0
CubaPlatform 6.10.4

Дополню своей багой. Как раз сегодня добавлял embedded атрибут.
Есть предок и несколько наследников со стратегией SINGLE_TABLE. Если добавляем embedded-атрибут в одного из наследников, то студия не генерирует соответствующих скриптов.
На самом деле это предположение и оно требует подтверждения.
UPD: Проверил. Не генерируются скрипты для этой ситуации.

Реальная же ситуации обратная. Я из наследника выносил несколько атрибутов в embedded-атрибут и студия сгенерировала скрипты удаления этих атрибутов.

CUBA Studio Version 6.10.1

Добрый день.

По пункту 1, мы не рекомендуем использовать SystemLevel сущности в проектах, Студия фильтрует список Embedded сущностей именно по этому признаку. Если же использование действительно необходимо, то описанный вами вариант добавления - единственно верный.
Пункт 2 мы так же не смогли воспроизвести, а по пункту 3 завели тикет.

  1. Не подскажете, с чем связана данная рекомендация? На мой взгляд, команда пишет стабильные и простые в использовании методы. В данном случае выходит, что мы или пишем ***/дубль, имея хороший пример, с которым уже привыкли работать, или получаем класс, подключенный по средствам костыля.
    Вы, несомненно, именно это и написали, но все же дополню. Это же правило касается и наследования (скажем, не получается из интерфейса создать MetaClassReferenceToEntity).
  2. Да, тоже пытался сделать тестовый проект. Так же не получилось воспроизвести. Предполагаю, что просто закрались какие-то артефакты из-за частого редактирования атрибута

Спасибо, что сообщили о проблеме, мы завели тикет по описанному Вами сценарию.
При вынесении несколько атрибутов в embedded-атрибут генерируются скрипты удаления этих атрибутов, если вы удалили их из сущности, и скрипты добавления новых атрибутов Embеdded сущности, их имена могут как совпадать, так и отличаться, Студия не проверяет такой кейс.

Наталья. Я попробовал и другой кейс, который предполагал. Проверил следующим образом. Добавил новый атрибут в embedded-сущность. Студия не сгенерировала скриптов для такой таблицы:

Прочел описание тикета. Все хорошо.

Плюсом нашел еще 2 бага (более критичных), как мне кажется. Продолжить в этой теме или открыть новую?

Если они связаны с Embedded, то можно здесь, если нет, то лучше в новой теме.

В общем продолжу тут, а там если что вынесите в отдельный топик.

Возможно все так и должно работать и просто не совпадает с моими ожиданиями.
Атрибуты embeddable-сущности добавляю в контроллер edit-экрана следующим образом:

<field property="geologyFluid.bottomPressure"/>

При этом:

  1. При изменении этих полей в форме не производится коммит. Вероятнее всего isModifided() у датасорса так и остается false. Если изменить атрибут самой сущности, то изменения (в том числе и в embeddable-сущности) сохранятся.
    Если есть какой-то обходной путь, поделитесь.
  2. ItemPropertyChangeListener для embedded-атрибута не срабатывает при изменении атрибута embeddable-сущности.
  3. Есть следующий слушатель:
    @Inject
    private LookupPickerField wellLPF;

    @Override
    protected void initNewItem(RequestEditWell item) {
        super.initNewItem(item);
        wellLPF.addValueChangeListener(e -> onChangeWell(wellLPF.getValue()));
    }

    private void onChangeWell(Well well) {
        Set<String> attrNamesToCopy = new HashSet<>(Arrays.asList("wellID", ..., "geologyFluid"));
        attrNamesToCopy.forEach(attrName ->
                getItem().setValue(attrName, well.getValue(attrName))
        );
    }

geologyFluid - соответственно embedded-атрибут. Так вот, при выборе значения с помощью picker-а все хорошо: на форме проставлются значения в атрибуты embeddable-сущности. При использовании же lookup-а значения на форме не проставляются, хотя и заполняются в датасорсе. При этом если переключиться на другую вкладку и вернуться назад, значения полей заполнятся.
В качестве обходного решения не подскажите как обновить экран принудительно? Что-то вроде repaint() для таблицы.


  1. Студия не позволяет выбрать представление для emdedded-атрибута:
    image
    Может и не должна…
    По умолчанию там _minimal, что как бы намекает, что они не будут подгружены. Кроме того галочками можно выбрать отдельные атрибуты.

  2. Предлагаю изменить поведение студии. Генерировать секцию @AttributeOverrides только при первом добавлении атрибута. Сейчас если я не хочу переопределять имена колонок и удаляю эту секцию, студия вновь сгенерирует ее при любом изменении сущности.

  3. Вопрос не связан с предыдущими, но связан с генерацией скриптов студией. Если изменить в metadata.xml

    <datatypes>
        <datatype id="Length" class="com.borets.wedb.datatypes.Length" sqlType="decimal(19,6)"/>
    </datatypes>

sqlType для кастомного типа данных, студия не будет учитывать этого при генерации скриптов обновления для уже добавленных атрибутов, только для вновь добавленных.

PS. Уже подумываю снова утащить из ebeddable сущности в основные… Может быть сможете предложить решения или обходные решения этих проблем.

1 симпатия

Дополню еще одной проблемой.

Если для роли указано, что разрешение для embedable сущности только Read, то на экране, куда включены атрибуты этой сущности они все равно будут editable.

Наталья, скажите, могу я ожидать ответа по этой теме?

К сожалению, не смогла воспроизвести эту проблему. Проверяла на платформе версии 6.10.6.

  1. Описанное вами поведение нормально для ситуации, когда атрибут добавляется описанным вами образом. Чтобы избежать этого, необходимо объявить вложенный datasource для embedded сущности и объявлять поля, ссылаясь на этот datasource:
    <field datasource="addressDs" property="street"/>
    По умолчанию студия сама сейчас так добавляет атрибуты.
  2. ItemPropertyChangeListener нужно добавить к datasource, относящийся к embedded сущности (см. пунк 1)
  3. Пришлите, пожалуйста, пример проекта, где можно воспроизвести проблему
  4. Студия версии 6.10.2 позволяет выбрать view для embedded атрибута.
  5. Это сделано специально для того, чтобы при наличии большого количества embedded атрибутов в сущности не совпали имена колонок. Создан feature request на изменение поведения студии
1 симпатия

Наталья, прежде всего, спасибо за ответ.

Скорее всего при “правильном” включении атрибутов в экран с помощью зависимого датасорса проблема и не существует.

Может быть и не имеет смысл это сейчас моделировать и при “правильном” включении атрибута все будет корректно.

Проверю отпишусь.

Для описанного мною случая при добавлении зависимого датасорса действительно все работает как нужно. Но хотелось бы дополнительно рассмотреть другие случаи:

  1. У роли пользователя есть права только read на сущность, в которой есть emdedded-атрибут. На форме даже при использовании зависимого датасорса поля embeddable-сущности не будут read-only.
  2. Аналогичная ситуация, если запретить изменение этого
    emdedded-атрибута.
  3. Аналогичная ситуация, если добавлять emdedded-атрибут в список readonly-атрибутов в SetupAttributeAccessHandler

Т.е. управлять доступом к полям, связанным с этим атрибутов у меня не получилось, может быть я опять что-то делаю не так.

Тестовый проект с бд иллюстрирующий первые 2 пункта. Могу добавить третий, если требуется.
embeddedAttr.7z (133,4 КБ)

Спасибо, что сообщили о проблеме, мы завели задачу на исправление.

Чтобы пометить поля как read-only не дожидаясь исправлений, нужно в контроллер экрана добавить следующий код:

    @Inject
    private Security security;
    @Inject
    private Metadata metadata;
    @Named("fieldGroup.city")
    private TextField cityField;
    @Named("fieldGroup.street")
    private TextField streetField;

    @Override
    public void init(Map<String, Object> params) {
        if(!security.isEntityAttrUpdatePermitted(metadata.getClass(Staret.class),"address")){
            cityField.setEditable(false);
            streetField.setEditable(false);
        }
    }
1 симпатия

Наталья, день добрый.

Вижу, что 7ая студия по умолчанию добавляет поля не так. Подход изменился?

Да, у нас полностью изменилось API работы экранов, подробнее можно узнать тут.

Наталья, мне известно об изменении api экранов. К сожалению, в документации нет ничего о работе с embedded-атрибутами. Или я не прав?

Да, вы правы, этот функционал еще не описан в документации, однако, вы можете работать с embedded-атрибутами в компоненте Form аналогично тому, как это было в FieldGroup: добавьте компонет для атрибута, задайте dataContainer и определите property.

Наталья, я почему собственно спрашивал.

“Аналогично” в FieldGroup без вложенного Ds не сохранялись изменений в embedded-атрибуте. Сейчас изменения сохраняются и без вложенного Dc.
Каков подход сейчас правильный: добавлять вложенный Dc (это не доработка студии, что она не добавила) или не добавлять?