grails dependency resolution - java

My Grails project depends on an intenal library Commons.jar which is built with Maven. In BuildConfig.groovy I have configured it to look for this dependency first in the local Maven repository, then in the company-wide repository.
repositories {
// Read the location of the local Maven repository from $M2_REPO
mavenLocal System.getenv("M2_REPO")
mavenRepo "http://build.mycompany.com/wtp_repository"
}
plugins {
build 'org.grails.plugins:spring-security-core:1.0.1'
}
dependencies {
compile ('com.mycompany:Commons:1.0.0-SNAPSHOT')
}
When I build Common/jar (using mvn deploy), it is stored first in mavenLocal, then copied to mavenRepo. However, when I build the Grails app, it looks for the JAR in the following locations:
Ivy cache (defaults to ~/.ivy2/cache)
mavenLocal (defined by $M2_REPO)
mavenRepo (http://build.mycompany.com/wtp_repository)
So the Grails app is constantly picking up an old version of the JAR from the Ivy cache, which is never updated when the Commons project is built.
I guess I could fix this problem if I knew how to:
Prevent Grails for looking for dependencies in the Ivy cache (though I guess disabling the cache might slow down my builds considerably)
Ensure that the Ivy cache is also updated when I build Commons
However, it seems that anyone else that references SNAPSHOT artifacts of Maven projects should also have this problem, so perhaps I'm missing something?
Thanks!

I guess this discussion is related to the problem you have and possibly suggests some workaround/solution.

Related

Local Maven Repository issue with multiple jars

I have local Maven repository in C:\Users\<User_Name>\.m2 directory. After getting "java.lang.NoSuchMethodError..." exception and navigating problem on the web, I see this page mentioning to remove unused jar version(s) from local repository.
My questions are:
1. When I look at C:\Users\<User_Name>\.m2\repository\org\mockito\mockito-core folder, there are 52 different version folder. I think it is similar for other jar libraries. So, should we clean unused jars periodically? Or should we keep unused versions of a jar library?
2. If I just have 3.0.0 version of mockito-core in my pom.xml, how the app use or mix another version(s) in the local repository? Normally, if I just a single mockito-core dependency in my pom.xml, may there be any problem as mentioned on that page (solving the problem after removing other jar version)?
1)
You do not need to "clean unused jars" from your local maven repo manually. How do you want to decide which jar, which version is unused? Maybe your next project will use the jar that you want to delete. Who knows.
If you have enough disk space then you can leave your local maven repo directory untouched for years. If this directory grows too big, then I suggest you delete the complete .m2 folder. Then the next time when you build a project, Maven will download automatically all dependencies that your project needs.
There is only one use-case when deleting your local maven repo can cause a headache: if you have installed some custom jars manually.
2)
It is highly possible that the different dependency versions that you see in your local Maven repo directory come from different projects that you built earlier.
Anyway, you can display your effective pon with the Apache Maven Help Plugin.

Compilation error occurs if jars are added manually in Intellij

I am using Maven in my project, and for some reasons, some additional jars should be added manually (I have followed the step like Correct way to add external jars (lib/*.jar) to an IntelliJ IDEA project).
The package can be imported successfully. However, the compilation error happens, which indicates the package does not exist and cannot find the symbol of the used object.
I have tried the following tips but it remain unchanged:
Invalid caches / restarts
reimport
delete .idea file and .iml file
The scenario is quit similar to this one : https://intellij-support.jetbrains.com/hc/en-us/community/posts/206821195--beginner-question-including-external-jar-compile-error.
Please see the following sample images. It may run successfully but cannot be compiled well.
The reason is that when you add a library manually via IntelliJ, only IntelliJ knows about them and when you compile your code using Maven, it can't be find by Maven because Maven only searches for dependencies you defined in pom.xml.
You should install your libraries in your (at least) local maven repository and add them as a normal dependency in your pom.xml. Then you don't need to add them manually in IntelliJ.
You should follow the steps mentioned at Guide to installing 3rd party JARs
Update:
Also you should note that if you're working as a team, you should install this on the local maven repository of all developers (which is not practical). The best solution is to install a Maven repository (e.g. Nexus, Artifactory or Archiva) in a server on your local network and upload your private jar files on those servers. Then all developers can define the address of the local Maven repository server in their local Maven settings and use artifacts/libraries from that servers. Plus it works as a local cache/proxy to fetch any Maven artifacts and prevents unnecessary calls to public maven repositories.

Grief with Gradle and Maven repository for Android builds

I have been having endless grief with Gradle for Android builds after I had to format my Macbook Pro for some stupid corporate domain migration. I have been using Gradle (both off the command line and with Android Studio) to build my projects for over an year now, and never had problems till the fresh install. I spent countless hours over the weekend trying to fix this, but with no luck, and I'm literally on the verge of tearing my hair out! Here is what I'm stuck with:
Gradle builds have slowed to a crawl
I have a multi-project (or multi-module in Android terms) project which used to take around 2 minutes for a clean build - plus uploading archives to the (local) Maven repository. Now,the Gradle configuration phase takes around 8 minutes! Nothing has changed, for after the fresh setup on the Mac, I just took a pull of the sources from the Github repo, and I'm building using the gradle wrapper (as before) which uses version 2.2.1. Not sure if this matters, but the Gradle version on my machine is 2.6. I use Maven - not for builds, but for the local M2 repository, and the Maven version is 3.3.3. Both Maven and Gradle were installed using Homebrew. The Gradle runtimes are the same whether of the command line or using Android Studio. I'm using Android Studio version 1.4-beta4. Here are the things I have set up:
I have set up the Maven settings.xml to point the local Maven repository to the default location `${user.home}/.m2/repository
I have set up Google repository using Android Studio and the Support repository (my project needs Play services and the support library)
We need to upload the archives to the corporate Maven repository on our build servers; to sidestep this, I use the gradle.properties to define the repository URL to be the local M2 repository that's set up in the Maven settings
The project defines Android build tools version 1.1.0, and while this is an older version, I tried with the latest 1.3.1 with no luck on the build times
Possibly related: my Mac Pro uses a good ol' HDD, not the newer solid-state storage. While that can impact build times, the disk was not updated during the format, and also, I presume that it shouldn't result in such multiple orders of magnitude impact
Failure in resolving artifacts from local M2 repo
The primary project that I work on is a library, and we have test clients that we use to verify functionality. The library and test clients are maintained as separate projects in the Github repo. To not have to make any changes in my local development setup, I prefer to deploy the artifacts from my library to my local M2 repo, and then have the test client define and resolve the dependency locally. I accomplish this using the global gradle.properties to override the repository URL (point it to the local M2 repo). This worked just fine till the disk format, but is broken since. Gradle is never able to resolve the artifacts, but I can see them in the local M2 repo. I have googled high and low (on Gradle forums, here on SO), but cannot seem to figure out what I'm missing or doing wrongly. As a work-around, I added the test client as a module to the library project, and am building it as a single multi-module project. BTW, even with this, I still run into the slow Gradle build times problem that I mentioned above.
Can someone help me out?
so there are a few Problems you got to adress:
1. gradle is not resolving the artefacts in the local repository
- maybe it corrupted during the formating (Setup a test Project using maven for
its build only, specify some existing dependencies if you want to verify).
A fresh setup of the repo could resolve this.
2. gradle build is slow
Well, without further Information hard to troubleshoot. Did you refresh your dependencies, clean up the Cache, have enough free disk space in the GRADLE_USER_HOME?
I figured it out. There's one little bit I'm still not able to grok, but that aside here is what was wrong:
Slow gradle builds
The project's build.gradle file had declared a dependency on our corporate SCM Maven repository. I replicate whatever dependencies my project actually needs in the local M2 repo. Once I replaced this with a file URL pointing to the local M2 repo, Gradle build times dropped to the earlier 30-40 seconds. The part I'm still confused about is that even with the remote repo, Gradle should have downloaded the artifacts once and cached them in the Gradle cache. Still need to figure out why it's not doing that.
Failure in resolving artifacts from local M2 repo
This was a bad error on my part. In my gradle.properties I'd listed the SNAPSHOT_REPOSITORY_URL override as /Users/me/.m2/repository (with me replaced with the username). I missed the file:// prefix here. I'm somewhat surprised that Gradle didn't call it out, and instead deployed the artifacts at the directory pointed by /Users/me/.m2/repository, but may be I don't understand how this works so well. Once I added the file:// prefix, all the test project builds worked like a charm!

Install Library and Its Dependencies From Maven Repository Into Internal Repository

Question
I have an internal maven repository in a shared folder say s:\mvnrepo – it's just a convention for a directory layout after all. Now I want to install a library com.example.lib:lib:1.0.0 and its dependencies from another external maven repository into s:\mvnrepo with the hypothetical command
mvn installlib com.example.lib:lib:1.0.0 -Dinto=file:///s:/mvnrepo
That would be a dream! Is such a thing possible?
(I don't have high hopes seeing as everything maven related is always so unapproachable and complicated...)
Supplemental Information
Now, I know there are maven repository management systems like Nexus but I really do think my use case should not require them. I also know about the deploy-file goal but it doesn't install transitive dependencies into the specified repository.
I also thought about simply creating a dummy project that has the specific library listed in its pom.xml. Then just execute mvn install -Dinto=file:///s:/mvnrepo. The problem is that the install goal apparently does not have an option to specify the repository directory (i.e. -Dinto is purely hypothetical).
I found out that it is possible to download a library and all its dependencies with Intellij. That's great but Intellij really only downloads the jars and does not create a maven compatible directory structure (i.e. there are no poms downloaded nor are the jars in a group subfolder etc.).
Background information
For work we want to have an internal maven repository such that it is possible to build an application on a freshly installed server that does not have an internet connection while still being able to specifiy dependencies in the gradle file as if we would use an external maven repository like jcenter (resp. bintray). So the gradle file we use would look something like this:
repositories {
// jcenter() // we don't want that
mavenUrl 'file:///s:/mvnrepo'
}
dependencies {
compile 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0'
}
Now, I downloaded the sdkmanager plugin jar and its pom file from mvnrepository.com and used something like
mvn deploy:deploy-file -Dfile=sdkmanager.jar -Dpom=sdkmanager.pom -Durl=file:///s:/mvnrepo
All fine and dandy, the sdkmanager plugin is installed into s:\mvnrepo with the correct directory layout and gradle even picks it up! But gradle is not quite satisfied, you see. It demands the jarchivelib which is a dependency of com.jakewharton.sdkmanager:gradle-plugin:0.12.0 (see the page on mvnrepository.com where jarchivelib really is listed as a dependency of the sdkmanager plugin). Now, I could repeat the fun and download jarchivelib and its pom from mvnrepository.com, deploy it and so on. Thinking about it... that does not sound like fun at all! So now you see my concrete use case and maybe you could suggest an even better approach than what I seek for in my question.

Gradle - Install thirdparty dependencies into local ivy repository

I have a gradle project that has several thirdparty dependencies. At the moment, I have set mavenCentral() as a repository to enable me to download the JARs and compile/run etc.
However, I have a local ivy style repository on the filesystem that is being used as a local repository (to control the JARs that developers add, rather than just having mavenCentral available for all JARs to be updated whenever - much like artifactory, but with out the application server stuff).
So I have my PoC working with my dependencies, and I now want to install the currently downloaded set of thirdparty JARs into my local ivy repository, so I can remove the dependency on mavenCentral and all builds just use the local JARs - is there any easy way to install these cached JARs in my ivy repo using gradle?
I have tried using a copyDeps task as below, but that just copies the jars to a flat folder, but I want the ivy folder structure
task copyDeps(type: Copy) {
from configurations.runtime
into '/tmp/lib'
}
Is this possible/easy? (and no, assume I can't drastically change the setup/environment/process :)
There isn't any easy way to install third-party dependencies and all their metadata (module descriptors, checksums, etc.) into a Maven/Ivy repository using Gradle. It's something you'd have to script on your own. If you go from a Maven to an Ivy repository, you'll also have to convert pom.xml's into ivy.xml's etc.
PS: Don't use a file-based Ivy repository. Artifactory is a much better choice, and it's free and easy to set up. I think it's even able to convert pom.xml's into ivy.xml's (but first reconsider if you actually need an Ivy repository).

Categories

Resources