Using HotSwapAgent with CaptainCasa

Introduction

About HotSwapAgent

HotSwapAgent is a Java VM environment that allows “unlimited runtime class and resource redefinition.“ Which means: classes and resources which are loaded by the Java VM can be changed at runtime without restarting the virtual machine and/or without opening up new class loaders.

Please find details here: http://hotswapagent.org/

Consequence for development

Starting your CaptainCasa based application in an HotSwapAgent environment means that changes to classes that you do during development are directly updating the runtime. You do not have to restart e.g. Tomcat or you do not have to trigger the reload of classes by opening up new class loaders.

Installation

Exchange the Java Runtime!

The CaptainCasa installation comes with a default Java runtime, which is a runtime provided by https://adoptium.net/:

<captainCasaInstall>

    /server

        /jre        <== default Adoptium runtime

        /tomcat

        ...

    A_startserver.bat

    A_startserver_debug.bat

    ...

 

There are several versions of the runtime available in the CaptainCasa download packages. And: you can at any time change the JRE by an other one (other version, other provider, ...).

The runtime is referenced within the batch files that are located in the main installation directory.

Install HotSwapAgent 17 as new runtime

Follow the installation steps on http://hotswapagent.org/mydoc_quickstart-jdk17.html and install the new Java runtime into a parallel directory “jre_hotswap17”:

<captainCasaInstall>

    /server

        /jre             <== default Adoptium runtime

        /jre_hotswap17   <== new runtime

        /tomcat

        ...

    A_startserver.bat

    A_startserver_debug.bat

    ...

 

Add CaptainCasa agent-jar

Open https://www.captaincasa.com/mavenrepository/ and download artifact “org/eclnt/hotswap”.

A file “eclnthotswap-<version>.jar” will be downloaded. Remove the version and store the file inside the CaptainCasa installation. You may choose any directory (but NOT server/tomcat/libs!) - we usually place the file in the “server”-directory:

<captainCasaInstall>

    /server

        ...

        /jre_hotswap17   <== new runtime

        /tomcat

        ...

        eclnthotswap.jar <== agent-plugin file

    ...

 

Update the batch files “A_startserver*.bat”

Both batch files need to be updated, so that the right JRE is used and so that the Java agent files are invoked.

...

cd server

set JAVA_HOME=jre_hotswap17

set JRE_HOME=

...

set JAVA_OPTS=-Xmx1024m -Xms128m -XX:HotswapAgent=fatjar -javaagent:jre_hotswap17\lib\hotswap\hotswap-agent.jar -javaagent:eclnthotswap.jar

...

If running Tomcat 10 - Add basic configuration file to tomcat/lib

HotSwapAgent comes with a Tomcat plugin. This plugin is not required for CaptainCasa development activities. - Even worse: the plugin is running into errors when being started with Tomcat 10.

You can switch off plugins of HotSwapAgent by a configuration file (the same file that is mentioned later on in chapter “Adapting a CaptainCasa project”). The configuration file is read per class loader, so for switching off the Tomcat plugin on Tomcat-level you need to define the configuration file...

tomcat/lib/hotswap-agent.properties

 

...with the following content:

# Comma separated list of disabled plugins
# Use plugin name - e.g. Hibernate, Spring, ZK, Hotswapper, AnonymousClassPatch, Tomcat, Logback ....
disabledPlugins=Tomcat

Adapting a CaptainCasa project

Switch off explicit reloading

The CaptainCasa toolset needs to be informed that a project is run using the HotSwapAgent.

Why? - By default the CaptainCasa toolset deploys a project and executes the following two steps:

In the HotSwapAgent environment we do not want any explicit reloading of classes by re-starting parts of the server - we want the HotSwapAgent to update the currently loaded classes “on the fly”!

Open the file “.ccproject” in the main directory of your project and update the line “reloadwebapp” to be “false”:

<project ...

         reloadwebapp="false"

         ...>

    ...

    ...

</project>

 

Switch off Hot Deployment

CaptainCasa's own hot deployment separates the classes that are compiled in your project into the ones that are copied to “tomcat/webapps/<yourapp>/eclnthotdeploy/classes” and the ones the are copied to “tomcat/webapps/<yourapp>/WEB-INF/classes”.

When using HotSwapAgent then all classes must be located in the “.../WEB-INF/classes” directory! So switch off hot deploymnet if you use it.

The simplest way for switching off hot deployment is to use the CaptainCasa toolset's configuration:

Make sure that “Hot Deployment is active“ is deselected.

Tell the HotSwapAgent what to do

Add the file “hotswap-agent.properties” to the resource part of your project.

For Maven/Gradle projects the file is placed at:

<projectDir>

    /src

        /main

            /resources

                hotswap-agent.properties

 

For projects following the “simple project structure” the file is placed at:

<projectDir>

    src/

        hotswap-agent.properties

 

Define the following content of the file:

extraClasspath=

watchResources=tomcat\webapps\hotswapagent\WEB-INF\classes

webappDir=

disabledPlugins=

autoHotswap=true

LOGGER=info

 

The file structure is explained in https://github.com/HotswapProjects/HotswapAgent/blob/master/hotswap-agent-core/src/main/resources/hotswap-agent.properties - please check this link for more details.

Clean and deploy project

Now clean up the runtime side and start “Cleanr and deploy server” from the CaptainCasa toolset.

A dialog will show up that tells you to stop the Tomcat running your application. Stop your Tomcat instance (if running) and then execute the “Clean and deploy”. Start your application Tomcat afterwards and you can start with development.

Deploy the project and start developing!

Deploy the project and develop just as normal:

Whenever taking over your compiled classes from the project into the Tomcat runtime, you use the “Deploy” function of the toolset:

You see: there is only one explicit “Deploy” function left: “Deploy server - Copy only”. The “normal” deploy functions for copying and restarting part of the server are disabled.

So “Deploy” will only copy the development artifacts into the Tomcat and will leave the code exchanging to the HotSwapAgent. You will see that class changes are automatically taken over - and you can continuously develop without restarting Tomcat.

Buffering “class”-dependent information

Now that classes are updated during runtime you need to identify scenarios in your code that buffer information that contains reflection information about classes.

Example: for a class you buffer the list of properties (set/get-implementations) that is provided by the class.

If the class changes then you have to re-read the corresponding information so that your buffer reflects the current version of the class.

You may register to CaptainCasa's class “ResetBuffers” and get notified when you need to refresh your caches due to an update of classes:

ResetBuffers.addListenerClassSwap(new IResetBuffer()

{

    @Override

    public void reset()

    {

        // ...

        // reset internal buffers

        // ...

    }

});