Specifying CLASSPATH in safe, flexible manner

This is how our desktop applications are launched. In this case, it's called DesktopApp (I changed the actual name). As you see, the dependencies are hard-coded, including their versions. In the script below, I included only one (..\lib\poi-5.2.5.jar;), but the bat file actually lists a ton of them. All of them are located in a lib folder. It's not hand-written. Basically, it's going to include all dependencies that are listed in the pom.xml of CommonLib — which is, as the name suggests, a library containing types common for all DesktopApps (e.g. custom Swing components, utility classes). SET CLASSPATH=%OOPATH%;..\lib\DesktopApp.jar;..\lib\CommonLib-SNAPSHOT.jar;..\lib\poi-5.2.5.jar; SET MAIN_CLASS=app.Application START %JAVA_HOME%\bin\javaw %VMARGS% -Xmx512M -classpath %CLASSPATH% %MAIN_CLASS% %* If you update a library's version in the CommonLib pom, this is what's going to happen next: Some customer wants a new DesktopApp (for example, a new feature is developed and they want it ASAP). We install a new DesktopApp. Its bat script is going to append the new library version to the classpath. However, DesktopApp2, which is not updated, still tries to append the old library version in the script. At this point, DesktopApp2 relies on the fact that the old version is still in the lib folder (perhaps, it was put there last time DesktopApp2 was updated). Otherwise, java.lang.ClassNotFoundException would get thrown (assuming the library's types are ever referenced in the executed code). Why is the old version still in the lib? See, we have a separate script that populates the lib with new jars (new libraries or new versions of old libraries). However, it does not empty the folder first. So over time, it gets bigger and bigger, growing essentially infinitely. You can imagine what it's going to look like if you use one of our apps for many years. If there are 100 libraries that were updated 10 times, it's going to contain 1000 jars. Note if lib for some reason is lost, we won't be able to easily recreate it: it has been gradually built, probably over some years, by different scripts. If we run only the latest lib script, only the latest libraries will be put there. Old DesktopApps are all going to crash before we damage-control our way out of it (we use Git, so it's doable). We figured all of this is a price we have to pay to allow independent updates of different DesktopApps. An institution can use the same build of DesktopApp1 for years, but update DesktopApp2 every few months for example (customers may be very assertive on which exact app(s) they wish to update). It may have a dozen of different DesktopApps installed on their numerous machines. We have a ton of customers (not just domestically). We don't update libraries that often. And yet, you may still argue it's madness. So I wonder, what do you think we should do? Preferably, in a way that doesn't derail all of our customers' operations (those are healthcare institutions, it matters a lot).

Jun 19, 2025 - 17:00
 0

This is how our desktop applications are launched. In this case, it's called DesktopApp (I changed the actual name). As you see, the dependencies are hard-coded, including their versions. In the script below, I included only one (..\lib\poi-5.2.5.jar;), but the bat file actually lists a ton of them. All of them are located in a lib folder.

It's not hand-written. Basically, it's going to include all dependencies that are listed in the pom.xml of CommonLib — which is, as the name suggests, a library containing types common for all DesktopApps (e.g. custom Swing components, utility classes).

SET CLASSPATH=%OOPATH%;..\lib\DesktopApp.jar;..\lib\CommonLib-SNAPSHOT.jar;..\lib\poi-5.2.5.jar;
SET MAIN_CLASS=app.Application

START %JAVA_HOME%\bin\javaw %VMARGS% -Xmx512M -classpath %CLASSPATH% %MAIN_CLASS% %*

If you update a library's version in the CommonLib pom, this is what's going to happen next:

  1. Some customer wants a new DesktopApp (for example, a new feature is developed and they want it ASAP).
  2. We install a new DesktopApp. Its bat script is going to append the new library version to the classpath.
  3. However, DesktopApp2, which is not updated, still tries to append the old library version in the script.
  4. At this point, DesktopApp2 relies on the fact that the old version is still in the lib folder (perhaps, it was put there last time DesktopApp2 was updated). Otherwise, java.lang.ClassNotFoundException would get thrown (assuming the library's types are ever referenced in the executed code).

Why is the old version still in the lib? See, we have a separate script that populates the lib with new jars (new libraries or new versions of old libraries). However, it does not empty the folder first. So over time, it gets bigger and bigger, growing essentially infinitely. You can imagine what it's going to look like if you use one of our apps for many years. If there are 100 libraries that were updated 10 times, it's going to contain 1000 jars.

Note if lib for some reason is lost, we won't be able to easily recreate it: it has been gradually built, probably over some years, by different scripts. If we run only the latest lib script, only the latest libraries will be put there. Old DesktopApps are all going to crash before we damage-control our way out of it (we use Git, so it's doable).

We figured all of this is a price we have to pay to allow independent updates of different DesktopApps. An institution can use the same build of DesktopApp1 for years, but update DesktopApp2 every few months for example (customers may be very assertive on which exact app(s) they wish to update). It may have a dozen of different DesktopApps installed on their numerous machines. We have a ton of customers (not just domestically). We don't update libraries that often.

And yet, you may still argue it's madness. So I wonder, what do you think we should do? Preferably, in a way that doesn't derail all of our customers' operations (those are healthcare institutions, it matters a lot).