51

For some reason my offshore team is not able to Download the artifacts(Dependencies) from my clients Artifactory which is our Organizations dependency repository."Refresh Dependencies" triggers nothing and gives TIME OUT EXCEPTION. I see the that my "Gradle Dependencies" are downloaded to the location "D:/C813507/Gradle/gradle-1.11/bin/caches/modules-2/files-2.1/". Can i zip this folder and send over to them ? How do they implement something in gradle that points to their local directory. My build gradle has the following line. How to point the URL to local directory in Windows OS

repositories {
         maven {
            url 'http://artifactory.myorg.com:8081/artifactory/plugins-release'
        }

}
Vinodh Thiagarajan
  • 758
  • 3
  • 9
  • 19

7 Answers7

54

Instead of configuring flatDir repository, you can declare a local maven repository as following:

repositories {
   maven {
       url 'file://D:/path/to/local/directory'
   }
}

As @Peter Niederwieser mentioned, flatDir repository doesn't support transitive dependency resolution. maven local repository does.

Alex Lipov
  • 13,503
  • 5
  • 64
  • 87
  • 2
    This will not work across different environments (specifically on the CI server) and breaks the principle "the build process should be same everywhere" – user3118604 Nov 07 '17 at 09:21
  • 18
    True. However, OP explicitly stated that he's looking for **local directory** solution, and therefore your comment is irrelevant in this context. – Alex Lipov Nov 07 '17 at 09:30
  • Can the gradle cache be converted into local maven repository ? – Subra M Jul 29 '19 at 20:27
  • 1
    @SubraM I believe it's worth a separate question, though the workarounds provided here might answer your needs: https://discuss.gradle.org/t/need-a-gradle-task-to-copy-all-dependencies-to-a-local-maven-repo/13397 – Alex Lipov Jul 30 '19 at 08:01
  • You can also either supply this repo via init.gradle, or have some conditional logic in your build to only use the local repo if property 'offshore' is true, or something like that. – Cinderhaze Oct 03 '19 at 17:06
  • How do I refer to the dependency when using this trick? Nothing I try seems to work. – BlueRaja - Danny Pflughoeft Dec 01 '21 at 02:20
  • @BlueRaja-DannyPflughoeft In exactly the same way you declare other dependencies, i.e. `implementation 'org.apache.httpcomponents:httpclient:4.5.5'`. – Alex Lipov Dec 01 '21 at 07:03
  • 4
    @user3118604 I needed a group of plugin artifacts which relate to each other with dependencies, so flatDir wasn't an option. I put the group of plugins in my project and refered to it via `maven(url = uri("file://${projectDir}/3rdParty/"))`. The `${projectDir}` making it system independent. – Jan Jul 26 '22 at 16:10
53

If you can't give access to your offshore team, you can copy all dependencies jar that needed to a single directory, and then use flatDir repository.

repositories {
   flatDir {
       dirs 'D:/path/to/local/directory'
   }
}


dependencies {
   compile name: 'name-of-jar'
}

Another way without using flatDir repository is:

dependencies {
    compile files('/path/to/dir/something_local.jar')
}
dieend
  • 2,231
  • 1
  • 24
  • 29
  • 9
    Note that with a flatDir repository, there is no transitive dependency resolution. It would be better to investigate and fix the original problem. – Peter Niederwieser Sep 22 '14 at 08:26
  • I have question regarding the build dependencies in the gradle.build for the local repository (i.e. using the local directory) dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') } Does it solve the dependencies in the libs directory only or it is resolves the dependencies on all the subfolders of lib directory. If it does not resolve the dependencies of subfolders/subdirectories, how to resolve the dependencies? note: Our project depends on lot of jars files(instead of giving the full file name for each jars/libs), so wants to know any alternate way. – mgr Jun 27 '16 at 16:39
  • @mallikgm I think you should ask it in a new question to give clearer context. I am guessing fileTree should works with sub dir. But I haven't tried it – dieend Jun 28 '16 at 07:29
  • I have asked a new question http://stackoverflow.com/questions/38059123/gradle-repository-points-to-local-directory-with-multiple-libs – mgr Jun 28 '16 at 10:15
19

Using flatDir like below is one option :

repositories {
   flatDir {
       dirs 'D:/path/to/local/directory'
   }
}

This works. But if there is mavenCentral() or other maven repositories that contain the same JAR, priority will be given to maven repository over flatDir.

Excerpt from Gradle Documentation : https://docs.gradle.org/current/userguide/repository_types.html

Gradle will dynamically generate a module descriptor (without any dependency information) based on the presence of artifacts. However, as Gradle prefers to use modules whose descriptor has been created from real meta-data rather than being generated, flat directory repositories cannot be used to override artifacts with real meta-data from other repositories. For example, if Gradle finds only jmxri-1.2.1.jar in a flat directory repository, but jmxri-1.2.1.pom in another repository that supports meta-data, it will use the second repository to provide the module.

So flatDir is not good. We should use local maven repository like mentioned in the second answer. But there are couple of issues with the second answer

  1. Not portable
  2. If the artifact is also present in the global repo's, it is unclear from where will it be picked from.

We can solve these issues by using a solution like below :

  1. Create a folder called libs in the project directory
  2. Copy your artifacts into this libs directory (if you are using git or any other scm's, make sure to distribute this libs fodler so that others can just gradle build without any issues)
  3. Declare a maven repo to your libs directory and call mavenLocal() before listing any other repos. This step is very important to make sure that the jar is picked from your local directory rather than from the other global repositories
repositories {
   maven {
       url uri("${projectDir}/libs")
   }

   mavenLocal()
   <All your Repos here>
   mavenCentral()
}

This way you can be sure that even if the JAR is present in other repo's it will only be picked from your local directory and the solution is also portable.

Sandeep
  • 18,356
  • 16
  • 68
  • 108
  • I followed your solution, it means I copied all folders of gradle cache [.gradle\caches\modules-2\files-2.1] into my local repository and after that I deleted the cache but I got an error during syncing gradle as [Could not resolve all artifacts for configuration ':classpath'. > Could not resolve com.android.tools.build:gradle:3.5.2.] this is my gradle: repositories { maven { url uri("./repository") } mavenLocal() jcenter() google() mavenCentral() maven { url 'https://maven.fabric.io/public' }} – Mojtaba Dec 03 '19 at 15:10
  • @Mojtaba You still facing the issue? – Sandeep Dec 29 '19 at 03:19
  • Yes, I still have the issue – Mojtaba Dec 31 '19 at 07:03
  • 1
    I realize this is an old issue, but maybe this will help someone anyway. The gradle caches don't work directly as a repository - the paths need to be converted to maven format first. This script for example does that: [link](https://github.com/sinsongdev/gradle-cash-to-maven-repo) – Pauli Kettunen Sep 20 '21 at 12:21
1

Expanding on Alex Lipov's answer, and this goes beyond the original question in detail, but for anyone that asked themselves the question of the title:

So you want to use Gradle and its neat dependency management (via Maven), maybe publish your project A to some local repository, and then in another project B, pull it in. Here a flatDir is certainly not what you want, because any dependencies from project A are not going to be known to project B.

What you want is a local maven repository. This does not require setting up a local server of any kind. It really is just another local directory, where your project A stores not just the jar, but also some extra files, e.g. for its dependencies.

Pointing Gradle to a local directory can be done like this:

// build.gradle.kts syntax:
repositories {
    maven(uri("C:\\your\\path\\.m2\\repository"))
}

You may be tempted to use mavenLocal(), since this is the default local maven repository (under your user profile, in .m2), but if want your files to reside within your directory of choice, mavenLocal is not the way. You may also be tempted to use the maven.repo.local system property to change your default local maven repository to your directory of choice, but this will dump contents of any other local projects you may have into your directory of choice.

Now, if you pull dependencies from any maven directory, you cannot simply dump your jars there, like you could with flatDir. So here's how to do it using Gradle.

How to put files into a local maven repository

First you need the plugin to enable maven publications

plugins {
    `maven-publish`
}

Then in the publishing extension in your build file, you can specify your repository again, similar to before

publishing {
    repositories {
        maven(uri("C:\\your\\path\\.m2\\repository")) {
            name = "MyPath"
        }
    }

Unlike before, we also added a name to the repository. This is because the maven plugin will now create tasks for it, e.g. publishAllPublicationsToMyPathRepository.

If you already have a maven publication for your project, and were only looking for a way to do so locally, you are done here. If not, then next, still in the publishing scope, here is an example

    publications {
        create<MavenPublication>(project.name) {
            groupId = group.toString()
            artifactId = project.name
            version = project.version.toString()

            from(components["java"])
        }
    }
}

This will create tasks named publish<project.name>PublicationTo..., that will put your project A into the local directory, in the correct format. If you examine the directory structure created, you will find groupId, artifactId and version, then the jar along with metadata files.

Should you use this

As others have pointed out, local repositories break the build anywhere principle. However, if the alternative was to use flatDir, then this is probably preferable, and more along the lines of how Gradle should be used.

Maven repositories are expected to be immutable. You should generally not publish one version, then make changes to code and publish the same version again. If you are using a snapshot version (e.g. your version string ending in -SNAPSHOT), the maven plugin will automatically create a unique publication every time you run publish. This may create a lot of files, so beware of this.

When using mavenLocal for publishing, the publications will have a maven-metadata-local.xml instead of maven-metadata.xml. They will not contain checksum files, and they will not create unique publications, even for snapshot versions. I tried using mavenLocal { url = uri("...") }, but this also does also not result in true local publishing (Gradle 7.2). If you really want the local publishing mode, a copy task grabbing it from the standard maven local directory may be the only way.

Caranown
  • 173
  • 9
0

Open a file in the directory with a browser, and then copy the path.

 maven { url = "file:///C:/lib/repo/"}
Ag2S
  • 31
  • 1
  • 3
0

Repeating other answers and providing one more detail, in Gradle multi-project, put the block into top level build.gradle and push down to all projects. Name is helpful if you are inspecting reposit

   allprojects {
      repositories {
       flatDir {
           name 'my local dir'
           dirs 'c:/users/to/local/directory'
       }
      }
   }
Vortex
  • 789
  • 12
  • 21
0

I using linux (Ubuntu 20.04) Android SDK 31. This work for my.

maven {
        url = "/home/user/.m2/repository/"
    }