What’s New

This section covers new features of Jmix framework and Studio 1.1, as well as some breaking changes to be aware of when upgrading from a previous version of the framework.

How To Upgrade

To create new projects with Jmix 1.1 or to upgrade an existing project, you need Studio 1.1 or later, so update your Jmix Studio plugin first.

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 the version of Gradle wrapper to 7.2 in gradle/wrapper/gradle-wrapper.properties.

See breaking changes and known issues below if you experience any problems with the upgrade.

New Features

Support for Java 17

To use Java 17 in an application project, follow the steps below.

  • Download JDK 17 and set JAVA_HOME as described in Setup.

  • In an existing project, open File → Project Structure and select your JDK 17 in the Project SDK field. If there is no JDK 17 in the drop-down list, click Edit next to the field and add your new JDK to the list of SDKs known to the IDE.

    Also, remove sourceCompatibility = '1.8' line in your build.gradle to be able to use the new language features.

    Gradle wrapper in your project must be of version 7.2 or later (see gradle/wrapper/gradle-wrapper.properties). When you upgrade your project from a previous Jmix version, Studio updates the wrapper automatically.

  • When creating a new project, select JDK 17 in the Project JDK field of the new project wizard. If there is no JDK 17 in the list, click Add JDK at the bottom of the list.

If you are experiencing any problems when starting the application on JDK 17, open Gradle Settings in Gradle tool window and make sure that the Gradle VM field contains the same JDK 17 as defined for the project.

Support for Kotlin

To create a new Jmix application in Kotlin, select the Single Module Applcation (Kotlin) template in the new project wizard.

Migration from CUBA

Jmix Studio now provides an automatic procedure for converting a CUBA project into Jmix one. The converted project uses a compatibility module with a set of CUBA APIs and features that were changed or removed in Jmix.

See the Migration from CUBA section for description of the main differences between Jmix and CUBA and instructions on how to migrate your CUBA project to Jmix.

User Substitution

The system administrator can give a user an ability to substitute another user. The substitution means the user has the security permissions and restrictions of the substituted user. For example, if Alice substitutes Bob, she logs in to the application as Alice, but has the Bob’s roles.

To see the feature in action, do the following:

  • Log in as admin and create at least one more user with "UI: minimal access" role.

  • Select admin in the users table and click Additional → User substitution. You will see a list of users that admin can substitute.

  • Add your new user to the list of users substituted by admin.

  • Now you will see that the current user name in the userIndicator component of the main screen has changed to a drop-down list that contains the substituted user. If you select this user, the workspace will change as if you re-login as this user. But all audit features will still register "admin" - the logged in user.

API changes:

  • Added CurrentUserSubstitution bean that can be used to obtain a currently substituted user, an authenticated user, or the effective user (which is substituted user in case of substitution, authenticated one otherwise).

    For example:

    @Autowired
    private CurrentUserSubstitution currentUserSubstitution;
    
    private String getSubstitutedUserName() {
        User substitutedUser = (User) currentUserSubstitution.getSubstitutedUser();
        return substitutedUser == null ? "" : substitutedUser.getUsername();
    }
  • The CurrentAuthentication.getUser() method always returns the authenticated user.

  • The CurrentAuthentication.getAuthentication().getAuthorities() returns authorities of the effective user. That is, in case of substitution, these authorities differ from the authorities of the authenticated user.

Spring Configuration Metadata

Jmix modules now provide Spring Configuration Metadata that allows IDE to autocomplete property names when you edit the application.properties file.

If you have IntelliJ Ultimate, make sure Spring and Spring Boot plugins are enabled, and configure the Spring facet for your project (you will get a notification about it when opening your project). After that, the IDE will show available properties with descriptions and provide autocompletion as soon as you start writing a property name or pressing Ctrl+Space.

Specific Permissions Registry

Now when you add a specific policy to a role using the role edit screen, you can select a policy from the list. Also, the /permissions REST endpoint returns information about all specific policies granted to the current user.

These features use the new SpecificPolicyInfoRegistry bean which is designed to provide information about existing specific policies.

To register a custom policy created in your project, follow the convention described in the SpecificPolicyInfoRegistry Javadoc: create a class extending SpecificOperationAccessContext and provide the policy name to the base constructor, for example:

public class MyAccessContext extends SpecificOperationAccessContext {

    public MyAccessContext() {
        super("myapp.somePolicy");
    }
}

