Release 3.1
|
Jmix 3.1 is currently available only as a release candidate. To work with it, use Studio 3.1 from the nightly channel as described in Nightly Builds. The documentation is being updated for this release. |
How To Upgrade
|
To create new projects with Jmix 3.1 or to upgrade an existing project, you need Studio 3.1 or newer, so update your Jmix Studio plugin first. Jmix Studio 3.1 requires IntelliJ IDEA 2026.1 or newer. |
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.8.0
See also the full list of breaking changes that can affect your project after the upgrade.
Updated Dependencies
The following major dependencies have been updated:
-
Spring Boot 4.1
-
Vaadin 25.3
New Features and Improvements
Jmix CLI
Jmix CLI is a new command-line tool that creates Jmix projects without an IDE: in a terminal, in a script, or by an AI coding agent. It uses the same project templates as Studio and adds the Jmix Agent Toolkit to the created project. See Using Jmix CLI for how to install and use it.
Studio Improvements
-
The view creation wizard has a new step for list and master-detail views where you select how users filter the data: genericFilter (the default), a set of propertyFilter components for the attributes you select, fullTextFilter if the Search add-on is included in the project, or no filter.
-
The entity designer lets you define the @LookupField annotation for an entity and for its reference attributes. The view creation wizard takes this annotation into account when it generates components for references.
-
The new Views with Attribute action of the entity designer shows the view components bound to an entity attribute and opens the view descriptor at the selected component. It also lets you add the attribute to the views of the entity. The action is available on the attributes table toolbar and in each attribute row.
-
The new Copy View action creates a copy of a view with its controller, descriptor and messages.
-
The dialog that lists Liquibase changelogs not yet applied to the database now shows the content of the selected changelog. You can use it to review changelogs that come from add-ons.
-
The JPQL designer can be opened from the gutter icon for queries in
LoadContext.Queryand in thesetQueryString()method. -
Studio inspections check the structure of reports defined in Java code that have a streaming band. They report a structure that the reporting engine does not support, for example, a second streaming band, a child band of a streaming band or a dataset that is not SQL or JPQL.
New AI Chat Add-on
The new AI Chat add-on provides UI components for building AI chat interfaces. The answers come from an LLMProvider that the application implements, so the components work with Spring AI, a vendor SDK, or your own service.
-
aiChat is a complete chat with streaming answers, Markdown messages, file attachments and per-message actions. It can be bound to a collection container of your own message entity to save the conversation.
-
aiMessageList and aiMessageInput can be used on their own to build a chat that
aiChatdoes not cover. -
aiCodeBlock shows source code in chat messages and in any other view.
New UI Recovery Add-on
The new UI Recovery add-on keeps unsaved changes of views when the server node restarts, the HTTP session expires, or the browser closes. It saves the changes to the database as a draft while the user works, and offers to restore the draft when the user opens the view again. Drafts are available in a cluster and after a full restart of the application.
Dynamic Model Add-on
The Dynamic Model add-on is no longer experimental. It has the following new features:
-
UI handlers add behavior to views: short expressions that run on button clicks, value changes and view events, and can call application methods marked with
@DynamicModelOperation. -
Full-text search indexes dynamic attributes marked as searchable.
-
Cluster support: a model applied on one node is applied on all other nodes.
-
The Dynamic model: modify settings without data loss role lets users apply only changes that cannot lose stored data.
-
The model history shows all applied versions of the model.
-
You can change the order of attributes.
-
You can set the lookup field type and actions for reference attributes.
-
Menu items of dynamic views can have an icon.
-
The Generate XML button renders a view template into XML that you can edit.
-
Dynamic entities and attributes are shown in the Data Tools views.
AI Tools Add-on
The AI Tools add-on has the following new features:
-
The new @ExcludeFromAi annotation hides an entity or an attribute from the Data Load tools at the code level. Unlike the
jmix.aitools.dataload.*include and exclude properties, the annotation cannot be overridden at deployment time, so the hidden data can be exposed only by changing the code and rebuilding the application. -
The chat UI sets conversation titles automatically. By default, the first user message becomes the title. With the new jmix.aitools.ui.conversation-title-mode property, the model can generate a short title instead, or the conversation can keep the default title.
BPM Add-on
The BPM add-on has the following new features in the BPMN modeler:
-
You can edit the History level of a process along with other process properties. The selected level overrides the history level of the process engine.
-
You can set the
flowable:exclusive,flowable:asyncLeave, andflowable:asyncLeaveExclusiveattributes for tasks, embedded subprocesses, call activities, gateways, and most events. For user tasks, gateways, and events,flowable:asyncis now available as well. See Asynchronous Execution Properties. -
You can add escalation events to processes, set their properties, and manage Escalation definitions in the process properties.
Reports Add-on
The Reports add-on has the following new features:
-
A report band can now be streaming: its rows are read from a database cursor and written to the XLSX document one by one instead of being loaded into memory. To make a band streaming, select its Streaming checkbox in the report detail view or set
streaming = truein the@BandDefannotation. -
The new AI-generated JPQL dataset type lets you describe band data in natural language. In the report detail view, an LLM generates a JPQL query from the prompt, and the view stores it in the report definition. A report run executes the stored query through
DataManagerand applies the data access permissions of the current user.
Grouping Data Grid Add-on
You can preserve the applied column header filters in URL query parameters by adding the groupDataGridFilter element to the urlQueryParameters facet.
Email Sending Add-on
The Email Sending add-on simplifies setting up OAuth2 authentication with Google and Microsoft mail servers:
-
The new Email connection view replaces the OAuth2 token view. It connects a mailbox account using the authorization code flow or, for Microsoft, the device code flow, and stores the refresh token. The view also shows the connection parameters and tests the connection to the mail server.
-
The new jmix.email.oauth2.redirect-uri property sets the redirect URI of the authorization code flow, for example, when the application runs behind a reverse proxy.
-
The add-on sets the
XOAUTH2authentication mechanism itself, so you don’t need to add it tospring.mail.properties.*.
Read Views
The new read views show an entity instance that users cannot edit. A read view extends StandardReadView, loads the entity by its id, and always has a read-only DataContext.
-
You can create read views in Studio using the Entity read view and DTO entity read view templates of the view creation wizard.
-
You can open read views using the ViewNavigators and DialogWindows beans, and using the ViewBuilders bean of the Tabbed Application Mode add-on.
-
If an entity has a read view, the list_read action opens it instead of the detail view in read-only mode. The new entity_read action shows the entity selected in an entity picker.
-
The @ReadViewTemplate annotation generates a read view for an entity at runtime. The Dynamic Model add-on generates read views for dynamic entities that declare a view of the read type.
Resizable Side Panel
Users can now resize the sidePanelLayout component at runtime by dragging the handle on the side panel’s inner edge. Resizing works for horizontal and vertical positions and respects the configured minimum and maximum sizes. The settings facet can save and restore the size selected by the current user.
SVG Component
The new svg component renders SVG markup directly in the view. The markup can be set in the nested content element, loaded from a file using the file attribute, or set in the view controller.
Popover Component
The new popover component is an overlay that opens next to a target component and can contain any components. You can declare it in a view or fragment descriptor and set the target attribute to the id of a component. The popover can open on a click, on hover or on focus, or from the view controller, and it can be modal.
Popover Renderer for Data Grid
The new popover renderer shows long text in a dataGrid column. The cell text is cut with an ellipsis if it does not fit, and a click on the cell shows the full text in a popover. Add the popoverRenderer element to a column in XML or create PopoverRenderer in Java.
Lookup Field Annotation
The new @LookupField entity annotation defines the component that the framework generates for selecting a reference: an entityComboBox with a drop-down list or an entityPicker that opens a lookup view. It is used in genericFilter and propertyFilter parameters, editable dataGrid cells and runtime view templates. Put it on an entity class to apply it to all references to the entity, or on a reference attribute to apply it to this attribute only. You can also set the actions of the component and load the drop-down items in pages while the user types, using a JPQL query or a search by the instance name.
The itemsQuery element of entityComboBox has the new byInstanceName attribute that finds items by the instance name without a JPQL query.
Breaking Changes
Vaadin 25.3
The update to Vaadin 25.3 brings the following changes (see #5720):
-
The image component can’t contain other components anymore.
JmixImagedoesn’t have thesetText()/getText(),setWhiteSpace(),setEnabled()/isEnabled(),add()andremove()methods. In XML, theenabled,textandwhiteSpaceattributes and nested components ofimageare ignored. -
The protected
JmixMenuBarRootItem.updateClassName()method is removed. -
InMemoryUploadHandlerandFileTemporaryStorageUploadHandlernow extend Vaadin’sAbstractUploadHandlerinstead ofTransferProgressAwareHandler.FileTemporaryStorageUploadHandlerdeletes the temporary file when an upload fails or is rejected, and itsgetFileInfo()method returnsnulluntil the current upload creates the file. -
In the Tabbed Application Mode add-on, the
@Pushconfiguration of the app shell is applied beforeUIInitListenerlisteners are called, so a listener can override it. -
Anchor.setHref()andIFrame.setSrc(), as well as thehrefandsrcXML attributes ofanchorandiframe, throwIllegalArgumentExceptionfor a URL scheme that Vaadin doesn’t consider safe, for examplejavascript:. Add the scheme to the VaadinsafeUrlSchemesconfiguration parameter, or usesetUnsafeHref()andsetUnsafeSrc()in code. -
addThemeName("")throwsIllegalArgumentException. -
TreeGridmethodsexpand(),collapse(),expandRecursively()andcollapseRecursively()now takeCollection<? extends T>andStream<? extends T>parameters. Update the signatures of these methods if you override them in aTreeDataGridsubclass. -
Many
VaadinIconconstants and the correspondingJmixFontIconconstants are deprecated.setRole()ofJmixSideDialogis deprecated in favor ofsetAriaRole(), andwithOverlayRole()ofDialogs.SideDialogBuilderis deprecated in favor ofwithAriaRole().
AI Tools Add-on
-
Rows of
JpqlExecutionResult.getRows()andEntityDataLoadResult.getRows()now containnullfor a column that has no value (see #5598). Before, such a column contained an empty string. The rows that tools return to the model also containnullinstead of an empty string. The method signatures are the same, so the compiler doesn’t show the places to fix. Check the values fornullwhen you read the rows:EntityDataLoadResult result = aiDataLoadService.loadData("customers with their email"); for (Map<String, Object> row : result.getRows()) { Object email = row.get("email"); String text = email != null ? email.toString() : ""; // email can be null } -
EntityDataLoadResult.getQuery()now returns the query that was actually executed or failed validation (see #5749). If the generated query was repaired, the method returns the repaired query, and its explanation, warnings,maxResultsandfirstResultcome from the repair. The original query generated by the LLM isn’t available from the result. -
The
AiChatMessageServiceinterface has a newloadLatestMessages()method (see #5649). If you have your own implementation of this interface, implement the method. The chat hub now orders and groups conversations by the time of the last message instead of the creation time. -
A new conversation now gets the first user message as its title (see #5648). Before, it kept the
New AI Conversationtitle. If your code gives a conversation its own title before the first message, the first message replaces this title. To keep your title, callsetTitleMode(AiConversationTitleMode.NONE)on theAiChatFragmentthat shows the conversation. To keep the previous behavior in the whole application, set the jmix.aitools.ui.conversation-title-mode property toNONE.
Charts Add-on
The Charts add-on now uses Apache ECharts 6.1 instead of 5.4 (see #5699). Existing views work without code changes, but charts may look different:
-
The default theme has a new color palette and spacing. The legend is at the bottom center, and the title is at the top center. To get a look closer to the previous version, set
colorPalette="#5470c6, #91cc75, #fac858, #ee6666, #73c0de, #3ba272, #fc8452, #9a60b4, #ea7ccc"oncharts:chart,top="0"oncharts:legend, andleft="0" top="0"oncharts:title. Check charts that have components at the top or at the bottom, for example a sliderdataZoom: they may overlap the title or the legend. -
Axis labels and names are kept inside the chart, and axis names are moved so that they don’t overlap axis labels. To return to the previous behavior, set
outerBoundsMode="NONE"oncharts:gridItemornameMoveOverlap="false"on the axis. -
Rich text styles inherit the font and text shadow settings of the plain label. To return to the previous behavior, add
"richInheritPlainLabel": falsetonativeJson. -
Bar, pictorialBar, candlestick and boxplot shapes don’t go outside the grid anymore. To return to the previous behavior, set
containShape="false"on the axis. -
The second argument of a tooltip
valueFormatterfunction is now the index in the original series data, not the index afterdataZoomfiltering. Update your JavaScript functions that use it. -
Grid.containLabelis deprecated. UseouterBoundsMode="SAME"together withouterBoundsContain="AXIS_LABEL"instead. WhencontainLabelis enabled, theouterBounds*options are ignored.
Email Sending Add-on
-
The OAuth2 token view is replaced with the new connection view, and its id is changed from
email_tokenViewtoemail_connectionView(see #5546). The oldemail/tokenroute still works. Replace the old view id in:-
menu.xml, if your application uses the single menu mode. Otherwise, the main view fails withNoSuchViewException. -
@ViewPolicyand@MenuPolicyannotations of your resource roles. Otherwise, users lose access to the view.
-
-
The add-on doesn’t define the
mailSendTaskExecutorbean anymore (see #5703). Before, Vaadin could use this bean for its asynchronous work, and the application failed to start if it had anotherTaskExecutorbean. Now:-
Code that injects the
mailSendTaskExecutorbean by name fails at startup withNoSuchBeanDefinitionException. Remove such injections. -
Your own bean named
mailSendTaskExecutordoesn’t replace the email sending pool anymore. The add-on ignores it and logs a warning at startup. -
@Asyncmethods and Vaadin asynchronous tasks run on theapplicationTaskExecutorbean of Spring Boot instead of the email sending pool. This pool has a different size and an unbounded queue.
-
-
When OAuth2 authentication is enabled, the add-on checks the configuration more strictly (see #5539):
-
The
spring.mail.passwordproperty is ignored, and the add-on logs a warning. Before, a password set together with OAuth2 authentication made the add-on use basic authentication. -
The application fails to start if
spring.mail.username,jmix.email.oauth2.client-idorjmix.email.oauth2.secretis not set. Before, these errors appeared only when an email was sent.
-
Maps Add-on
Deleting map objects is now controlled separately from modify mode by the featureDeleteEnabled attribute of a vector source (see #5576):
-
A source with
featureModifyEnabled="true"doesn’t show the Delete action by default anymore. SetfeatureDeleteEnabled="true"on the source, or set thejmix.maps.ui.feature-modify-includes-deleteapplication property totrueto keep the previous behavior for all sources that don’t setfeatureDeleteEnabled. -
SourceFeatureDeleteEventandaddSourceFeatureDeleteListener()are moved fromHasFeatureModifytoHasFeatureDelete. ReplaceHasFeatureModify.SourceFeatureDeleteEventwithHasFeatureDelete.SourceFeatureDeleteEventin your code.
OIDC and SAML Add-ons
The following elements of the auto-configuration are renamed (see #5484):
-
OidcAutoConfiguration.DefaulOidcVaadinWebSecurity→DefaultOidcVaadinWebSecurity -
SamlAutoConfiguration.DefaulSamlVaadinWebSecurity→DefaultSamlVaadinWebSecurity -
The
claimsRoleMapperbean inSamlAutoConfiguration→samlAssertionRolesMapper
Update the code that extends these classes or refers to the bean by name.
Reports Add-on
-
The
io.jmix.reports.yarg.loaders.impl.GroovyDataLoaderclass. The add-on usesJmixGroovyDataLoaderfor thegroovyloader type. Unlike the removed class, it checks thejmix.core.unsafe-runtime-features-enabledandjmix.reports.groovy-enabledproperties. -
The
InitializationExceptionandReportingXmlExceptionclasses from theio.jmix.reports.yarg.exceptionpackage. -
The
update()andbatch()methods ofio.jmix.reports.yarg.util.db.QueryRunner. Use SpringJdbcTemplateor JDBC instead. -
The
commitAndClose(),commitAndCloseQuietly(),rollback(),rollbackAndClose(),rollbackAndCloseQuietly(),loadDriver(),printStackTrace()andprintWarnings()methods ofio.jmix.reports.yarg.util.db.DbUtils. -
The
UnoConverter.createAny(Object)method. Usenew Any(new Type(XCell.class), value)instead. -
The
AbstractFormatter.SIMPLE_ALIAS_REGEXPandDataExtractorImpl.EMPTY_MAPfields.
Dynamic Model Add-on
The Dynamic Model add-on now reads the YAML model definition strictly (see #5731). The rules are described in Writing YAML by Hand.
This affects only models that were written or edited by hand in the Code presentation. Models saved from the visual editor always have quoted values and are read as before.
Loaded State of Entity References
An entity instance returned by DataManager.getReference() now reports as loaded only its id and the attributes set on it later (see #5660). Before, EntityStates.isLoaded() returned true for every attribute of such an instance.
Now for a reference:
-
isLoaded()returnsfalsefor all attributes except the id and the attributes set after creation. -
isLoadedSafe()returnsYESorNOand doesn’t call getters. -
isLoadedWithFetchPlan()returnsfalsefor a fetch plan that contains other attributes. -
getCurrentFetchPlan()returns a fetch plan with the id and the attributes set after creation.
This has the following visible effects:
-
A reference is serialized (in REST, BPM process variables, etc.) with only its id and the attributes set on it.
-
A reference doesn’t have the default values assigned on creation in
@PostConstructmethods or field initializers. -
DataContext.merge()of a reference into a context that has the loaded instance doesn’t replace loaded values with nulls.
If your code relied on a reference reporting all attributes as loaded, update it.