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/
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.
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.
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
...
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
...
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
...
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
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:
It copies all the development files (e.g. compiled .class files) from the project directory into the runtime directory, so that the corresponding tomcat/webapps/<app> directory is updated
It then triggers the reloading of the environment - either by restarting the web-application or by using its hot deployment, that is based on exchanging the class loader which loaded the UI-relevant-classes (and by this reloads the classes)
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>
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.
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
pluginPackages=org.eclnt.eclnthotswap
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.
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 develop just as normal:
Change your classes in your IDE.
Change your resource files in the IDE.
Create and edit layout definitions by the CatpainCasa toolset.
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.
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
// ...
}
});