Что нового
В данном разделе приведена информация о новой функциональности и возможных несовместимых изменениях в фреймворке Jmix и Jmix Studio версии 1.5. Примите их во внимание при обновлении с предыдущей версии фреймворка.
Для создания новых проектов в Jmix 1.5 или для апгрейда существующего проекта требуется Studio 1.5 или более поздней версии, поэтому в первую очередь обновите плагин Jmix Studio. Минимальная требуемая версия IntelliJ IDEA - 2022.3. |
Перейдите к разделу Апгрейд проекта, чтобы узнать, как обновить проект с помощью Studio. Процедура автоматической миграции вносит следующие изменения в ваш проект:
-
Обновляет версию Jmix BOM, которая, в свою очередь, определяет версии всех зависимостей.
-
Обновляет версию Jmix Gradle plugin.
-
Обновляет версию Gradle wrapper до 7.6 в
gradle/wrapper/gradle-wrapper.properties
. -
Добавляет все необходимые включения в корневой Liquibase changelog.
-
Добавляет свойство
main.liquibase.change-log
вapplication.properties
. -
Переименовывает свойства
jmix.liquibase.*
вmain.liquibase.*
. -
Обновляет конфигурации Liquibase для дополнительных хранилищ (если они есть).
-
В проектах с Flow UI создает роль
UiMinimalRole
. -
Если в проекте используются дополнения Grid Export Actions и/или GrapesJS, изменяет имена их артефактов.
См. полный список опасных изменений, которые могут затронуть ваш проект после обновления.
Новая и улучшенная функциональность
Корневой Liquibase Changelog со всеми включениями
Корневой файл Liquibase changelog для главного хранилища теперь содержит директивы include
для файлов changelog всех дополнений, используемых в проекте. Это делает changelog совместимым с плагином Gradle для Liquibase и Liquibase CLI, что позволяет запускать Liquibase вне Studio и приложения, например на сервере CI.
Проект должен содержать свойство main.liquibase.change-log
, указывающее путь к корневому changelog, например:
main.liquibase.change-log=com/company/demo/liquibase/changelog.xml
Studio поддерживает включения автоматически при добавлении и удалении дополнений. Кроме того, при старте приложения Studio проверяет что включения в корневом changelog соответствуют дополнениям, используемым в проекте. При обнаружении расхождения отображается диалог с рекомендациями. Определенные пути можно добавить в игнорируемые, чтобы не получать о них уведомление впредь.
Процедура миграции Studio автоматически обновляет корневой changelog и устанавливает необходимое свойство.
См. также опасные изменения.
Ядро Flow UI
Модуль Flow UI обновлен до Vaadin 23.3.
Следующие компоненты Vaadin интегрированы в Flow UI:
-
TabSheet →
JmixTabSheet
(tabSheet
в XML)<tabSheet width="100%"> <tab id="mainTab" label="Main"> <formLayout id="form" dataContainer="userDc">...</formLayout> </tab> <tab id="additionalTab" label="Onboarding steps"> <vbox> <hbox>...</hbox> <dataGrid width="100%" dataContainer="stepsDc">...</dataGrid> </vbox> </tab> </tabSheet>
-
MultiSelectComboBox →
JmixMultiSelectComboBox
(multiSelectComboBox
в XML)<instance id="productDc" class="com.company.demo.entity.Product"> <fetchPlan extends="_base"> <property name="tags" fetchPlan="_base"/> </fetchPlan> <loader/> </instance> <collection class="com.company.demo.entity.Tag" id="allTagsDc"> <fetchPlan extends="_base"/> <loader id="allTagsDl"> <query> <![CDATA[select e from Tag e]]> </query> </loader> </collection> <!-- ... --> <formLayout id="form" dataContainer="productDc"> <textField id="nameField" property="name"/> <multiSelectComboBox property="tags" itemsContainer="allTagsDc"/> </formLayout>
-
Upload →
FileStorageUploadField
(fileStorageUploadField
в XML) иFileUploadField
(fileUploadField
в XML)<fileStorageUploadField id="uploadField" dataContainer="userDc" property="picture"/>
-
Image →
JmixImage
(image
в XML)<image id="image" dataContainer="userDc" property="picture" height="280px" width="200px" classNames="user-picture"/>
-
Многие компоненты теперь поддерживают Tooltip, например:
<textField id="nameField" property="name"> <tooltip text="Product name" position="BOTTOM_START"/> </textField>
В Studio tooltip добавляется с помощью кнопки Add в панели инспектора Jmix UI.
Input Dialog
Интерфейс Dialogs теперь включает метод createInputDialog()
, который позволяет отображать диалог ввода произвольных параметров. Например:
dialogs.createInputDialog(this)
.withParameters(
stringParameter("name").withLabel("Name"),
intParameter("age").withLabel("Age"))
.withCloseListener(dialogCloseEvent -> {
if (dialogCloseEvent.closedWith(DialogOutcome.OK)) {
System.out.println("Name: " + dialogCloseEvent.getValue("name"));
System.out.println("Age: " + dialogCloseEvent.getValue("age"));
}
})
.open();
Background Tasks
Теперь Flow UI имеет механизм выполнения фоновых задач без блокировки пользовательского интерфейса, аналогичный классическому UI.
Пример запуска задачи и отображения прогресса в надписи:
@Autowired
private BackgroundWorker backgroundWorker;
@ViewComponent
private Span taskProgress;
@Subscribe("testBtn")
public void onTestBtnClick(ClickEvent<Button> event) {
BackgroundTaskHandler<Void> handler = backgroundWorker.handle(new SampleTask(15, null, 10));
handler.execute();
}
protected class SampleTask extends BackgroundTask<Integer, Void> {
int count;
public SampleTask(long timeoutSeconds, View<?> view, int count) {
super(timeoutSeconds, view);
this.count = count;
}
@Override
public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
for (int i = 1; i < count + 1; i++) {
Thread.sleep(1000);
taskLifeCycle.publish(i);
}
return null;
}
@Override
public void progress(List<Integer> changes) {
taskProgress.setText(changes.get(0) + "");
}
}
Пример запуска задачи и отображения прогресса в модальном диалоге:
@Autowired
private Dialogs dialogs;
@Subscribe("testBtn")
public void onTestBtnClick(ClickEvent<Button> event) {
dialogs.createBackgroundTaskDialog(new SampleTask(15, this, 10))
.withTotal(10)
.withCancelAllowed(true)
.open();
}
protected class SampleTask extends BackgroundTask<Integer, Void> {
int count;
public SampleTask(long timeoutSeconds, View<?> view, int count) {
super(timeoutSeconds, view);
this.count = count;
}
@Override
public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
for (int i = 1; i < count + 1; i++) {
Thread.sleep(1000);
taskLifeCycle.publish(i);
}
return null;
}
}
Flow UI в дополнениях
Модули Flow UI теперь доступны для следующих дополнений:
-
Multitenancy
-
Quartz
-
Application Settings
-
Grid Export Actions (с возможностью экспорта всех строк, см. Экспорт в Excel).
Дизайнер меню Flow UI
Значительно усовершенствован дизайнер меню Flow UI. В режиме "single", Studio позволяет добавлять в проект пункты меню, унаследованные из подключенных дополнений. Доступные пункты всегда отображаются в отдельной панели слева, что позволяет при необходимости перетаскивать их в свое меню.
Экспорт в Excel
Дополнение Grid Export Actions теперь позволяет пользователям экспортировать в Excel все строки по текущим критериям отбора. Действие excelExport
отображает диалог с опциями All rows | Current page | Selected rows.
Ранее данное действие позволяло экспортировать только строки текущей загруженной страницы.
UI управления пессимистичными блокировками
В ядро фреймворка добавлен UI управления пессимистичными блокировками. Соответствующий пункт меню можно найти в подменю Administration классического UI и в подменю System Flow UI.
Окно инструментов UI дизайнера
Дизайнер и классического и Flow UI теперь имеет одно окно инструментов справа: Jmix UI. Оно включает дерево иерархии компонентов и инспектор свойств выбранного компонента.
Палитра компонентов открывается при нажатии Add component в контекстном меню иерархии компонентов, в верхней панели XML-дескриптора, или в меню Generate.
Предварительные функции
Универсальный фильтр для Flow UI
Компонент GenericFilter
(genericFilter
в XML) позволяет пользователям фильтровать данные по произвольным условиям во время работы приложения.
Пример использования:
<facets>
<dataLoadCoordinator auto="true"/>
<queryParameters>
<genericFilter component="filter"/>
</queryParameters>
</facets>
<layout>
<genericFilter id="filter" dataLoader="usersDl"
summaryText="My filter">
<responsiveSteps>
<responsiveStep minWidth="0" columns="1"/>
<responsiveStep minWidth="800px" columns="2"/>
<responsiveStep minWidth="1200px" columns="3"/>
</responsiveSteps>
</genericFilter>
Элемент genericFilter
фасета queryParameters
необходим для отражения состояния фильтра в параметрах запроса в URL. Благодаря ему тот же фильтр применяется при навигации обратно в экран списка из экрана деталей, а также при перезагрузке страницы браузера.
В данный момент универсальный фильтр поддерживает только условия по атрибутам сущностей. Все остальные функции фильтра классического UI (условия JPQL, кастомные условия, группировка условий, возможность сохранения конфигураций) будут реализованы в следующем релизе.
Опасные изменения
Измененные артефакты дополнений
Grid Export Actions
Изменено имя артефакта стартера:
-
Было
io.jmix.ui:io.jmix.ui:jmix-ui-export-starter
-
Стало
io.jmix.gridexport:jmix-gridexport-ui-starter
И базовый пакет:
-
Было
io.jmix.uiexport
-
Стало
io.jmix.gridexportui
Процедура миграции Studio автоматически изменяет имя артефакта в build.gradle
. Имя пакета необходимо изменить вручную, если он используется в коде проекта.
Liquibase Properties
-
Префикс
jmix.liquibase.*
переименован вmain.liquibase.*
для соответствия паттерну именования свойств источника данных (напримерmain.datasource.url
, гдеmain
- это имя хранилища). Если добавить хранилищеsecond
, его свойства конфигурации Liquibase будут начинаться сsecond.liquibase.*
. -
application.properties
должны содержать путь к корневому файлу Liquibase changelog для каждого хранилища. Например:main.liquibase.change-log=com/company/demo/liquibase/changelog.xml second.liquibase.change-log=com/company/demo/liquibase/second-changelog.xml
Конфигурация хранилища данных
Конфигурация дополнительных хранилищ данных должны быть изменены.
Класс LiquibaseChangeLogProcessor
удален.
Ранее при определении дополнительного хранилища с установкой параметра DB Schema Management в значение Create and Update Studio генерировала следующее определение бина:
@Bean
public SpringLiquibase thirdLiquibase(
LiquibaseChangeLogProcessor processor,
@Qualifier("thirdDataSource") DataSource dataSource) {
return JmixLiquibaseCreator.create(
dataSource,
new LiquibaseProperties(),
processor,
"third");
}
Теперь определение бина должно выглядеть следующим образом (здесь "third" - это имя хранилища):
@Bean("thirdLiquibaseProperties")
@ConfigurationProperties(prefix = "third.liquibase")
public LiquibaseProperties thirdLiquibaseProperties() {
return new LiquibaseProperties();
}
@Bean("thirdLiquibase")
public SpringLiquibase thirdLiquibase(
@Qualifier("thirdDataSource") DataSource dataSource,
@Qualifier("thirdLiquibaseProperties") LiquibaseProperties liquibaseProperties) {
return JmixLiquibaseCreator.create(
dataSource,
liquibaseProperties);
}
Ссылки на сообщения в форматтерах
Исправлена неверная обработка ссылок на сообщения в форматтерах, определенных в XML.
Теперь, как и для других сообщений, ссылка вида msg://myFormat
ищет сообщение с группой текущего экрана, например com.company.app.screen.foo/myFormat
. Префикс с тройной косой чертой ищет сообщение без группы, например myFormat
.
Для адаптации проекта к данному изменению необходимо найти все ссылки на сообщения в форматтерах и заменить двойную косую черту на тройную. Например:
<formatter>
<date format="msg:///myDateFormat"/>
</formatter>
UiMinimalRole в проектах с Flow UI
UiMinimalRole
определяет доступ к главному экрану и экрану логина. Для того, чтобы можно было заменить эти экраны, данная роль перемещена из фреймворка в проекты. Например:
package com.company.demo.security;
import io.jmix.core.entity.KeyValueEntity;
import io.jmix.security.model.*;
import io.jmix.security.role.annotation.*;
import io.jmix.securityflowui.role.annotation.ViewPolicy;
@ResourceRole(name = "Flow UI: minimal access", code = UiMinimalRole.CODE, scope = SecurityScope.UI)
public interface UiMinimalRole {
String CODE = "flowui-minimal";
@ViewPolicy(viewIds = "MainView")
void main();
@ViewPolicy(viewIds = "LoginView")
@SpecificPolicy(resources = "flowui.loginToUi")
void login();
@EntityPolicy(entityClass = KeyValueEntity.class, actions = EntityPolicyAction.READ)
@EntityAttributePolicy(entityClass = KeyValueEntity.class, attributes = "*", action = EntityAttributePolicyAction.VIEW)
void keyValueEntity();
}
Flow UI DataGrid
-
Метод
getColumns()
компонентовDataGrid
иTreeDataGrid
теперь возвращает только колонки, не скрытые подсистемой безопасности. Ранее он возвращал все колонки, включая скрытые. -
Колонки, скрытые подсистемой безопасности, не изменяют своего свойства видимости. Ранее атрибут
visible
таких колонок устанавливался в false.
ui-test-assist
Модуль ui-test-assist
теперь не приносит транзитивных зависимостей на Spock и Groovy. Кроме того, он не содержит классов UiTestAssistSpecification
, ScreenSpecification
м TestMainScreen
.
Все касающееся Spock и Groovy было перемещено в новый модуль ui-test-assist-spock
.
Если ваш проект использовал классы ScreenSpecification
или UiTestAssistSpecification
, добавьте зависимость в build.gradle
:
testImplementation 'io.jmix.ui:jmix-ui-test-assist-spock'
и измените импорты классов ScreenSpecification
, UiTestAssistSpecification
, TestMainScreen
на io.jmix.ui.testassistspock.*
.
Известные проблемы
Jmix 1.5.3 зависит от Spring Boot 2.7.13, который в свою очередь зависит от версии Hazelcast 5.1.7. К сожалению, в Hazelcast 5.1.7 имеется баг. Этот баг делает невозможным работу с кластером Kubernetes во встроенном режиме, и инструкции, описанные в разделе Кластер Kubernetes, не работают.
Обходным путем является откат к версии Hazelcast 5.1.5. Это можно сделать, добавив следующую инструкцию в файл build.gradle
:
implementation('com.hazelcast:hazelcast') {
version {
strictly '5.1.5'
}
}