Closed little-dude closed 4 years ago
Try using: LEIN_USE_BOOTCLASSPATH=no lein repl
Leiningen uses the bootclasspath by default in 2.9.0. Loading clojure.instant
from the bootclasspath fails because it uses java.sql.Timestamp
, whose module java.sql
is not available to the bootclasspath in the new JDK9 module system.
Related Clojure ticket: CLJ-2077. The patch for that ticket means clojure.instant
is conditionally loaded depending on if the relevant module is available – when we're on the bootclasspath, it's not loaded, which results in: Caused by: java.lang.RuntimeException: Unable to resolve var: clojure.instant/thread-local-utc-date-format in this context
.
Relevant Leiningen commit: technomancy/leiningen@c0eb388176be79167fae736491ffae9ce57bed68
@cichli
so should clojure fix this or leiningen ?
Seems like this is unrelated to Fipp. Closing.
PR #65 mentions bootclasspath, but it's unclear if that has anything to do with the issue of whether or not clojure.instant has been loaded.
To ensure that clojure.instant gets loaded, I've just pushed this commit: https://github.com/brandonbloom/fipp/commit/7cef283d41d1c9afc68ccc712d382dde16aae03a
Please test the newly published version 0.6.19 and let me know if the problem is resolved. If it is not resolved, please let me know:
@brandonbloom So if you're using bootclasspath in a post-Java 9 world, clojure.instant
is not loadable. This is because clojure.instant
relies upon java.sql.Timestamp
, which is no longer on bootclasspath.
You can refer to https://clojure.atlassian.net/browse/CLJ-2077 for confirmation - the workaround placed in clojure.core simply stops trying to load clojure.instant
it if java.sql.Timestamp
is not found, which it won't be if you're using bootclasspath.
With that in mind, you actually can't ensure that clojure.instant
gets loaded - you can only do so if you're not on bootclasspath.
The reason we care about the behavior of bootclasspath is that at least for the moment, Leiningen still uses it. You can pass LEIN_USE_BOOTCLASSPATH=no
to force it to not use the classpath, but at the moment anything consuming Fipp upstream that happens to rely on bootclasspath behavior will crash. The change proposed in #65 was intended to say: if java.sql.Timestamp
can't be found, that means we're probably in a bootclasspath environment, so we shouldn't even try to load clojure.instant
Thanks for the link to CLJ-2077, that clears things up for me.
I'm not sure I like the when-class
solution employed by core. As mentioned in response to #65, that creates an issue with load-order sensitivity. Thanks to the magic of dynamic class loaders, the presence of a class may change after testing for it.
at the moment anything consuming Fipp upstream that happens to rely on bootclasspath behavior will crash
Considering that it looks like bootclasspath is going away, is there any good reason why anything should rely on this behavior? Is there any meaningful disadvantage to setting LEIN_USE_BOOTCLASSPATH=no
?
Thanks to the magic of dynamic class loaders, the presence of a class may change after testing for it.
This is true, but I'd argue that in that case it's the responsibility of the party engaged in dynamic classloading to handle the classloading order in such a way as to achieve the necessary outcome. Dynamic classloading is black magic and the parties engaged in it typically know that there might be dragons.
Considering that it looks like bootclasspath is going away, is there any good reason why anything should rely on this behavior? Is there any meaningful disadvantage to setting LEIN_USE_BOOTCLASSPATH=no?
Is bootclasspath going away? I've only read about libraries getting removed from it, not it going away entirely (I'm not staking a position here, I just literally couldn't find a thread where its absence wholesale was discussed).
Lein continues to rely on bootclasspath because not using it slows down Lein initialization time by about 30%. For them, moving away from bootclasspath would have a negative startup time impact on all of their users, even those who wouldn't otherwise have been affected by bootclasspath issues. Particularly relevant since they like having backwards compatibility to Java 8.
For me (selfishly, as the Ultra maintainer), I see two disadvantages to setting LEIN_USE_BOOTCLASSPATH=no
- it's an extra env var my users have to configure that could be avoided, and it'll slow their lein initialization time by 30%.
Is bootclasspath going away?
Quoting from the JDK 9 Release Notes:
The boot class path has been mostly removed in this release. The java -Xbootclasspath and -Xbootclasspath/p options have been removed. The javac -bootclaspath option can only be used when compiling to JDK 8 or older. The system property sun.boot.class.path has been removed. Deployments that rely on overriding platform classes for testing purposes with -Xbootclasspath/p will need to changed to use the --patch-module option that is documented in JEP 261. The -Xbootclasspath/a option is unchanged.
Thanks for taking the time to provide your perspective, but for the following reasons I'm not going to fix this issue:
1) While I'm sympathetic to Leiningen's desire to accelerate initialization time, the move to remove the bootclasspath feature from the JDK suggests that this is not a good way to go about it. 2) I really don't want to get in to the business of conditional compilation and dependency management with Fipp. Simply put: Fipp depends on clojure.instant. Barring some newly discovered ignorance about bootclasspath, I think Clojure made a mistake in supporting this. 3) Presumably, an alternative workaround is to either (A) not use Fipp during these "boot" scenarios. or (B) alter the bootclasspath to load the necessary code. 4) On a personal note, I don't use Ultra or JDK 9. I do use Whidbey, but it seems to work fine, at least with JDK 8. I don't have a pressing need to upgrade, and if I do, I'll probably eliminate Lein from my workflow entirely. Some of my projects have already moved to deps.edn and the improved clojure.main & clojure.repl bits.
Let me know if I've grossly misunderstood something.
I think your position is fair.
Structurally this is a very complex domain with legitimate motivations for everyone acting. The JDK folks want to minimize attack surface area. The Lein folks want to minimize startup time. The Clojure folks want to maintain backwards compatibility.
The ecosystem in which this problem exists is one that doesn't lend itself to a clean solution, at least for now. Fipp doesn't need to support weird runtime configuration environments. #65 was the lowest-impact change that could have been proposed to accommodate said runtime configuration environments, but I understand why that's not enough to justify merging it.
Hello,
I'm trying to install
ultra
which depends onfipp
but I'm getting the following error:I have the following environment:
I see someone already reported the problem on the ultra repo.
I'm totally new to Clojure so I may be missing to important infos here so let me know if you need anything else.