-
Notifications
You must be signed in to change notification settings - Fork 10.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Guava for Android and Guava for the JRE need separate Maven namespaces #2914
Comments
Seems like a classifier would be far more appropriate. |
That would also work, so long as the JRE version retained the default classifier (which I think is |
See #2839, as well. |
#2839 could also be resolved by adding a classifier. Expecting just the version string to work won't work. |
Can we please get a 23.1 release that just adds the classifiers and stops projects breaking? |
Our understanding was that classifiers do not solve the problem. I'll see if I can dig up past conversations or test it out. |
Despite what Maven's docs say about
...we found that Maven will happily permit a project to depend on both [edit: see also tbroyer on As best we can tell, the only reliable solution is for users to manually request If there's another scheme that could work, we'd be happy to hear about it. |
Then pick a different project ID :) The problem right now is that more and more projects are potentially being broken. |
A different project ID has the same effect as a different classifier, as far as we can tell. |
Using the right terminology now :) So the maven namespace is segmented by group id (which can be The next best solution is to change the artifact id. This will lead to a situation where people might end up depending on both |
@jbduncan, it depends on what you're targeting, and what gets put into your classpath:
Because the packages are the same, whichever is first on the classpath will be selected. In some cases, this will work as expected. In some cases it won't. Because maven's dependency resolution is "novel" at best, which you get is a bit of a crapshoot. Unless you use version pinning, the version dependency appears to be advisory at best. |
Our thinking was that it was pretty bad for people to be able to depend on both What I probably need to understand better are the drawbacks of the current versioning scheme. It sounds like you want to be able to tell Maven "depend on the most recent version?" If we could use a version like [*] mostly: It still requires that you have at least one dep on |
@cpovirk yes there's a problem. Doing that will break android projects. |
@cpovirk, I think your understanding of maven dependency resolution isn't quite right. It does a BFS of dependencies, picking the first one that it finds. Thus, even if something like selenium declares a dep on "23.0-server", unless it's "closer" to the build than the one that specifies "19.0", version 19 will be selected. |
RE: "Doing that will break android projects": Ah, you're saying that, if an Android project tells Maven "use the most recent available version of Guava," it will then get the server version? Good point. RE: "maven dependency resolution": Thanks, I am aware of the BFS. Above you said: "Maven's dependency resolution looks at group and project IDs, and then attempts to find the most recent version." I was figuring that you were using something like Gradle's "newest" strategy or perhaps some plugin that automatically updates your project to depend on the newest versions (update: like this)? I'm trying to understand the places where it matters which version Maven considers to be "newest." |
Re: Android. Yes, that's exactly what I'm saying. It's a thorny problem. |
Re: "guava-server". Not all java implementations are server-side. I think |
Re: "maven dependency resolution" Glad you know about the full horror of how maven selects versions. It's good to have company :) I'm just getting reports from users who are using maven's default versioning strategy (not necessarily using gradle). I guess they're using aether. You know, GH could really do with threading of comments. |
In case it isn't clear, this particular issue Selenium was having was due to leaving the version as open ended:
This allows selenium to specify the minimum required version of guava but anticipating that we will still be compatible with future versions of guava that another project may specify. The problem we encounter is that if another project depends upon us and doesn't specify their version of guava, maven may choose the 'latest' it finds in central... which by timestamp happens to be 23.0-android. Having users not accidentally include both android and jdk 8 versions is certainly a problem... but solving it in this way feels like bad maven practice. It seems like it's a bug for maven to try to figure out a way for everyone to identify two packages that are incompatible with each other. |
(I'm sure I don't know the full horror of Maven dependencies yet, hopefully ever :)) True, "server" is the wrong word. I think that "jre" may technically mean "Oracle," which isn't necessarily what we mean, either. Hmm. (Update: Admittedly "Android" is itself not the best term, since we advise Java 7 users to use it, too.) Sounds like Aether may be "Maven Artifact Resolver" nowadays? The docs best docs seem to be this Wiki. |
Yes, that's the aether version I was referring to. |
I think that #2914 (comment) properly describes the problems that guava users are experiencing, and is what we should be trying to resolve. |
Oops, I think you're right about "jre." Thanks. |
Oof, I can see that this is not easy to resolve. Just reading this comment thread is enough to do my head in. 😜 @lukeis Do you know if the Selenium team ever considered one of the following workarounds?
|
@jbduncan we are currently working around the issue by setting the version explicitly to 23.0. Selenium is highly customizable, in particular with our "Grid / Server" product. It would be a bit unkind to those users to shade a dependency that may need upgrading in a timely manner... we don't always timely upgrade our guava reference and it can be many months between our releases when we all get busy. |
Thanks, @lukeis. That may have been clear to others but was not to me. That does sound like a good reason for making sure that the jre artifact is newer than the android artifact. (As @shs96c noted, that doesn't help Android users, but I think we would have broken any Android users who used open-ended ranges when we released 21.0, which didn't come with an Android version.) I'm guessing that there would still be problems -- say, if Selenium depended on something that requests 23.0-android, might Maven still pick that over the "newer" 23.0-jre, since it was requested specifically? And of course there's the problem I mentioned above in which someone wants 24.0-android and someone wants 23.0-jre: The only solution is 24.0-jre, which Maven is never going to figure out on its own. I will keep thinking about all this. |
@jbduncan: I'm the selenium lead :)
|
@cpovirk, yeah, making sure that the jre version is released after the android version will mask this issue for many users. |
(We will likely keep the main artifact on Java 8, but I don't know that we've made that decision for certain. It's similar to how we stayed on Java 6 and (IIRC) upgraded straight to Java 8 without releasing a Java 7 version.)
We're trying to serve the case of cross-platform libraries, too. It's possible that they could fork or preprocess their code, too, of course, but that has its own tradeoffs. Ideally I should note this in the linked doc someday.
We also promise that it's usable as on the JRE (for Java 7 users). (I don't know enough about AAR to say more than that.)
My understanding has been that users can opt into such enforcement themselves, but we have no way of doing it for them. If users know enough to take action, the solution is generally simple enough (at least once we switch to |
AAR is an Android-specific way of packaging a library. If you've got something that is only meant for an Android app, that's the best way to distribute it. https://gist.github.com/lopspower/6f62fe1492726d848d6d might be useful. |
The only advantage would be to bundle the ProGuard rules so they're used
automatically which seems very low value compared to now shipping 3
artifacts (jdk8, jdk6/7-ish, and android).
…On Fri, Sep 1, 2017 at 1:43 PM Simon Stewart ***@***.***> wrote:
We also promise that it's usable as on the JRE (for Java 7 users). (I
don't know enough about AAR to say more than that.)
AAR is an Android-specific way of packaging a library. If you've got
something that is only meant for an Android app, that's the best way to
distribute it.
https://gist.github.com/lopspower/6f62fe1492726d848d6d might be useful.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#2914 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAEEEWTU-6QCj_ebF-RlcVAaj7MoP0Dhks5seEImgaJpZM4O4ET0>
.
|
You'd be shipping two: just guava as a jar (targeting java 8, as now), and guava as an aar, which android projects could depend on. |
That would then contradict this statement by @cpovirk:
|
An aar would require the artifact only notation in Gradle. I think that if the explicit extension and transitively unqualified dependency of guava were in the tree, then both would be retrieved. If so, this would require Android users to manually exclude which would require a fix to the user's build. That doesn't seem clearer than using a resolution strategy / enforcer to restrict versions. |
This makes Maven consider 24.0-jre to be "newer" than 24.0-android. That's preferable, as discussed in #2914, #2839, and https://docs.google.com/document/d/1NYGbfz56C0Oh4IGymXjeQUVK4FcRiqDbpc4vGLnDMrY/edit# RELNOTES: To upgrade to Guava 24.0, change your version numbers to "24.0-jre." (Or, if are writing an Android app or Android-compatible library, use "24.0-android.") ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=167799453
@cpovirk If we changed |
@yborovikov Isn't |
@perceptron8 for example, java i believe a single sentence in the |
Downside of using Checked these (version |
|
@ben-manes We're trying to achieve something Maven doesn't have a prescribed solution for here. You're right, We would be piggy-backing on this documented Maven feature:
to provide two Guava versions that can be treated equally from version comparison perspective (at least by Maven itself). This approach should resolve this very issue of Maven version comparison treating As for why JBoss switched from |
…anilla versions from 24.0-jre back to 24.0
Copied from the discussion doc shared by @cpovirk: While it's considered bad practice to just tell Maven "use latest version" (or rely on version ranges), there's another practice of assuring (via In our case we try to maintain Java 7 compatibility by using android-flavored guava version, and upgrade to 23.0-android broke the (java 8) builds that depend on the project yet try to enforce the latest versions among shared dependencies - Arguably, java 7 / android builds will experience similar issues (e.g., trying to use Ideally, Guava would produce two versions that are considered equally fresh by Maven tooling - and there is such option: use This would allow a project to pick the flavor it needs while enforcing that the latest (among dependencies) version is being effectively used. (Of course, android builds would still rely on / check that Java 8 features are not being actually used in the execution path of the libraries - but that's unavoidable anyways.) |
I replied to the latest comment on the doc a while back. I still need to go back and reply to the remaining comments on the doc. Sorry that I'm taking so long. For the moment, in any case, we're trying |
@cpovirk yes it does, it just did for me and I had to chase around java dependency trees for 3 hours to figure it out! I'm using Google Cloud java SDK libraries, and they sometimes use the This postfix concept, is a misuse that is incompatible with what a version is supposed to be in the maven echo-system. excerpt from
|
Version should describe a different version of the SAME artifact. If it is a different artifact use a different artifact name! @dbyron0 |
Guava for Android is lacking classes that are provided in Guava for the JRE (notably around support for Java 8 in the immutable collections). The two are not interchangeable.
Maven's dependency resolution looks at group and project IDs, and then attempts to find the most recent version. Because the only difference between the android and JRE versions of guava is the version number, this can result in Java 8 projects getting the Android version of Guava (and, presumably, vice versa).
For reference, at the time of writing search.maven.org believes the most recent guava release is the one for Android.
The correct thing to do is give the Android version a different project ID.
The text was updated successfully, but these errors were encountered: