How to define repositories for all subprojects in Gradle - gradle

I am writing Gradle scripts to build a lot of projects. They are using the same repositories so I would like to define repositories for all of my sub-projects instead of defining in each of them.
So I try to move the repositories definition from the build.gradle in an individual project into the build.gradle in their parent folder.
subprojects{
repositories{
mavenCentral()
flatDir{
name 'uploadRepository'
dirs '../../sharedlib'
}
}
}
However, the sub-projects can't find the repository definition at all. Moving other configurations in subprojects closure work. I've tried dependencies and properties configuration. They all work with no problem. I don't know why repositories work differently.
When Googling, I can't find any example of putting repositories inside subprojects, I suspect I am doing it the wrong way. Please tell me what's wrong.
Thanks!

I finally figured out what the problem was.
Originally, I missed the settings.gradle in the parent folder. (I don't know why dependencies configuration works even without this file)
After I put that in, the sub-projects could find the repositories, but the dependencies and an one property (sourceCompatibility=1.5) I defined in the parent project no longer works.
I have to move the apply plugin:'war' from the subproject's build.gradle to the parent's subprojects{...}
I figure that's because the dependencies and sourceCompatibility are things provided by the plugin. And somehow Gradle doesn't look into the subproject's script to find the plugin first.

Your repository declarations look fine, except that an upload repository isn't declared in the project.repositories block but inside the upload task (e.g. uploadArchives). The Gradle User Guide has the details.

Related

how to make a gradle build using only the local dependencies?

I am trying to make a gradle build.
The repositories are now unaccessible (due my internet connection).
But I had made a build with those libraries already and are compiled at my computer locally.
I want to make a gradle build without going to the internet and look for them, instead, want to fetch them locally.
I have tried adding this:
buildscript {
repositories {
mavenLocal()
...
But is not really working, any idea how to do it? or through the command line?
There are 2 places where you can declare your repositories, each of them affects different things in the build.
The one you mentioned, within the buildscript only states that for this buildscript (build.gradle), resolve the dependencies (practically classes) from the local maven repository.
If you want to resolve the dependencies which you declared under the dependencies block, you have to go straight with
repositories {
mavenLocal()
}

How can I share build config between two build.gradle.kts files?

I have two projects (in a single git repository) that should have the same
repository {
}
section in their build.gradle.kts, but otherwise are completely unrelated.
Can I factor this common part out and include it in each respective build.gradle.kts? How?
Update In the 0.11.0 release, applyFrom(uri) was removed.
You should now instead use:
apply {
from("dir/myfile.gradle")
}
Old answer
With Groovy build scripts you can do something like apply from: 'dir/myfile.gradle' where dir/myfile.gradle is a file containing your shared repositories block.
In a similar fashion with Gradle Script Kotlin (at least with 0.4.1), you can use the applyFrom(script: Any) method.
build.gradle.kts
applyFrom("dir/myfile.gradle")
If you need to apply it from a subproject you could do something like:
applyFrom("${rootProject.rootDir}/dir/myfile.gradle")
No idea if it works with kotlin however you can try equivalent from plain gradle:
lol.gradle
apply plugin: 'java'
repositories {
mavenCentral()
}
build.gradle
apply from: 'lol.gradle'
Above works fine. Mind that lol.gradle has java plugin applied - it adds context where repositories is present hence can be applied.
We use an init script bundled in a custom gradle distribution to apply our corporate Nexus repository to every gradle project. It's worth considering if you have a lot of projects.
I encountered a similar problem when common config is replicated in each and every project. Solved it by a custom gradle distribution with the common settings defined in init script.
Created a gradle plugin for preparing such custom distributions - custom-gradle-dist. It works perfectly for my projects, e.g. a build.gradle for a library project looks like this (this is a complete file, all repository, plugin, common dependencies etc are defined in the custom init script):
dependencies {
compile 'org.springframework.kafka:spring-kafka'
}

Gradle include jar produced by another project in war

Currently I have two projects with gradle build.gradle. The first is going to create a fat jar file, which I would like to include in a war file. I thought compiling it would be enough, but it doesn't seem to be ending up in the /lib directory of my war file. Anyone have thoughts I am quite new to gradle.
dependencies {
compile project(':JarProject')
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile 'org.apache.tomcat:tomcat-jsp-api:7.0.55'
}
war {
archiveName 'WarProject.war'
from 'JarProject/build/libs'
webXml = file('src/web.xml')
}
Does the second project war need to be in providedRuntime? Or should I publish the jar from the other project in the local maven repo and include it that way?
The War task essentially behaves like a CopyTask with regards to stuff it packs in the war, so the documentation on working with files is useful. In essence, I think you need something like (untested):
from fileTree('JarProject/build/libs') {
into("lib")
}
That being said, using mavenLocal() and publishing there also works, but it can lead to unexpected results when the war includes some old version from local, picking up the jar explicitly from the file system like above is better.
I think the elegant solution would be to use multi project builds and project level dependencies. You would have the two builds as separate projects of the same Gradle build and add the "jar project" as a regular compile dependency.
How have you declared the dependency? I assume you have a multi-project build with subprojects A and B, both using the War plugin. I made an experiment using Gradle 2.4 and if I declare B/build.gradle like this:
apply plugin: 'war'
dependencies {
compile project(':A')
}
then B.war contains WEB-INF/lib/A.jar. If you correctly follow conventions of Gradle War plugin (place web resources in A/src/main/webapp/ and code-related resources in A/src/main/resources/), then A.jar should contain what you want.
see this

Gradle artifactory plugin saying "Cannot cast object 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention'..."

Here's the configuration to get the artifactory plugin:
buildscript {
repositories {
mavenCentral()
maven { url 'http://jcenter.bintray.com' }
}
dependencies {
classpath group:'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '3.0.1'
}
}
apply plugin:'com.jfrog.artifactory'
apply plugin:'ivy-publish'
...some publish spec stuff...
I run gradle (2.3) and I get:
> Failed to apply plugin [id 'com.jfrog.artifactory']
> Cannot cast object 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention#6b6c7be4' with class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention' to class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention'
Certainly looks like a classpath issue, but I literally have this project and a sibling project using this same set of gradle/artifactory configurations and one works and the other does not. Both are part of the same top level project. Same JDK (1.8.0_20). Same Gradle. Same everything.
I'm baffled...
The problem was that when I added the various bits to the sibling project that meant I had two projects defining the buildscript {} section.
buildscript {
...
dependencies {
classpath group:'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '3.0.1'
}
}
Apparently that caused two different versions of the dependency to exist in the classpath, hence the error.
The solution was to move the buildscript bit into the master project so those dependencies are only defined once:
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath group:'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '3.0.1'
}
}
Here's another potential cause. All of this looks to be a problem with rival classloaders defining the class. The full qualified classes include the loader. so, load A foo.bar is not loader B foo.bar and crossing that divide is a complex dance requiring interfaces and careful definition.
So, when using the Jenkins artifactory plugin to build your gradle project with the gradle artifactory plugin, you must add the usesPlugin or jenkins plugin will generate an init script which adds the gradle plugin on to a class loader.
def server = Artifactory.server "artifactory"
def rtGradle = Artifactory.newGradleBuild()
rtGradle.usesPlugin = true // Artifactory plugin already defined in build script
...
My problem was, desktop build OK, jenkins build shows this post's problem
I was getting a similar exception when building with Jenkins. For me the conflict was with Jenkin's version and the version in the Build script:
To address this the Artifactory section of the build has a flag you can check specifying that you want to use the version from the gradle file:
This fixed my issue. Hope it helps.
I had a similar problem. Gradle seems to try to reach across and do some checking or evaluation across siblings. I have a top level settings.gradle with 10 or so subprojects.
The fix for me was to put the buildscript block and dependencies at the top level build.gradle and put it in each of the individual subprojects build.gradle files where needed.
My guess as to the reason this works is that the plugin gets loaded in the parent which will be a parent classloader, then each child project inherits that classloader such that the declaration in the lower child script uses that classloaders class and CCE does not occur. The problem is they are the same class, but not assignable since the different classloaders per subproject if nothing is declared at the top. This was Gradle 2.4, and using IntelliJ 14.
In case it helps someone, I got the same error, but for a different reason.
I had the following in my build.gradle:
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:+"
}
At some point the artifactory plugin updated itself from version 3.x to version 4.x while building, because no specific version was specified for the dependency. After it updated I got the error (Could not find any convention object of type ArtifactoryPluginConvention).
I guess the problem was that the rest of the configuration in my build script doesn't work with the new plugin version. Setting the dependency to use version 3.x fixed the problem for me:
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.+"
}
While the currently accepted answer correctly identifies the cause of this issue, the proposed solution doesn't work when you still need to be able to build individual subprojects (because then of course they no longer have access to the buildscript defined repositories and dependencies). The solution that worked for me was to have identical buildscript blocks in each of my subprojects, that seemed to be the key. Any variations would cause the original error.
I got the same exception thrown by bamboo:
'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention#18eb2827' with class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention' to class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention'
Since the bamboo Bamboo Artifactory Plugin by default looks for the gradle.propeties file in each sub-project module, it has to be provided there.
There is no need for publishing logic in the build.gradle file since the Bamboo Artifactory plugin will read the gradle.properties file for each module respectively, containing:
group=com.example
artifactId=your-project
version=1.0.0
The reason that I got the ArtifactoryPluginConvention exception thrown was that my configured build plan on Bamboo was misconfigured.
With misconfigured, the build ordered of the tasks was not correct. Have a look at your bamboo building tasks/preferably clone a Bamboo plan that is already working.

Adding jars to classpath using gradle

In gradle, is there a way to reference external jars. I have some external jars, sitting in another folder outside the project structure. Is there a way to add a reference to these jars in my build.gradle file, so that they are picked up during the compilation process?
Thanks
Edit:
I modified mu build.gradle with an allprojects task having the following 'sub-tasks(?)' as follows:
repositories{
flatDir name:'ExternalJars',dirs:'<path to the jars>'
dependencies{
compile: 'jarname:jarname:version'
}
}
This seems to make my build run just fine. Can someone shed some light on what exactly is happenning when I create the repository and specify the dependencies? - Thanks
The basic idea is that it looks for jar files in the root directory(s) you specified in flatDir that match [artifact]-[version].[ext] pattern.
Note: artifact group is ignored (so you can specify them as :jarname:version), and also all artifacts assumed to have no transitive dependencies.
By the way, another way to reference local jars is to create a local ivy repository. You'll need to use this if you want to declare transitive dependencies.

Resources