Hot Deploy

Jmix supports Hot Deploy technology that makes it possible to apply project changes to the running application immediately, without restarting the application server.

Supported Classes and Resources

The following classes and resources can be hot deployed:

  • View descriptors and controllers

  • Classes used by view controllers by instantiating them or via static methods. Examples of such classes are described in the subsection below.

  • Localized messages

  • Menu

  • Fetch plans

  • Resource roles

  • Row-level roles

Entity classes and Spring beans are not hot deployed.

How Hot Deploy Works

Hot Deploy works as follows:

  • Studio detects changed source files and:

    • if the changed file is a resource file, Studio copies it to the .jmix/conf directory;

    • if the changed file is a Java or Kotlin file, Studio compiles it and copies to the build/classes project directory.

  • When the application opens a view, it loads new classes and resources from the above directories.

Cleanup of the Hot Deploy Directory

The location of the directory for hot deploying resources is determined by the jmix.core.conf-dir application property. This directory may be cleared automatically before application startup:

  • When the application is run from Jmix Studio, the run configuration can include the Clean Hot Deploy Conf Directory Before launch step configured in Run/Debug Configuration Settings. When enabled, this step deletes the directory before startup.

  • For Gradle-based startup, bootRun depends on the cleanConf task, so running the application with bootRun also deletes the directory before startup. This behavior can be disabled in build.gradle:

    build.gradle
    jmix {
        // ...
        confDirCleanupEnabled = false
    }

Studio also sends signals to the application to clear the appropriate caches to make it load the changed resources. These include the messages cache and the configurations of fetch plans, registered views and the menu. Signals are implemented as trigger files created in the .jmix/temp/triggers directory. The location of this directory can be changed using the jmix.core.temp-dir property.

Examples of Hot-Deployed Classes

Here are some practical examples of classes that are hot-deployed when used by view controllers. Note that these are only a few common cases; other classes that meet the criteria (instantiated in the view controller or called via static methods) will also be hot-deployed.

Custom UI Components

If you create a custom UI component and use it in a view, changes to that component will be applied without restarting the application.

An example of such a component can be found in Using Element API.

Utility Classes with Static Methods

Utility classes that contain static methods are hot-deployed when called from view controllers.

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class DateUtils {
    public static String formatDate(LocalDate date) {
        return date.format(DateTimeFormatter.ofPattern("dd.MM.yyyy"));
    }

    private DateUtils(){
    }
}

In the view controller:

@ViewComponent
private TypedTextField<String> textField;

@Subscribe
public void onInit(final InitEvent event) {
    String formattedDate = DateUtils.formatDate(LocalDate.now());
    textField.setValue(formattedDate);
}

Value Description Classes for Charts

For example, classes that prepare or transform data for charts are hot-deployed.

An example of such a class is ValueDescription in the UI Samples.

Hot Deploy Indicator

Studio displays a status indicator icon in the top-right corner of hot-deployable files. This icon, which appears on files such as view controllers, view descriptors, message bundles, roles, and other similar resources, provides at-a-glance feedback on the current hot deployment status for that specific file.

The primary purpose of this indicator is to continuously inform developers about the propagation of their latest source code changes to the running application. The icon’s appearance changes to reflect whether the changes have been successfully deployed, are in the process of being deployed, or if any errors occurred during the deployment process, providing immediate visual feedback on the state of hot deployment.

Let’s examine the different states of the hot-deploy indicator.

  1. Application not running:

    hot deploy ind 1

    The indicator displays with a gray outline. Clicking the indicator will trigger a pop-up message with an option to start the application.

  2. Application running, no file changes:

    hot deploy ind 2

    The indicator displays with a green outline. Clicking the indicator will trigger a pop-up message indicating that the file has not yet been hot-deployed.

  3. File modified, hot deployment available: The indicator turns solid green. Clicking the indicator will trigger a pop-up message with an option to initiate hot deployment.

    hot deploy ind 3

    After hot deployment is initiated, the indicator remains solid green, and the pop-up message displays the time of the last hot deployment:

    hot deploy ind 4
    The application may require 2-3 seconds to reload classes and resources. If you don’t see expected changes in the application, try to refresh the web page again.
  4. Hot deployment failed: The indicator turns red, indicating that hot deployment was unsuccessful due to a compilation error or other issue.

    hot deploy ind 5

Troubleshooting

In some cases, for example, for non-standard multi-module project configurations, Jmix Studio may fail to determine the module compiler output path. This affects hot deploy because Studio cannot properly resolve the classpath needed for the hot-deploy compilation process.

If you encounter this issue, you can manually specify the module compiler output path using a special property in your build.gradle script:

ext.jmixCompilerOutputPath = "build/classes/java/main"

The path should be specified relative to the folder containing the build script. Jmix Studio will resolve this value during Gradle sync and use it in the hot-deploy compilation process classpath.