Class HotswapAgentJar

java.lang.Object
com.vaadin.flow.devloop.daemon.HotswapAgentJar

public final class HotswapAgentJar extends Object
The HotswapAgent jar the application JVM is launched with: where it is cached, and how it gets there.

Separate from Launch because two very different callers provision it. The daemon does, at the moment it composes the command line for the application. The build does too, from flow:install-dev-cli, so that a machine prepared while it had network access - a container image, a benchmark sandbox - can run the loop afterwards without any. Both go through this class so there is one pinned version, one checksum and one cache location rather than two that can drift.

The build reaches it by name, through a class loader over this jar: the Maven and Gradle plugins must not depend on the daemon, and the version that has to be provisioned is the one in the jar the project resolves and the CLI will run. So this class name, the VERSION field and the signature of provision(Consumer) are a contract with DevCliInstaller.provisionHotswapAgent that no compiler checks - renaming any of them turns the install goal into a no-op that only warns.

This is the only asset the loop downloads. Everything else it needs - the daemon jar, which is also the javaagent - travels in as a project dependency and is resolved from the local Maven repository.

For internal use only. May be renamed or removed in a future release.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    Names a jar that is already on the machine, which is how an air-gapped setup that never ran the install goal still gets an agent.
    static final String
    SHA-256 of the release asset at URL, verified after download.
    static final String
    Where the pinned VERSION of the agent is downloaded from.
    static final String
    Pinned, never "latest": a changing agent would make applies irreproducible.
  • Method Summary

    Modifier and Type
    Method
    Description
    static Path
    Where machine-level dev-loop assets are cached: the HotswapAgent jar, and nothing else so far.
    static Path
    Where VERSION lives once it has been provisioned.
    static Path
    Ensures the HotswapAgent jar is present and matches the pinned checksum, and answers where it is.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • VERSION

      public static final String VERSION
      Pinned, never "latest": a changing agent would make applies irreproducible.

      The checksum is of the hotswap-agent-<version>.jar release asset at URL, not of the same version on Maven Central - the two are built separately and there is no promise they are the same bytes. Bumping the version means downloading that asset and recomputing this.

      See Also:
    • SHA256

      public static final String SHA256
      SHA-256 of the release asset at URL, verified after download.
      See Also:
    • URL

      public static final String URL
      Where the pinned VERSION of the agent is downloaded from.
      See Also:
    • OVERRIDE_PROPERTY

      public static final String OVERRIDE_PROPERTY
      Names a jar that is already on the machine, which is how an air-gapped setup that never ran the install goal still gets an agent.
      See Also:
  • Method Details

    • cacheDir

      public static Path cacheDir()
      Where machine-level dev-loop assets are cached: the HotswapAgent jar, and nothing else so far.

      Under the ~/.vaadin directory Vaadin already owns, so one download serves every application on the machine and nothing is written into a project. It also survives a mvn clean, which a per-project cache did not.

      Returns:
      the machine-level dev-loop cache directory
    • cachedJar

      public static Path cachedJar()
      Where VERSION lives once it has been provisioned.
      Returns:
      the path of the cached agent jar, which need not exist yet
    • provision

      public static Path provision(Consumer<String> progress) throws IOException
      Ensures the HotswapAgent jar is present and matches the pinned checksum, and answers where it is.

      Downloads only when it has to: an explicit override wins, then an already-cached copy whose bytes still verify. So a machine provisioned once needs no network again - not for the next application, and not after a mvn clean.

      Parameters:
      progress - where to report a download, since it is the one step here that takes long enough to need saying out loud
      Returns:
      the jar to load into the application JVM
      Throws:
      IOException - if the jar cannot be downloaded, or if the bytes in hand are not the pinned ones