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:

  • File → Project Structure → Project → SDK

  • Settings → Build, Execution, Deployment → Build Tools → Gradle → Gradle JVM

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 = false to the vaadin block in build.gradle.

  • Adds @Stylesheet(Lumo.UTILITY_STYLESHEET) annotation to the application class.

  • Migrates compact theme declaration from @JsModule to @Stylesheet.

  • Removes lumoImports from theme.json.

  • Adds offline=false to @PWA annotation.

  • Migrates signature of @Install loadFromRepositoryDelegate for instance loaders.

  • Sets attribute operationTextVisible to false for propertyFilter in 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 JmixUpload about generic type.

  • Parameterizes FileUploadSucceededEvent generic type depending on the field type: FileUploadField or FileStorageUploadField.

  • Removes DropdownButton icon theme name if the text attribute is set.

  • Removes @io.jmix.maps.Geometry annotation.

  • Migrates JmixUserDetails authorities contract in Kotlin projects.

  • Sets jmix.ui.legacy-monitoring-enabled=true.

  • Sets jmix.reports.use-legacy-date-time-types=true and jmix.reports.client.show-report-table-view-in-menu=true if the Reports add-on is included.

  • Sets com.vaadin.experimental.themeComponentStyles=true in src/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:

./gradlew clean vaadinClean

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.databindtools.jackson.databind

  • Nullability annotations of org.springframework.lang package are now deprecated. Replace them with org.jspecify.annotations, for example:

    • org.springframework.lang.Nullableorg.jspecify.annotations.Nullable

    • org.springframework.lang.NonNullApiorg.jspecify.annotations.NullMarked

  • For distributed tracing, switch to the spring-boot-starter-opentelemetry starter 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 @TenantId attribute 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.

aura theme
Dynamic Model add-on with Aura theme

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:

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:

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.

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

  1. 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 SecurityFilterChain as explained in the Custom Endpoints section.

  2. The VaadinWebSecurity class has been removed in Vaadin 25. The FlowuiVaadinWebSecurity class exists, but doesn’t extend the Vaadin’s class anymore. If you have overridden VaadinWebSecurity methods like configure(WebSecurity web), rewrite your configuration using SecurityFilterChain or WebSecurityCustomizer beans as described in the Custom Endpoints section.

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 StoreMainGenerate Liquibase Changelog action, or, if you don’t have a subscription, create a new changelog using the Data StoresMainNewLiquibase 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 Downloader bean now works through DownloaderExportHandler, which implements Vaadin’s DownloadHandler API. As a result, generated URLs now have the VAADIN/dynamic/resource/<random_id> format instead of /download/UUID. Previously, the Downloader bean created JmixFileDownloader, which served a StreamResource. JmixFileDownloader will be removed in the next major release, or earlier if Vaadin removes StreamResource.

  • UiComponentUtils#createResource() now returns DownloadHandler instead of StreamResource.

Upload API Changes

  • fileUploadField, fileStorageUploadField, and WebdavDocumentUploadField were updated internally to use Vaadin’s UploadHandler API.

  • FileUploadSucceededEvent now 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 of receiverFqn.

  • 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-start and align-end were added for field components.

  • always-float-label is no longer available for field components.

  • contained and outlined are no longer available for button components.

  • icon-on-top must now be applied to nested tab elements in tabs and tabSheet.

  • dropdown-indicators is used internally by dropdownButton to display the dropdown indicator. In Lumo, use the icon theme 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-link to jmix-menu-item.

  • Bean menu items are now rendered as vaadin-button instead of a RouterLink.

  • Styling that targeted jmix-menu-item-link should be updated to use jmix-menu-item, or the item-specific CSS class names jmix-menu-item-view and jmix-menu-item-bean where 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.

Changelog

  • Resolved issues in Jmix Framework:

  • Resolved issues in Jmix Studio: