Truth extensions causing rest of project to downgrade to guava android - google-truth

If I add the com.google.truth.extensions:truth-proto-extension:1.1 jar to my bazel workspace, it seems to totally nuke the classes from com.google.guava:guava:28.2-jre, resulting in errors like
import static com.google.common.collect.ImmutableMap.toImmutableMap;
^
symbol: static toImmutableMap
location: class ImmutableMap
java/com/google/fhir/protogen/ProtoGenerator.java:316: error: cannot find symbol
.collect(toImmutableMap(def -> def.getId().getValue(), def -> def));
^
symbol: method toImmutableMap((def)->def[...]lue(),(def)->def)
location: class ProtoGenerator
Your documentation says
One warning: Truth depends on the “Android” version of Guava, a subset of the “JRE” version.
If your project uses the JRE version, be aware that your build system might select the Android version instead.
If so, you may see “missing symbol” errors.
The easiest fix is usually to add a direct dependency on the newest JRE version of Guava.
Does this mean anything other than the maven dep on com.google.guava:guava:28.2-jre? If not, what's the next easiest fix?

The key word here is "newest": You'll need to depend on (as of this writing) 30.1-jre. I have edited the docs to emphasize this.
(You can see the newest version in various locations, including: Maven Central, Maven Central Search, the Guava GitHub page.)
The problem is:
Some tools (including Gradle as well as the maven_install rule from Bazel's rules_jvm_external) pick the "newest" version of any given artifact among all versions found in your transitive dependencies.
Truth 1.1 depends on version 30.0-android.
30.0-android is considered to be "newer" than 28.2-jre (because 30 is greater than 28).
The -android releases lack the Java 8 APIs.
(So you can actually fix this by depending on any -jre version from 30.0-jre up: 30.0-jre is considered "newer" than 30.0-android because of alphabetical order. Fun!)
Unfortunately, the Maven ecosystem doesn't support a good way to offer 2 "flavors" of every release (JRE+Android). (People often suggest the Maven "classifier," but that does not actually solve the problem.)
For the future:
Gradle: Gradle is working with us to provide its own solution, but it's not quite ready yet.
Maven: Maven is unlikely to provide help. (It doesn't even try to pick the "newest" version, let alone support "flavors.")
Bazel: I don't know if rules_jvm_external (which uses Coursier) has any plans to support "flavors." (Editorializing a bit: In an ideal world, I would rather specify all my repo's transitive dependencies and their versions myself, rather than having the build system try to work it out for me. That can help avoid surprises like this one. But that brings its own challenges, and we've made only incremental effort toward addressing them in our own Bazel-based projects.)

Related

How to change play framework dependency version

I want to change one of my library to the latest version. where to find the version of the dependency in play.
In general, you can see a list of Play's direct dependencies by checking the project/Dependencies.scala file in the source code for that version of Play. For version 2.4.3, that file is here: https://github.com/playframework/playframework/blob/2.4.3/framework/project/Dependencies.scala
In the specific case of Jackson, the group ID and module structure changed between Jackson 1.x and 2.x. Play 2.4.3 is using Jackson 2.5.4. If your project depends on Jackson 1.8.5, this dependency isn't coming from Play, but from some other source.
You can use the sbt-dependency-graph plugin to view the full tree of transitive dependencies and see where it is introduced.
To update to a newer version, you can add a direct dependency to your build.sbt with the desired version:
libraryDependencies += "org.codehaus.jackson" % "jackson-mapper-asl" % "1.9.13"
This will override the version requested by other libraries; by default, sbt will use the greatest version requested.
However, there are a few things to keep in mind:
Jackson is composed of several sub-modules. If you are using several of these in the same project, including transitively, it's a good idea to use the same version of all of them. This might require adding additional dependencies to your project to keep them all in sync.
When upgrading dependencies in your application that are also used by other libraries it depends on, you'll need to consider backward compatibility. Jackson is not always fully backward compatible between minor versions, so if you update to a newer version of Jackson than what your libraries were designed to use, you might encounter problems at runtime.
Using both Jackson 1.x and 2.x in the same project is possible, since they have different group IDs and Java package names, but it may be confusing and error prone. If you can, it would be better to standardise on the Jackson version that is used by the Play Framework version you choose.

Can MR-Jars overwrite classes from other jars?

I have a jar that works on Java 8.
I would like to create a new jar, that is going to be Multi-Release JAR but empty, just with 'patched' classes in META-INF/versions.
I would like to have a separate jar, so people can include it on Java9, otherwise, they use the default one. Why? Because so many tools are not yet prepared for Java9 MR-Jars.
Would this be possible? Would Java9 MR-Jar override classes from others jars?
Why?
The idea behind Multi-Release jars is that they provide simple patching. In my humble opinion, the way MR jars works is not satisfying.
There are two reasons why I can't make 2 separate Jars:
try to make cross-compile source base that works with Java8 and Java9. You would end up with folders like java, java8 and java9... and then have the build produce two jars, two poms... Yeah, good luck.
Imagine that I even build a library for java9. What about transient dependencies? That would mean that all other libraries that uses mine, would need to have jre8 version that depends on my jre8 version. Just because there is Java9 version!
Here is the story:
My A is a Java library built on Java8 but packaged as Multi-Release Jar which means it contains additional classes for when jar is run on Java9. Additional classes are built separately on JDK9 and I copied them manually (yeah, I know, but it works for now).
Unfortunately, some tools and servers (Jetty) are not aware of MR Jars and this makes them NOT working.
For that reason, I have A-jre8 version of my library, that comes without any extra classes, so servers can use it.
However, if user is using library B that depends on my A, he will still get the MRJar version of A and this will fail again. I want to be able to prevent this somehow. And I can't say to B: hey, could you make B-jre8?
Possible solution
JAR is just about packaging!
Allow the separate jar to patch existing jar.
In my case, I would just include A.jar9 and Java would consider A.jar and A.jar9 together as a package. No need for META-INF/versions. Very clean. And, best of all, it would help in situations like above! If run on Java8, the jar9 jar would make no difference; if run on Java9 the jar9 jar would patch the jar with the same name. Simple as that. No transitive dependency hell.
Rename classes in META-INF/versions.
Common Oracle, have you ever heard about the classpath scanning? Could you at least rename the classes in versions to e.g. *.class9 so not to be caught by existing classpath scanners.
As it is today (Java v9.0.4) - no.

Implementation of frama-clang

So far I've found the STANCE project (Stance project website) a reader (found on the website) and a presentation (also found on the website). Also, apparently there will be a frama-c day taking place on June 20th where frama-clang is going to be introduced.
However, I am wondering whether there is an implementation to play around with frama-clang.
Since a few minutes, there is: http://frama-c.com/frama-clang.html (don't forget to read the Caveat part). It is released as a new plug-in, under LGPL2.1. Frama-Clang is compatible with Frama-C Aluminium (i.e. the latest Frama-C version so far), and clang/llvm 3.8 (be sure to either use the dev packages of your distribution or compile clang by hand).

NuGet Versioning Is Backwards

I've been working to get NuGet versioning squared away in my ASP Core project and have come across some odd behaviors and would like to ask why they decided to do it this way.
1) Choose the lowest version in a range.
ex: [1.0.0, 2.0.0) Does not mean choose the most recentversion in 1.X.X but choose the lowest version, basically always 1.0.0 and never update.
2) Setting the specific version chooses a different version
ex: "1.0.0" will really select "1.0.X".
This one really concerns me. I want to make sure that when I tag code, using a specific version, all future builds will always use the same version. With this implementation, builds are not guaranteed to be reproducible!
I'm coming from using Maven and NPM and am trying to keep an open mind to other ways of doing versioning, but these two baffle me.
Please help me understand why they would do this, basically backwards from other package manager solutions.
You can use a floating version if you want the most recent version, ex 1.0.*.
I think you're incorrect here. If 1.0.0 is requested, it'll install 1.0.0 if 1.0.0 is available on the NuGet server. If it's not found on the server, it'll install the next closest version found, 1.0.1.
This is pretty well documented at
http://docs.nuget.org/consume/ProjectJson-Dependency#dependency-resolution-in-nuget-v3-/-project.json

Enforce Javadoc version in SBT

I just started to work on a large project that uses SBT for building. I got a new computer with Java 8 installed, but the rest of the team still uses Java 7. That's not a problem as far as the code goes because we're all set to generate v7 byte-code.
The problems arise when attempting to publishing the project using the publishLocal action. Please keep in mind though that I am very new to SBT and some things I say/assume may not be accurate.
We use sbt 0.13. When I run the command sbt publishLocal, it runs the doc action, which in turn runs javadoc to generate the documentation. Since I have java 1.8 installed, it uses the corresponding version of javadoc, which let's be honest is a real pain in the neck, complaining about every single missing #return or #param, self-closing elements (e.g. "<p/>") and such, and returning a non-zero value because of this, thus making the publication fail. However, as I mentioned, the project is fairly big and, although it would be better to complete the javadoc documentation, it's not feasible at the moment.
Luckily, javadoc 8 provides an option do disable the pedantry: -Xdoclint:none will make it quiet about pretty much anything, allowing me to run the publish action by adding it to the javacOptions.
However, as I said, the other team members are still using java 7, and, unfortunately, javadoc 7 does not support that option, so if I push the build.sbt file with this option it will fail on other machines.
So now I'm wondering what I can do. The way I see it, there's a number of options, none of which seems "simple enough" to fix that stupid problem:
downgrade locally to java 7 (not a big fan of having two concurrent versions lying around)
have all other team members upgrade to java 8 (pain for them)
fix all javadoc problems in the whole project (pain for everyone)
Hopefully, there's another option I'm missing that would allow me, for instance, to set the javadoc options based on the java version? Or anything else that doesn't require touching anything else than the build.sbt file...
Thanks!
David
Yes, you can set the Javadoc options based on the Java version:
javacOptions in Compile ++=
sys.props("java.version").split('.') match {
case Array("1", n, _*) if n.toInt <= 7 =>
Seq()
case _ =>
Seq("-Xdoclint:none")
}

Resources