Release 3.0
How To Upgrade
|
To create new projects with Jmix 3.0 or to upgrade an existing project, you need Studio 3.0 or later, so update your Jmix Studio plugin first. The minimal supported IntelliJ IDEA version is now 2025.3. |
|
Jmix 3.0 requires Java 21 or 25. Update your IDE project settings to use Java 21 JDK before upgrading to Jmix 3.0:
|
See Upgrading Project section for how to upgrade your project using Studio. The automatic migration procedure makes the following changes in your project:
-
Updates the version of Jmix BOM which in turn defines versions of all dependencies.
-
Updates the version of Jmix Gradle plugin.
-
Updates Gradle wrapper to 9.5.1
-
Adds dependencies:
-
implementation 'com.vaadin:vaadin-dev' -
testImplementation 'org.springframework.boot:spring-boot-jdbc-test'
-
-
Adds
productionMode = falseto thevaadinblock inbuild.gradle. -
Adds
@Stylesheet(Lumo.UTILITY_STYLESHEET)annotation to the application class. -
Migrates compact theme declaration from
@JsModuleto@Stylesheet. -
Removes
lumoImportsfromtheme.json. -
Adds
offline=falseto@PWAannotation. -
Migrates signature of
@Install loadFromRepositoryDelegatefor instance loaders. -
Sets attribute
operationTextVisibleto false forpropertyFilterin some cases. -
Migrates imports:
-
com.vaadin.flow.component.splitlayout.SplitLayout.SplitterDragendEvent -
io.jmix.authserver.service.mapper.JdbcOAuth2AuthorizationServiceObjectMapperCustomizer -
io.jmix.flowui.component.validation.group.UiCrossFieldChecks -
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties -
org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties -
org.springframework.boot.autoconfigure.web.ServerProperties -
org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.
-
-
Adds a comment for every injected
JmixUploadabout generic type. -
Parameterizes
FileUploadSucceededEventgeneric type depending on the field type:FileUploadFieldorFileStorageUploadField. -
Removes
DropdownButtonicontheme name if thetextattribute is set. -
Removes
@io.jmix.maps.Geometryannotation. -
Migrates
JmixUserDetailsauthoritiescontract in Kotlin projects. -
Sets
jmix.ui.legacy-monitoring-enabled=true. -
Sets
jmix.reports.use-legacy-date-time-types=trueandjmix.reports.client.show-report-table-view-in-menu=trueif the Reports add-on is included. -
Sets
com.vaadin.experimental.themeComponentStyles=trueinsrc/main/resources/vaadin-featureflags.properties.
See also the full list of breaking changes that can affect your project after the upgrade.
|
Execute the following Gradle tasks in the terminal after migration and before building and running the application:
|
Updated Dependencies
The following major dependencies have been updated:
-
Spring Boot 4.0
-
Vaadin 25.1
-
EclipseLink 5.0
-
Flowable 8.0
Common Spring Boot 4 Migration Notes
-
Rename Jackson packages:
com.fasterxml.jackson.databind→tools.jackson.databind -
Nullability annotations of
org.springframework.langpackage are now deprecated. Replace them withorg.jspecify.annotations, for example:-
org.springframework.lang.Nullable→org.jspecify.annotations.Nullable -
org.springframework.lang.NonNullApi→org.jspecify.annotations.NullMarked
-
-
For distributed tracing, switch to the
spring-boot-starter-opentelemetrystarter and update the OTLP export properties. See Observability / Tracing for the updated setup.
See the following resources for more information:
New Features and Improvements
Studio Improvements
-
The AI Agents Toolkit action available in the Settings menu of the Jmix tool window allows you to automatically install agent skills, instructions, and MCP servers from the Jmix AI Agent Guidelines GitHub repository into the current project. It supports the following agents: Claude Code CLI, Codex, OpenCode, Junie.
-
Do not generate Liquibase drop changesets for unmapped tables option has been added to the Data Store Properties dialog.
-
Inherited attributes can now be displayed in the entity designer.
-
Studio now helps you create custom update services and use them in views. When you create a JPA entity, select the Create Update Service checkbox in the New JPA Entity dialog to generate a service class. Later, when you create a view for an entity that has an update service, select the Use Update Service checkbox in the Create Jmix View dialog to delegate saving and removing to that service automatically.
-
If the Multitenancy add-on is included in the project, the new Has Tenant ID trait allows you to add a
@TenantIdattribute to an entity. -
Search index definitions and Quartz jobs are displayed in the Jmix tool window and can be quickly created from templates.
-
Main Jmix features are now available in the context menu of the Project tool window:
-
Jmix Project Properties
-
Jmix Main Data Store
-
Jmix Additional Data Stores
-
Jmix Add-ons
-
New → Jmix → …
-
-
Studio can now read and update build scripts written in Kotlin DSL (
build.gradle.kts).
Dynamic Model Add-on
The new Dynamic Model add-on lets you extend the data model of a running application without changing source code or restarting: you can add attributes to existing entities and define entirely new entities backed by dedicated database tables. The model is edited in a graphical admin UI, stored as a versioned definition, and can include runtime UI such as views and menu items, along with validation, uniqueness, and security based on resource roles.
AI Tools Add-on
The new AI Tools add-on brings an LLM-powered assistant to Jmix applications. It provides a ready-to-use chat UI, a programmatic API, predefined tools for natural-language data access, and extension points for adding custom tools.
Aura Theme
With the upgrade to Vaadin 25, Jmix applications now support the new Aura theme. The existing Lumo theme remains available. When creating a project in Studio, you can choose the theme you want to use.
MarkdownEditor Component
The new markdownEditor component allows users to write and preview Markdown content within a single field. It provides a formatting toolbar, mode switching between Edit and Preview, keyboard shortcuts, and standard field features such as data binding, validation, and theming.
DataGrid and TreeDataGrid Detail Renderers
The dataGrid and treeDataGrid components now provide two predefined XML renderers for opening entity detail views directly from a column:
-
detailLinkRendererrenders a link to the detail view, -
detailButtonRendererrenders a button that opens the detail view by navigation or in a dialog.
This makes it easier to add Open or Edit actions to a dataGrid or treeDataGrid column without writing a custom renderer.
Application-Wide Sorting Customization
Jmix Flow UI now provides dedicated extension points for customizing sorting behavior. Developers can register sorting customizations as Spring beans for both in-memory sorting and JPQL sort expressions.
Because each customization is defined as a separate bean, applications and add-ons can contribute their own sorting rules while keeping them independent and reusable. This avoids conflicts between rules and removes the need to modify global framework defaults such as SorterFactory or JpqlSortExpressionProvider.
See Sorting for details.
Per-Grid Sorting Customization
In addition to application-wide sorting customization, developers can now customize sorting for a specific dataGrid or groupDataGrid. These components can use a Column Comparator for in-memory sorting and a Sort Builder Delegate to map a column to custom comparators and database sort expressions.
This approach keeps sorting rules close to the grid configuration. It is useful when sorting requirements are specific to a single view.
Runtime View Templates
The new Runtime View Templates feature lets you generate standard list and detail views from templates declared on entity metadata, instead of creating them manually at design time. You annotate an entity class with @ListViewTemplate and @DetailViewTemplate, and the framework generates the corresponding views, routes, and menu items at startup.
Built-in templates render a dataGrid for list views and a formLayout for detail views, with configurable property filtering. Detail views of entities that have composition collections render a tabSheet with a separate editable grid per collection. You can also supply a custom Freemarker template to fully control the generated view content.
GenericFilter Builder API
The new genericFilter fluent builder API provides a concise way to configure a filter in Java. Use filterComponentBuilder() to create propertyFilter, jpqlFilter, and groupFilter components, and runtimeConfigurationBuilder() to assemble and register a run-time configuration. The builder performs the component initialization — data loader wiring, parameter-name and value-component generation, condition delegation — that previously had to be written explicitly through the low-level API.
Disabling Unsafe Runtime Features
New application properties let you turn off runtime features that can execute arbitrary code or expose internal information and therefore may be unsafe in production. All properties default to true, so the current behavior is preserved unless a property is explicitly turned off.
The jmix.core.unsafe-runtime-features-enabled property is a global kill switch: when it is false, all the guarded features below are disabled regardless of their own properties. Each feature can also be turned off individually:
-
jmix.core.hot-deploy-enabled – loading classes from the file system by Hot Deploy.
-
jmix.core.trigger-files-enabled – bean invocation through trigger files.
-
jmix.security.data.groovy-enabled – Groovy execution in predicate row-level policies.
-
jmix.dynattr.ui.groovy-enabled – Groovy execution in dynamic attribute scripts.
-
jmix.reports.groovy-enabled – Groovy execution in reports.
-
jmix.jmxconsole.write-and-invoke-enabled – write and invoke operations in the JMX console.
-
jmix.datatools.data-model-diagram.public-server-enabled – sending the data model to the public PlantUML server.
See #5287 for more information.
Password Change at Next Login
It is now possible to require users to change their password at the next login. You can use this when creating a new user or when assigning a temporary password with the standard Reset Password action.
Learn more in Password Change at Next Login.
Message Template Preview
The Message Templates add-on now lets users validate templates directly in the UI before using them. The new Preview action helps check rendering with actual parameter values, and exposes FreeMarker or missing-parameter problems earlier.
Breaking Changes
Security
-
In Vaadin 25 the default authorization rule for requests that don’t match a known view or framework resource changed from "authenticated" to "deny". As a result, being logged in no longer grants access to arbitrary paths the way it did in Jmix 2. Custom static resources (e.g.
/icons/**,/images/**) now return HTTP 403 unless their path is explicitly permitted.When migrating to Jmix 3.0, applications that serve custom static resources must explicitly allow those paths by registering a dedicated
SecurityFilterChainas explained in the Custom Endpoints section. -
The
VaadinWebSecurityclass has been removed in Vaadin 25. TheFlowuiVaadinWebSecurityclass exists, but doesn’t extend the Vaadin’s class anymore. If you have overriddenVaadinWebSecuritymethods likeconfigure(WebSecurity web), rewrite your configuration usingSecurityFilterChainorWebSecurityCustomizerbeans as described in the Custom Endpoints section.
See Vaadin security configuration migration docs for more information.
TENANT_ID Column in Application Settings
The AppSettingsEntity base class of the Application Settings add-on now has tenantId attribute to support multitenancy (see #5144). If you have application entities extending this base class, you need to create the TENANT_ID column for this attribute in your database.
Use the Data Store → Main → Generate Liquibase Changelog action, or, if you don’t have a subscription, create a new changelog using the Data Stores → Main → New → Liquibase Changelog action and add a changeset like this (replace MY_SETTINGS with your settings table):
<changeSet author="sample" id="1">
<addColumn tableName="MY_SETTINGS">
<column name="TENANT_ID" type="VARCHAR(255)"/>
</addColumn>
</changeSet>
See Data Store Actions for more information about data store actions in Studio.
JasperReports Dependencies
The Reports add-on does not bring JasperReports dependencies transitively anymore. If you use JasperReports templates, add the following dependencies to your build.gradle explicitly:
implementation 'net.sf.jasperreports:jasperreports'
implementation 'net.sf.jasperreports:jasperreports-fonts'
implementation 'net.sf.jasperreports:jasperreports-functions'
Overlays
Overlay internals and styling behavior have changed in Vaadin 25. If your application customizes overlays, review the Vaadin overlay upgrade notes.
Download API Changes
-
The
Downloaderbean now works throughDownloaderExportHandler, which implements Vaadin’s DownloadHandler API. As a result, generated URLs now have theVAADIN/dynamic/resource/<random_id>format instead of/download/UUID. Previously, theDownloaderbean createdJmixFileDownloader, which served aStreamResource.JmixFileDownloaderwill be removed in the next major release, or earlier if Vaadin removesStreamResource. -
UiComponentUtils#createResource()now returnsDownloadHandlerinstead ofStreamResource.
Upload API Changes
-
fileUploadField, fileStorageUploadField, and WebdavDocumentUploadField were updated internally to use Vaadin’s
UploadHandlerAPI. -
FileUploadSucceededEventnow provides direct access to the uploaded file data. To support this, its generic type signature has changed from<FileStorageUploadField>to<FileStorageUploadField, FileInfo>. See the example.
Upload Component API
The upload component API has changed:
-
The component now uses handler-based configuration. Use uploadHandlerType instead of
receiverType, and uploadHandlerFqn instead ofreceiverFqn. -
Vaadin-deprecated listener methods were replaced:
-
addFailedListener()→addUploadFailedListener() -
addFinishedListener()→addUploadFinishedListener() -
addProgressListener()→addUploadProgressListener() -
addStartedListener()→addUploadStartedListener()
-
-
addUploadSucceededListener()now receives UploadSucceededEvent<V>.
@DialogMode
@DialogMode.modal() is deprecated. Use modality() instead.
Theme Variants Changes
Theme variants were updated, with some removed, some added, and a few changing in behavior:
-
align-startandalign-endwere added for field components. -
always-float-labelis no longer available for field components. -
containedandoutlinedare no longer available for button components. -
icon-on-topmust now be applied to nestedtabelements in tabs and tabSheet. -
dropdown-indicatorsis used internally by dropdownButton to display the dropdown indicator. In Lumo, use theicontheme name when you want to hide these indicators.
Theme variants support now depends on the application theme. Some available only for Lumo, some only for Aura, and most work with both themes. Supported variants are listed in each component’s Theme Variants section. See markdownEditor Theme Variants for an example.
loadFromRepositoryDelegate
The loadFromRepositoryDelegate handler signature has been changed. It now accepts JmixDataRepositoryContext as the second parameter. You should replace FetchPlan with JmixDataRepositoryContext, for example:
// before
@Install(to = "customerDl", target = Target.DATA_LOADER, subject = "loadFromRepositoryDelegate")
private Optional<Customer> loadDelegate(UUID id, FetchPlan fetchPlan) {
return repository.findById(id, fetchPlan);
}
// after
@Install(to = "customerDl", target = Target.DATA_LOADER, subject = "loadFromRepositoryDelegate")
private Optional<Customer> loadDelegate(UUID id, JmixDataRepositoryContext context) {
return repository.findById(id, context.fetchPlan());
}
Studio migrates this code automatically.
See #5139 for more information.
ValueLoadContext Conditions
When using PropertyCondition with ValueLoadContext, do not include the query alias in the property path anymore. Jmix 3.0 now adds the alias automatically, aligning this behavior with regular entity LoadContext.
// before, worked as a workaround
PropertyCondition condition = PropertyCondition.equal("e.username", "admin");
// now
PropertyCondition condition = PropertyCondition.equal("username", "admin");
If you keep the manual alias, Jmix generates incorrect JPQL and the query fails.
See #4371 for more information.
BaseAction
io.jmix.flowui.kit.action.BaseAction and io.jmix.flowui.action.SecuredBaseAction are now self-typed generics. Replace raw usages with a typed action class where possible or use wildcard types, for example:
// before
BaseAction action = getAction();
action.addActionPerformedListener(this::onAction);
// after
BaseAction<?> action = getAction();
action.addActionPerformedListener(this::onAction);
See #5218 for more information.
JmixListMenu
Menu items that execute bean actions are now rendered as real buttons instead of links without navigation targets.
-
The base CSS class name for all menu items changed from
jmix-menu-item-linktojmix-menu-item. -
Bean menu items are now rendered as vaadin-button instead of a RouterLink.
-
Styling that targeted
jmix-menu-item-linkshould be updated to usejmix-menu-item, or the item-specific CSS class namesjmix-menu-item-viewandjmix-menu-item-beanwhere needed.
See #5205 for more information.
UserManager
The io.jmix.core.security.UserManager interface has a new method resetPasswords(). If you have an implementation different from AbstractDatabaseUserRepository, implement this method.
See #5323 for more information.
Enum-backed Configuration Properties
Getter return types changed in the following properties:
-
UiViewProperties.getValidationNotificationType()→Notifications.Type -
UiViewProperties.getValidationNotificationPosition()→Notification.Position -
GridExportProperties.getDefaultColumnsToExport()→ColumnsToExport -
GridExportProperties.getDefaultExportModes()→List<ExportMode>
See #5262 for more information.
OpenAPI Client Generator Configuration
If you use OpenAPI Client Generation, update the configuration in build.gradle as follows:
plugins {
// ...
id 'org.openapi.generator' version '7.23.0'
}
dependencies {
// ...
implementation 'org.openapitools:jackson-databind-nullable:0.2.10'
}
tasks.register('openApiGeneratePetclinic', GenerateTask) {
inputSpec = layout.projectDirectory.file("src/main/resources/petclinic-openapi.yml")
outputDir = layout.buildDirectory.dir("generated/openapi/petclinic")
// ...
configOptions.set([
useRuntimeException: "true",
useJakartaEe : "true",
useSpringBoot4 : "true",
useJackson3 : "true"
])
}
Removed Orphan Timer Metrics
The series jmix_JavaClassLoader_loadClass_* and jmix_AnnotationLockDescriptorProvider_loadConfig_* disappear from /actuator/prometheus. Any external dashboard or alert that references them must be updated.
See #5290 for more information.
Removed Dependencies
XStream has been removed from dependencies of the Audit and Reports add-ons. If you use it in your project, add the dependency explicitly:
implementation 'com.thoughtworks.xstream:xstream:1.4.21'
See #5337 for more information.