Skip to content
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

Cannot resolve external dependency com.google.googlejavaformat:google-java-format:1.3 #120

Closed
arulrajnet opened this issue Jun 10, 2017 · 21 comments

Comments

@arulrajnet
Copy link
Contributor

arulrajnet commented Jun 10, 2017

Recently I have upgraded to spotless 3.4.0. Gradle 3.5 and Java 1.8
My spotless config

buildscript {
  repositories {
    mavenCentral()
    maven { url 'https://plugins.gradle.org/m2/' }
  }
  dependencies {
    classpath 'com.diffplug.spotless:spotless-plugin-gradle:3.4.0'
    classpath 'com.google.googlejavaformat:google-java-format:1.3'
  }
}

apply plugin: com.diffplug.gradle.spotless.SpotlessPlugin

spotless {
  java {
    googleJavaFormat('1.3')
    custom 'Lambda fix', { it.replace('} )', '})').replace('} ,', '},') }
    importOrder(['java', 'javax', 'org', 'com'])
    trimTrailingWhitespace()
    removeUnusedImports()
  }
  format 'misc', {
    target '**/.gitignore', '**/*.gradle', '**/*.md', '**/*.sh'
    indentWithSpaces(2)
    trimTrailingWhitespace()
    endWithNewline()
  }
}

I am getting following error.

:spotlessJava
You probably need to add a repository containing the '[com.google.googlejavaformat:google-java-format:1.3]' artifact, e.g.: 'buildscript { repositories { mavenCentral() }}'
org.gradle.api.artifacts.ResolveException: Could not resolve all dependencies for configuration ':detachedConfiguration1'.
        at org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration.rethrowFailure(DefaultLenientConfiguration.java:192)
        at 
 (tons more)

If I downgrade to 3.0.0 its just working fine for the same config.


EDIT by @nedtwigg: this is a long thread, but the resolution was that the buildscript block above must appear in build.gradle, it's not enough for it to be appear in a separate file, such as spotless.gradle, which gets included.

@nedtwigg
Copy link
Member

At the top of the error message, it says:

You probably need to add a repository containing the '[com.google.googlejavaformat:google-java-format:1.3]' artifact, e.g.: 'buildscript { repositories { mavenCentral() }}'

If you add buildscript { repositories { mavenCentral() } }, it will fix your problem. This was changed in Spotless 3.3.0, you can see the reasoning in #99.

@arulrajnet
Copy link
Contributor Author

Please check my spotless config mavenCentral() is already there in repositories. I have added google-java-format as dependencies too.

@nedtwigg
Copy link
Member

Does your project have subprojects? Your project file as written above works for me. If you have subprojects, you might need a block like this:

subprojects {
  buildscript {
    repositories {
      mavenCentral()
    }
  }
}

@arulrajnet
Copy link
Contributor Author

@nedtwigg thanks for your commitment. I don't use subproject, its just plain vennila gradle java project.

To reproduce that clone this repo https://github.com/arulrajnet/gradle-java-template . Then just run gradle spotlesscheck . You will get the above mentioned error.

@nedtwigg
Copy link
Member

The code you linked to does not have buildscript { repositories { mavenCentral() } }. If I add that little snippet to the code, then it works.

@arulrajnet
Copy link
Contributor Author

This spoless.gradle file already has that snippet.

But adding that snippet in build.gradle solves the problem. Thanks

@nedtwigg
Copy link
Member

Ahhhh. Interesting. I've never quite understood how include works, and now I understand it less than ever ;-) Glad you got your problem solved, and thanks for sharing the journey here, I'm sure others will bump into this at some point as well :)

@fvgh
Copy link
Member

fvgh commented Jun 12, 2017

The problem is that spotless takes the buildscript from each individual project.
But a buildscript closure is bound to the underlying script.

This is also the reason why you have to configure the repository for all sub-projects. I personally find this not so intuitive. Normally I would expect that the buildscript is used, where apply plugin for spotless is called.

When applying the new spotless version to Junit, there were similar problems.

@nedtwigg If you agree to my proposal (using buildscript where the apply plugin is called), I can have a look whether/how the behavior can be changed.

@nedtwigg
Copy link
Member

If it's possible, I'm all for it! Another possible answer is to use the buildscript for the root project. I think it's reasonable to have different repositories for the build than for the artifacts being built (this was the usecase which drove #99 in the first place), but it's harder to understand needing different buildscript repos for different projects...

@fvgh
Copy link
Member

fvgh commented Jun 12, 2017