Studio Improvements

Business Process Designer

Business process designer is now available inside Studio. It allows you to create BPMN 2.0 process definitions and save them in your project resources.

If your project includes the BPM add-on, you can create a process definition by clicking New (+) → BPMN Process in the Jmix tool window.

List of Add-ons

The Add-ons section of the Jmix tool window displays all Jmix add-ons included in the project.

Screens in the Jmix Tool Window

The Backoffice UI → Screens element of the Jmix tool window displays all screens of your application.

Inject Dialog

The content of the Generate → Inject dialog has been restructured and cleaned from irrelevant objects. It’s now split into the following categories:

  • Project Beans - Spring beans of the current project

  • Project Properties - configuration property classes of the current project

  • Infrastructure - frequently used framework beans

  • Other Beans - all other Spring beans of the framework and add-ons

  • Other Properties - all configuration property classes of the framework and add-ons

When opened in a screen controller, this dialog also contains elements relevant for UI as before.

Logger Generation

With the Generate → Logger command, you can quickly add a SLF4J logger as a static class variable.

Support for Visual Components

UI designer now fully supports the following visual components: ResponsiveGridLayout, SingleSelectList, MultiSelectList, Charts.

Breaking Changes

Return RowLevelPredicate from predicate policy methods

Predicate policy methods must now return io.jmix.security.model.RowLevelPredicate instead of java.util.function.Predicate. It is required for serialization of security configuration in a cluster.

If you have predicate policies defined by Java interface methods, just replace Predicate with RowLevelPredicate, for example:

@PredicateRowLevelPolicy(
        entityClass = User.class,
        actions = {RowLevelPolicyAction.READ})
default RowLevelPredicate<User> userIsActive() {
    return user -> !Boolean.TRUE.equals(user.isEnabled());
}

If you don’t do this, the application will throw an exception on start, similar to the following:

java.lang.ClassCastException: class com.company.app.security.ViewOnlyActiveUsersRole$$Lambda$753/0x0000000800616040
 cannot be cast to class io.jmix.security.model.RowLevelPredicate

Renamed JmixDataRepository methods

The following two methods of the experimental JmixDataRepository interface has been renamed:

  • findOne()findById()

  • newOne()create()

Fix your code accordingly if you use Spring Data repositories based on JmixDataRepository.

DataGrid always fires EditorClose event

DataGrid inline editor now always fires the EditorClose event. To find out whether it was confirmed or cancelled use isCancelled() method of the event, for example:

dataGrid.addEditorCloseListener(closeEvent -> {
    if (closeEvent.isCancelled()) {
        // closed by Cancel button
    } else {
        // closed by OK button
    }
});

Changed TagField inner HTML

TagField inner HTML layout has been changed: now all its content (tags, field, clear-all button) is placed into one <div> with the jmix-tagfield-layout class. Therefore some CSS selectors for TagField content may not work. If you have defined custom styles for a TagField, rewrite them considering div with the jmix-tagfield-layout class.

Renamed ChangePasswordDialog message keys

Due to refactoring, ChangePasswordDialog localized message keys have been renamed, which can affect a custom localization:

io.jmix.securityui.screen.changepassword/ChangePasswordDialog.currentPassword
io.jmix.securityui.screen.changepassword/ChangePasswordDialog.password
io.jmix.securityui.screen.changepassword/ChangePasswordDialog.passwordRequired
io.jmix.securityui.screen.changepassword/ChangePasswordDialog.confirmPassword
io.jmix.securityui.screen.changepassword/ChangePasswordDialog.captionWithUserName
io.jmix.securityui.screen.changepassword/ChangePasswordDialog.wrongCurrentPassword
io.jmix.securityui.screen.changepassword/ChangePasswordDialog.currentPasswordWarning
io.jmix.securityui.screen.changepassword/ChangePasswordDialog.passwordsDoNotMatch
io.jmix.securityui.screen.changepassword/ChangePasswordDialog.passwordChanged

Known Issues

Sometimes on Windows after rebuilding and restarting the project, the running application contains old classes and resources. The problem is apparently caused by the Gradle 7.2 issue. It seems to be fixed in Gradle 7.3, but it hasn’t been released yet.

There is a workaround: add the following line to the %USERPROFILE%/.gradle/gradle.properties file:

org.gradle.vfs.watch = false

Changelog