Всем здравствуйте.
Мы столкнулись с этой же ошибкой. Возможно корень проблемы лежит в том же месте, с которым столкнулись мы. Так же мы смогли создать тестовый пример (150,5 КБ) на котором она воспроизводится:
- Запустить приложение
- Зайти в экран Foos, создать один экземпляр
Foo 0
и два экземпляра Bar 0.1
, Bar 0.2
. Сохранить.
- Открыть экран Bars и открыть редактор
Bar 0.2
- Указать у экземпляра любого пользователя (поле
User
). Сохранить.
- Открыть экран Foos, редактировать
Foo 0
, в таблице выбрать Bar 0.2
нажать на красную кнопку.
Пояснения, что происходит.
В методе сущность грузится с представлением более широким, нежели то, которое используется в исходном экране и обновляет атрибуты в исходном источника данных.
Bar bar = barsGrid.getSingleSelected();
if (bar == null) {
return;
}
bar = dataManager.reload(bar, "bar-edit");
barsDs.updateItem(bar);
Так как barsDs
является CollectionPropertyDatasource, то при обновлении объект не заменяется, а копируются значения из источника (CollectionPropertyDatasourceImpl:603
). Так как при копировании исходный объект содержит свойство user
то проверка persistentAttributesLoadChecker.isLoaded(source, name)
(MetadataTools:905
) проходит и значение пытается поставиться в объект с меньшим представлением. Из-за того, что атрибут user
не загружен у объекта с меньшим представлением, возникает ошибка.
Однако, эта ошибка должна была перехватиться (MetadataTools:913
). Однако этого не происходит в следствие того, что исключение не ожидаемый IllegalStateException
, а org.eclipse.persistence.exceptions.ValidationException
. Для того, чтобы кинуть “правильное” исключение IllegalStateException
есть специальная модификация в eclipselink’е org.eclipse.persistence.internal.indirection.DatabaseValueHolder.java:93
. Однако условие, необходимое для срабатывания не работает.
В результате мы выяснили, что подобное происходит тогда, когда FetchGroupManager использует LoadGroup
вместо FetchGroup
. Это в свою очередь было из-за того, что в представлении loadPartialEntities
являлся false. В свою очередь это было из-за того, что в методе com.haulmont.cuba.core.app.RdbmsStore#createRestrictedView
не срабатывает условие:
if (context.isLoadPartialEntities()
&& !needToApplyInMemoryReadConstraints(context)
&& !needToApplyAttributeAccess(context)) {
copy.setLoadPartialEntities(true);
}
Конкретно needToApplyAttributeAccess(context)
возвращал true. В следствие этого сущности грузились не так, как их ожидали. В результате чего эта ошибка и возникала.
Изначально мы пытались построить преставление так, чтобы наши сущности грузились корректно, и сначала нам это упешно удавалось. Однако, потом возникла ситуация, где ввиду большого количества перекрестных ссылок и как следствие сложности подбора соответствующего представления, мы не смогли его подобрать. В итоге мы решили переопределить FetchGroupManager так, чтобы всегда использовался FetchGroup при загрузке.
Хотелось бы увидеть комментарии разработчиков по поводу опасности такого решения или предложить альтернативный способ решения этой проблемы.