Java backward-compatibility problems

I have had a maddeningly frustrating time trying to deploy a webapp recently, which makes for a jarring (no pun intended) experience. This boils down to the fact that Java 12 has removed core libraries required by the (long derelict) http-lite library, which in turn is used by my deployment packaging immutant. The result has been compilation failures. Debugging was made all the worse by the expensively-made discovery that both of my computers, which are running Tumbleweed SUSE rolling distribution, can still find the necessary package for a java env variable: export JAVA_TOOL_OPTIONS="--add-modules=java.xml.bind". However, it took a lot of time to realize that the java packages on our Ubuntu server do not seem to have that module anywhere, so the command failed.

Finally, as we were juggling java versions, I faced the conundrum that my user on the server could compile the program, but no one else – including both root, and me -> sudo: root -> su: me – could compile. This turned out to be because somehow my user had a particular lein installed which had bound to the java 8 executable, and everyone else was failing with the system java 12.

/VENTING

So, in conclusion, I am very grateful for the effort made by Cognitect to safeguard compatibility and stability, and the fact that their commitment apparently exceeds that of Oracle and the main Java complex. I sympathize with anyone who has to bump into such fundamental compatibility limits.

Issues on IMMUTANT: https://issues.jboss.org/projects/IMMUTANT/issues/IMMUTANT-645?filter=allopenissues

Old issue (and proposed solution) on httplite, sadly unmaintained: https://github.com/hiredman/clj-http-lite/issues/17

The stackoverflow link you posted has the solution. You just add a couple extra dependencies since the removed core libraries are now regular dependencies.

<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-core</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-impl</artifactId>
  <version>2.3.0</version>
</dependency>

So you translate that to the usual [javax.xml.bind/jaxb-api "2.3.0"] (and the others) for project.clj or deps.edn map and everything should be working without any special command line flags.

1 Like

You’d think so, but including those dependencies in our leiningen didn’t seem to have any effect. I figured maybe it was because of build order or something, or because the problem is being caused by the lein-immutant plugin which requires httplite which has the bad dependencies, and I’m not sure what project.clj jiujitsu is necessary to say “the dependency of a dependency should use the library I’m providing in another dependency”

You ought to be able to do that via the :provided and :exclusions keys in dependencies. It’s not a full accounting of the jujitsu though.

1 Like

Plugins don’t use the regular :dependencies as they are launched as part of the lein JVM not the runtime JVM. So you can probably either “cheat” by creating a dummy plugin which just brings in the dependencies you need but doesn’t do anything else. Or a quick fork of lein-immutant with the dependencies added.

1 Like

Well, the following in my project.clj didn’t work, so maybe forking it is.

  :plugins [[lein-cprop "1.0.3"]
            [migratus-lein "0.7.2"]
            [lein-cljsbuild "1.1.7"]
            [com.sun.xml.bind/jaxb-core "2.3.0.1"]
            [com.sun.xml.bind/jaxb-impl "2.3.2" :provides [javax.xml.bind.DatatypeConverter]]
            [lein-immutant "2.1.0"]
            [lein-garden "0.3.0"]]

I do think that you really would need to create a dummy plugin that declared those dependencies. Just dumping them in there likely isn’t enough for lein to load them but I don’t know how lein loads plugins exactly. lein-immutant fork should be more reliable regardless.