Dependency from an arbitrary URL (again)

Is it possible to declare a dependency on a local module definition and add an artifact fetched from an external URL? I found a reference that this used to be possible here –

http://gradle.1045684.n5.nabble.com/Dependency-from-an-arbitrary-URL-td1433384.html

But this doesn’t work for me (complains about unresolved dependency, never tries to fetch it):

myconfiguration module(‘foo:bar:1.4’) {

artifact {

name = ‘foo’

extension = ‘jar’

type = ‘jar’

url = ‘http://targethost/foo.jar

}

}

I can’t find any mention of ‘artifact.url’ in the Gradle docs or tests. It might be a leftover from the time when Gradle used Ivy for dependency resolution. I can’t get it to work myself, but then I only tried with a Maven repository.

There are plans to make URL dependencies a first-class feature, but it hasn’t happened yet.

The URL is definitely part of the class – http://www.gradle.org/docs/current/groovydoc/org/gradle/api/artifacts/DependencyArtifact.html

and it is definitely picked up from the definition and is validated (throws an exception on invalid URLs). But it doesn’t seem like it can be used to enforce an URL fetch anymore.

I didn’t mean to say that the property is no longer part of the interface/class.

Ok, thanks Peter. Is there a way to fetch a dependency dynamically if it’s not in any public repository (ivy or maven)? I don’t want to keep it with the sources. I know I could organize a (fake or real) ivy repository somewhere but I’m interested if there’s a way to do it by pointing at a specific URL and saying something along the lines of “fetch this JAR and use it as a dependency”.

You’ll have to roll your own solution (e.g. leveraging Groovy’s ‘URL.bytes’), but I’m not aware of a way to get the artifact into Gradle’s dependency cache.

There might be a workaround by declaring your remote location as an ‘ivy’ repository. If Gradle can’t find the ‘ivy.xml’ file, it will then look for a ‘jar’ file matching the artifact pattern. If this jar file is found, it’s treated like a fully-fledged ‘ivy module’ with no dependencies.

No guarantees, but you may be able to do this by declaring a repository with a pattern like:

dependencies {
  myconfiguration "anything:foo:1.4"
}
repositories {
  ivy {
    url "http://targethost"
    layout 'pattern' , {
        ivy '[module]-ivy.xml'
        artifact '[module](.[ext])'
    }
  }
}

If it’s not working, check out the ‘–debug’ output to see what actual URL is being requested. The resolver will first look for an ivy file using the ‘ivy’ pattern, and failing that it will check for an artifact file using the ‘artifact’ pattern. If the artifact is found, it should be used like any other remote dependency.

You could configure a similar scenario using the ‘artifactPattern’ property of an ivy repository.

Thanks Daz. I was thinking about creating a fake ivy repository but what scared me a bit was that then it installs the artifact in a local cache and this could conflict with real ivy deps in the future. On the other hand – I could name the artefact so that it’s something really unique so this is an option. Thanks!

The ‘group’ value you assign to the module will also be taken into account for caching. So where I’ve put ‘anything’ you can put a value that is likely not to clash with any other modules.

The cache is also content aware. That is, it does not consider two artifacts with the same identifiers (e.g. name, group) to be the same. They might be the same, and in that case Gradle can do some optimisations, but Gradle always uses checksums as the authoritative identifier.

This means that there is no way you can pollute your cache by doing what you’re doing.