rootProject is possible, but still does not help (at least according to my understanding of the Gradle Doc) if you use apply plugin and have your spotless config in a separate script, which I think is quite common scenario.
Let me look for the right hook and the solution will cover (I'll add tests 😄 ) both scenarios.

@fvgh
Copy link
Member

fvgh commented Jul 2, 2017

@nedtwigg As you assumed, it is not possible to access the buildscript from which the spotless has been created. I looked at the Gradle code and I am pretty sure that I have not missed anything.
What I currently not fully understand are our needs. Do we (except for snapshots and testing) need any other repository than mavenCentral?
I provided a draft proposal which always adds mavenCentral to the end of the project build repositories if it is missing. Since gradle uses the first match, this solution should not conflict with any user testing of mavenLocal or proxy configuration.
Wouldn't that solve 99% of the user problems?
I tested it briefly with JUnit and provided a simple unit test.
If you see no conflicts and agree that this should meet most users needs, I would make some more checks and finalize the proposal.

@nedtwigg
Copy link
Member

nedtwigg commented Jul 4, 2017

This makes me a little nervous. It's not uncommon for a company to proxy all access to external repositories, so automatically adding mavenCentral is a fairly promiscuous behavior. One reason for this is to ensure that all artifacts from the public internet have a local proxy, and the second more important reason to proxy is so that every library can be vetted by a security team before it is allowed to be part of the build.

The nice thing about the "root project" workaround I mentioned above is that we would never add a repository that the user hasn't already approved.

@fvgh
Copy link
Member

fvgh commented Jul 4, 2017

As stated before, the solution does not conflict with a proxy. I use Archiva myself, followed the gradle documentation for integration.
As long as any repository has been specified by the user in any of its underlying scripts, that one is asked before the mavenCentral my solution adds dynamically.
The gradle proxy documentation and the that gradle provides repo naming in the API just gave me the idea, that this modification by plugin seems to be a way Gradle wants such problems to be solved and not a hack. I see no other reason why gradle should expose the names of their "internal "defaults.

The drawback with the "root project" is that it does not work for the problem @arulrajnet described.

@nedtwigg
Copy link
Member

nedtwigg commented Jul 4, 2017

As long as any repository has been specified by the user in any of its underlying scripts, that one is asked before the mavenCentral my solution adds dynamically.

So let's take the case where the company proxy only contains deps that have been approved by a security team. Somebody bumps a version number to something which hasn't been approved, but they won't notice because it will get downloaded from mavenCentral(), even though they never once asked that mavenCentral be added.

I agree that the root project workaround won't fix @arulrajnet's problem, but would it fix your problem with junit? If so, I think we should improve the error message to include

NOTE: the buildscript block must appear in a build.gradle file, this won't work:
include 'myScriptWithBuildScriptBock.gradle'

@fvgh
Copy link
Member

fvgh commented Jul 4, 2017

To be hones I consider your example a little bit far fetched:

  1. You describe a scenario where the company security is not only worried about the libraries included by the software shipped to the customer, but also about build tools (we are only talking about the buildscript dependencies). I think this is very rare.
  2. This company security does not prevent access to Maven Central from developer workstations. I think this will never be the case.

Anyhow, I knew that the proposed solution is controversial. Since in the end you have to answer for the software, you have the final word.

The root project solution you proposed initially is definitely a good enhancement and will also make the description how to configure spotless easier. Code-wise it should be a one-liner, since the tests can remain as they are. Rest is documentation. Do you implement it, or shall I?

@nedtwigg
Copy link
Member

nedtwigg commented Jul 4, 2017

I agree with you on 2, but I think 1 isn't that rare - e.g. a CI environment that doesn't have access to the public internet.

If you build it, I'd be happy to turn the release crank.

@fvgh
Copy link
Member

fvgh commented Jul 4, 2017

Sorry Ned, I am unsure now what your final word is.
In your previous comment you stated that security concerns should not block for my proposal.
And you mentioned CI.
My experience with CI was actually the key point why I think my proposal is not a hack.
My proxy config looks like this:

allprojects {
	buildscript {
	    repositories {
		maven {
			url "http://<ip>:<port>/apache-archiva/repository/internal/"
		}
	    }
	}		
	repositories {
		maven {
			url "http://<ip>:<port>/apache-archiva/repository/internal/"
		}
	}
}

This is in my opinion how gradle wants a proxy to be configured.
If the proxy can can not resolve the extensions and direct access of Maven Central is denied, than you get an error like you do now. I had the problem that my proxy forwards request to Maven Central. So when #99 was solved, I needed no changes in my build scripts. But when I committed the JUnit changes, JUnit Travis failed. This would not have happen with my proposed solution.
When I said that disallowing access to all Maven Central versions (via proxy or not), I meant 'rare' in the sense that it only affect less than 5% of the users. 95% of the users would be able just to use spotless without any further configuration, regardless whether they use multi-project, or configured spotless in a dedicated gradle file.
Just let me now what the final solution shall be.

@nedtwigg
Copy link
Member

nedtwigg commented Jul 4, 2017

Sorry - my final word is that I do not want to add mavenCentral automatically to a user's configuration.

If you want to build the rootProject based workaround, then I'll be happy to release it quickly. But by no means are you obligated to build it :)

@praveenkumarc86
Copy link

@nedtwigg i am running it in multiple project. i have added the subprojects block in my rootProject. But still facing the below issue.

You probably need to add a repository containing the '[com.google.googlejavaformat:google-java-format:1.5]' artifact in the 'build.gradle' of your root project.
E.g.: 'buildscript { repositories { mavenCentral() }}'
Note that included buildscripts (using 'apply from') do not share their buildscript repositories with the underlying project.
You have to specify the missing repository explicitly in the buildscript of the root project.

@nedtwigg
Copy link
Member

nedtwigg commented Dec 17, 2018

Can you point us to your buildscript? You might need allprojects block rather than subprojects.

@eirnym
Copy link
Contributor

eirnym commented Oct 23, 2023

The same is happening when using dependencyResolutionManagement, which is another legal way to provide list of repositories without duplicating the block for each module.

example:

@Suppress("UnstableApiUsage")
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
    repositories {
        google().content {
            includeGroup("com.android")
            includeGroup("android.arch.lifecycle")
            includeGroup("android.arch.core")
            includeGroupByRegex("com\\.android\\..*")
            includeGroupByRegex("com\\.google\\..*")
            includeGroupByRegex("androidx\\..*")
        }
        mavenCentral()
    }
    versionCatalogs {
        create("agp") {
            from(files("gradle/agp.dependencies.toml"))
        }
        create("libs") {
            from(files("gradle/libs.dependencies.toml"))
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants