Additional build.gradle configuration

In some cases, out of the box configuration is insufficient. You need to explicitly set some configuration. To get an idea about this, start off by having a look at the rebel.xml that was generated based on the defaults, and figure out where is it going wrong. You can override the default settings or customize the behavior of the JRebel Gradle plugin by adding a rebel {} element into your build.gradle, specifying any of the parameters below:

rebel {
  /*
   * alwaysGenerate - default is false
   *
   * If 'false' - rebel.xml is generated if timestamps of build.gradle and the current rebel.xml file are not equal.
   * If 'true' - rebel.xml will always be generated
   */
  alwaysGenerate = true

  /*
   * showGenerated - default is false
   *
   * If set to true, generated rebel.xml will be printed out in console during the build, so you can immediately see what was generated.
   */
  showGenerated = true

  /*
   * rebelXmlDirectory - default is 'build/classes'
   *
   * Output directory for rebel.xml.
   */
  rebelXmlDirectory = "build/classes"

}

Configuring <classpath>

The <classpath> element in rebel.xml defines which locations are monitored by JRebel for new versions of your classes. If you use Gradle’s Java or War plugin, the plugin will ask for the classes output location from your Gradle project model. In many cases this will be sufficient to make class reloading work (you just have to check that your IDE is also auto-compiling your classes into that same directory). In that case, you can just completely leave out the classpath { .. } block and the defaults will be used.

If for some reason the plugin is not getting it right, or you want to add additional classpath locations to your rebel.xml or explicitly fine-tune excluded or included resources, you can do so by providing classpath { .. } section in your build.gradle DSL:

rebel {
  // (other config)

  classpath {
    resource {
      directory = "build/main/other-classes-dir"
      includes = ["**/*"]
      excludes = ["*.java", "*.properties"]
    }

    // the default element
    resource {}

    resource {
      directory = "build/integration-tests/classes"
    }
  }
}

Each resource {..} element will define one classpath search location in your rebel.xml. The empty resource {} element has a special meaning – this is a placeholder for the default classpath location asked from the Java or War plugin. It can be used to control the order where the default location will be placed in the generated rebel.xml. For example, the above configuration would generate a rebel.xml that instructs JRebel to search for a class from these directories in that same order:

  1. build/main/other-classes-dir

  2. [the default compilation output directory known by your Gradle Java plugin]

  3. build/integration-tests/classes

When you omit the empty resource {} block, the default classpath will be added as the first element into your rebel.xml. Should you want the default classpath to not appear at all, use the omitDefault configuration option:

rebel {
  // (other config)

  classpath {
    // don't add the default classes target directory
    omitDefaultClassesDir = true

    // don't add the default resources directory
    omitDefaultResourcesDir = true

    resource {
      directory = "build/main/other-classes-dir"
      includes = ["**/*"]
      excludes = ["*.java", "*.properties"]
    }
  }

}

Customizing the root path

You have the option to explicitly specify the root path of your workspace. This is useful when the JRebel Gradle plugin incorrectly receives it by default or when you have multiple symlinks/aliases for the same folder (and you want to specify which one to use).

Notice that for default resources, the plugin will check if the default directories prepended by this workspace root path actually exist. When not, they will not be added to rebel.xml. Non-default locations (the ones manually defined in classpath { .. } and web { .. } blocks) are added even when they do not exist at the moment of the plugin execution.

You can add the rootPath configuration option to your build.gradle as all the other configuration options:

rebel {
  rootPath = "/opt/my-project"
}

This is not ideal when the configuration is shared using a SCM and when workspace paths do not match in different environments. In these cases, it is better to provide the configuration option in your personal gradle.properties file that is not added to the SCM:

rebel.rootPath = /opt/my-project

You can also provide it directly on the command line:

gradle build -Prebel.rootPath=/opt/myproject

This option can be used to generate a rebel.xml that contains a placeholder root directory. This way, every user can specify the value for it via a JVM argument when executing their JRebel-enabled JVM:

build.gradle:

rebel {
  rootPath = "\${my-workspace}"
  classpath {
    resource {
      directory = "build/classes/main"
    }
  }
}

Fragment of the generated rebel.xml:

<classpath>
  <dir name="${my-workspace}/build/classes/main">
  </dir>
</classpath>

When running the JVM, every user would add an extra JVM argument: -Dmy-workspace=/opt/my-project.


Configuring <web>

The <web> element is valid for WAR projects and lets you map specific locations of your workspace against specific locations inside your WAR archive.

For example: your WAR contains a folder /WEB-INF/jsps, the contents of which come from your workspace folder src/main/jsps. To have the changes you make to JSPs in your workspace be immediately available in your deployed application, you have to define a mapping in your rebel.xml.

The corresponding mapping is created by the first resource { .. } block in the example below:

rebel {
  // other config ..

  web {
    resource {
      directory = "src/main/jsps"
      target = "/WEB-INF/jsps"
    }

    resource { }

    resource {
      directory = "src/main/WEB-INF-resources"
      target = "/WEB-INF/"
      includes = ["**/*.xml"]
      excludes = ["*.java", "*.groovy", "*.scala"]
    }
  }
}

The empty resource {} block here has similar meaning and properties as the one in classpath {..} configuration block. It can be used to control the placement of the default resource-mapping element. The default resource-mapping maps your WAR’s root to the main webapp directory known by Gradle’s project model. Here you can also use the omitDefault setting to completely exclude the default configuration from the generated rebel.xml:

rebel {
  // other config ..

  web {
    omitDefault = true
    resource {
      directory = "src/main/jsps"
      target = "/WEB-INF/jsps"
    }
  }
}

Once again, omit the web {..} configuration block as a whole if you are satisfied with the defaults.


Duplicate rebel.xml (since Gradle 7.x)

If there is already rebel.xml present among the source files then the behavior will depend on Gradle version. Versions below 7.0 do not require any additional configuration and the generated rebel.xml will be included to the build result by default. Since Gradle 7.0, duplicatesStrategy must be configured in build.gradle in order to prevent a duplicate entry error at build time:

processResources.duplicatesStrategy='include'

The value 'include' will force the generated rebel.xml to be copied to the build result. Contrariwise, 'exclude' will favor rebel.xml that is present among the source files. See Gradle API documentation for additional information.